mirror of https://github.com/grpc/grpc-node.git
Merge pull request #120 from kjin/grpc-js-core-work
grpc-js-core: compiler error and http2-facing fixes
This commit is contained in:
commit
e48ac4ee4e
|
@ -3,7 +3,7 @@ import {map, reduce} from 'lodash';
|
|||
import {Metadata} from './metadata';
|
||||
|
||||
export type CallMetadataGenerator =
|
||||
(options: Object, cb: (err: Error|null, metadata?: Metadata) => void) =>
|
||||
(options: {}, cb: (err: Error|null, metadata?: Metadata) => void) =>
|
||||
void;
|
||||
|
||||
/**
|
||||
|
@ -15,7 +15,7 @@ export interface CallCredentials {
|
|||
* Asynchronously generates a new Metadata object.
|
||||
* @param options Options used in generating the Metadata object.
|
||||
*/
|
||||
generateMetadata(options: Object): Promise<Metadata>;
|
||||
generateMetadata(options: {}): Promise<Metadata>;
|
||||
/**
|
||||
* Creates a new CallCredentials object from properties of both this and
|
||||
* another CallCredentials object. This object's metadata generator will be
|
||||
|
@ -28,7 +28,7 @@ export interface CallCredentials {
|
|||
class ComposedCallCredentials implements CallCredentials {
|
||||
constructor(private creds: CallCredentials[]) {}
|
||||
|
||||
async generateMetadata(options: Object): Promise<Metadata> {
|
||||
async generateMetadata(options: {}): Promise<Metadata> {
|
||||
let base: Metadata = new Metadata();
|
||||
let generated: Metadata[] = await Promise.all(
|
||||
map(this.creds, (cred) => cred.generateMetadata(options)));
|
||||
|
@ -46,7 +46,7 @@ class ComposedCallCredentials implements CallCredentials {
|
|||
class SingleCallCredentials implements CallCredentials {
|
||||
constructor(private metadataGenerator: CallMetadataGenerator) {}
|
||||
|
||||
async generateMetadata(options: Object): Promise<Metadata> {
|
||||
async generateMetadata(options: {}): Promise<Metadata> {
|
||||
return new Promise<Metadata>((resolve, reject) => {
|
||||
this.metadataGenerator(options, (err, metadata) => {
|
||||
if (metadata !== undefined) {
|
||||
|
@ -64,7 +64,7 @@ class SingleCallCredentials implements CallCredentials {
|
|||
}
|
||||
|
||||
class EmptyCallCredentials implements CallCredentials {
|
||||
async generateMetadata(options: Object): Promise<Metadata> {
|
||||
async generateMetadata(options: {}): Promise<Metadata> {
|
||||
return new Metadata();
|
||||
}
|
||||
|
||||
|
|
|
@ -182,9 +182,10 @@ export class Http2CallStream extends Duplex implements CallStream {
|
|||
this.cancelWithStatus(Status.UNKNOWN, error.message);
|
||||
});
|
||||
});
|
||||
stream.on('trailers', (headers) => {
|
||||
stream.on('trailers', (headers: http2.IncomingHttpHeaders) => {
|
||||
let code: Status = this.mappedStatusCode;
|
||||
if (headers.hasOwnProperty('grpc-status')) {
|
||||
let details = '';
|
||||
if (typeof headers['grpc-status'] === 'string') {
|
||||
let receivedCode = Number(headers['grpc-status']);
|
||||
if (receivedCode in Status) {
|
||||
code = receivedCode;
|
||||
|
@ -193,9 +194,8 @@ export class Http2CallStream extends Duplex implements CallStream {
|
|||
}
|
||||
delete headers['grpc-status'];
|
||||
}
|
||||
let details = '';
|
||||
if (headers.hasOwnProperty('grpc-message')) {
|
||||
details = decodeURI(headers['grpc-message']);
|
||||
if (typeof headers['grpc-message'] === 'string') {
|
||||
details = decodeURI(headers['grpc-message'] as string);
|
||||
}
|
||||
let metadata: Metadata;
|
||||
try {
|
||||
|
@ -301,7 +301,7 @@ export class Http2CallStream extends Duplex implements CallStream {
|
|||
}
|
||||
this.endCall({code: code, details: details, metadata: new Metadata()});
|
||||
});
|
||||
stream.on('error', () => {
|
||||
stream.on('error', (err: Error) => {
|
||||
this.endCall({
|
||||
code: Status.INTERNAL,
|
||||
details: 'Internal HTTP2 error',
|
||||
|
@ -325,7 +325,9 @@ export class Http2CallStream extends Duplex implements CallStream {
|
|||
|
||||
cancelWithStatus(status: Status, details: string): void {
|
||||
this.endCall({code: status, details: details, metadata: new Metadata()});
|
||||
if (this.http2Stream !== null) {
|
||||
// The http2 stream could already have been destroyed if cancelWithStatus
|
||||
// is called in response to an internal http2 error.
|
||||
if (this.http2Stream !== null && !this.http2Stream.destroyed) {
|
||||
/* TODO(murgatroid99): Determine if we want to send different RST_STREAM
|
||||
* codes based on the status code */
|
||||
this.http2Stream.rstWithCancel();
|
||||
|
|
|
@ -71,6 +71,7 @@ export interface Channel extends EventEmitter {
|
|||
}
|
||||
|
||||
export class Http2Channel extends EventEmitter implements Channel {
|
||||
private readonly authority: url.URL;
|
||||
private connectivityState: ConnectivityState = ConnectivityState.IDLE;
|
||||
/* For now, we have up to one subchannel, which will exist as long as we are
|
||||
* connecting or trying to connect */
|
||||
|
@ -134,9 +135,9 @@ export class Http2Channel extends EventEmitter implements Channel {
|
|||
let subChannel: http2.ClientHttp2Session;
|
||||
let secureContext = this.credentials.getSecureContext();
|
||||
if (secureContext === null) {
|
||||
subChannel = http2.connect(this.address);
|
||||
subChannel = http2.connect(this.authority);
|
||||
} else {
|
||||
subChannel = http2.connect(this.address, {secureContext});
|
||||
subChannel = http2.connect(this.authority, {secureContext});
|
||||
}
|
||||
this.subChannel = subChannel;
|
||||
let now = new Date();
|
||||
|
@ -165,14 +166,14 @@ export class Http2Channel extends EventEmitter implements Channel {
|
|||
}
|
||||
|
||||
constructor(
|
||||
private readonly address: url.URL,
|
||||
address: string,
|
||||
public readonly credentials: ChannelCredentials,
|
||||
private readonly options: ChannelOptions) {
|
||||
super();
|
||||
if (credentials.getSecureContext() === null) {
|
||||
address.protocol = 'http';
|
||||
this.authority = new url.URL(`http://${address}`);
|
||||
} else {
|
||||
address.protocol = 'https';
|
||||
this.authority = new url.URL(`https://${address}`);
|
||||
}
|
||||
this.filterStackFactory = new FilterStackFactory([
|
||||
new CompressionFilterFactory(this),
|
||||
|
@ -193,7 +194,7 @@ export class Http2Channel extends EventEmitter implements Channel {
|
|||
finalMetadata.then(
|
||||
(metadataValue) => {
|
||||
let headers = metadataValue.toHttp2Headers();
|
||||
headers[HTTP2_HEADER_AUTHORITY] = this.address.hostname;
|
||||
headers[HTTP2_HEADER_AUTHORITY] = this.authority.hostname;
|
||||
headers[HTTP2_HEADER_CONTENT_TYPE] = 'application/grpc';
|
||||
headers[HTTP2_HEADER_METHOD] = 'POST';
|
||||
headers[HTTP2_HEADER_PATH] = methodName;
|
||||
|
|
|
@ -24,7 +24,7 @@ export class Client {
|
|||
}
|
||||
// TODO(murgatroid99): Figure out how to get version number
|
||||
// options['grpc.primary_user_agent'] += 'grpc-node/' + version;
|
||||
this.channel = new Http2Channel(new URL(address), credentials, options);
|
||||
this.channel = new Http2Channel(address, credentials, options);
|
||||
}
|
||||
|
||||
close(): void {
|
||||
|
|
|
@ -166,6 +166,7 @@ export class Metadata {
|
|||
* Creates an OutgoingHttpHeaders object that can be used with the http2 API.
|
||||
*/
|
||||
toHttp2Headers(): http2.OutgoingHttpHeaders {
|
||||
// NOTE: Node <8.9 formats http2 headers incorrectly.
|
||||
const result: http2.OutgoingHttpHeaders = {};
|
||||
forOwn(this.internalRepr, (values, key) => {
|
||||
// We assume that the user's interaction with this object is limited to
|
||||
|
@ -194,7 +195,7 @@ export class Metadata {
|
|||
values.forEach((value) => {
|
||||
result.add(key, Buffer.from(value, 'base64'));
|
||||
});
|
||||
} else {
|
||||
} else if (values !== undefined) {
|
||||
result.add(key, Buffer.from(values, 'base64'));
|
||||
}
|
||||
} else {
|
||||
|
@ -202,7 +203,7 @@ export class Metadata {
|
|||
values.forEach((value) => {
|
||||
result.add(key, value);
|
||||
});
|
||||
} else {
|
||||
} else if (values !== undefined) {
|
||||
result.add(key, values);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue