mirror of https://github.com/grpc/grpc-node.git
grpc-js: Make filter stack handle status in all code paths
This commit is contained in:
parent
2ca96a322f
commit
a99afaf5eb
|
|
@ -224,7 +224,8 @@ export class Http2CallStream implements Call {
|
||||||
/* Precondition: this.finalStatus !== null */
|
/* Precondition: this.finalStatus !== null */
|
||||||
if (!this.statusOutput) {
|
if (!this.statusOutput) {
|
||||||
this.statusOutput = true;
|
this.statusOutput = true;
|
||||||
this.listener!.onReceiveStatus(this.finalStatus!);
|
const filteredStatus = this.filterStack.receiveTrailers(this.finalStatus!);
|
||||||
|
this.listener!.onReceiveStatus(filteredStatus);
|
||||||
if (this.subchannel) {
|
if (this.subchannel) {
|
||||||
this.subchannel.callUnref();
|
this.subchannel.callUnref();
|
||||||
this.subchannel.removeDisconnectListener(this.disconnectListener);
|
this.subchannel.removeDisconnectListener(this.disconnectListener);
|
||||||
|
|
@ -353,14 +354,26 @@ export class Http2CallStream implements Call {
|
||||||
|
|
||||||
private handleTrailers(headers: http2.IncomingHttpHeaders) {
|
private handleTrailers(headers: http2.IncomingHttpHeaders) {
|
||||||
this.trace('received HTTP/2 trailing headers frame');
|
this.trace('received HTTP/2 trailing headers frame');
|
||||||
const code: Status = this.mappedStatusCode;
|
|
||||||
const details = '';
|
|
||||||
let metadata: Metadata;
|
let metadata: Metadata;
|
||||||
try {
|
try {
|
||||||
metadata = Metadata.fromHttp2Headers(headers);
|
metadata = Metadata.fromHttp2Headers(headers);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
metadata = new Metadata();
|
metadata = new Metadata();
|
||||||
}
|
}
|
||||||
|
const metadataMap = metadata.getMap();
|
||||||
|
let code: Status = this.mappedStatusCode;
|
||||||
|
if (code === Status.UNKNOWN && typeof metadataMap['grpc-status'] === 'string') {
|
||||||
|
const receivedStatus = Number(metadataMap['grpc-status']);
|
||||||
|
if (receivedStatus in Status) {
|
||||||
|
code = receivedStatus;
|
||||||
|
}
|
||||||
|
metadata.remove('grpc-status');
|
||||||
|
}
|
||||||
|
let details = '';
|
||||||
|
if (typeof metadataMap['grpc-message'] === 'string') {
|
||||||
|
details = decodeURI(metadataMap['grpc-message']);
|
||||||
|
metadata.remove('grpc-message');
|
||||||
|
}
|
||||||
const status: StatusObject = { code, details, metadata };
|
const status: StatusObject = { code, details, metadata };
|
||||||
let finalStatus;
|
let finalStatus;
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,6 @@ import { Status, LogVerbosity } from './constants';
|
||||||
import { FilterStackFactory } from './filter-stack';
|
import { FilterStackFactory } from './filter-stack';
|
||||||
import { CallCredentialsFilterFactory } from './call-credentials-filter';
|
import { CallCredentialsFilterFactory } from './call-credentials-filter';
|
||||||
import { DeadlineFilterFactory } from './deadline-filter';
|
import { DeadlineFilterFactory } from './deadline-filter';
|
||||||
import { MetadataStatusFilterFactory } from './metadata-status-filter';
|
|
||||||
import { CompressionFilterFactory } from './compression-filter';
|
import { CompressionFilterFactory } from './compression-filter';
|
||||||
import { getDefaultAuthority } from './resolver';
|
import { getDefaultAuthority } from './resolver';
|
||||||
import { LoadBalancingConfig } from './load-balancing-config';
|
import { LoadBalancingConfig } from './load-balancing-config';
|
||||||
|
|
@ -192,7 +191,6 @@ export class ChannelImplementation implements Channel {
|
||||||
this.filterStackFactory = new FilterStackFactory([
|
this.filterStackFactory = new FilterStackFactory([
|
||||||
new CallCredentialsFilterFactory(this),
|
new CallCredentialsFilterFactory(this),
|
||||||
new DeadlineFilterFactory(this),
|
new DeadlineFilterFactory(this),
|
||||||
new MetadataStatusFilterFactory(this),
|
|
||||||
new CompressionFilterFactory(this),
|
new CompressionFilterFactory(this),
|
||||||
]);
|
]);
|
||||||
// TODO(murgatroid99): Add more centralized handling of channel options
|
// TODO(murgatroid99): Add more centralized handling of channel options
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Call } from './call-stream';
|
import { Call, StatusObject } from './call-stream';
|
||||||
import { ConnectivityState, Channel } from './channel';
|
import { ConnectivityState, Channel } from './channel';
|
||||||
import { Status } from './constants';
|
import { Status } from './constants';
|
||||||
import { BaseFilter, Filter, FilterFactory } from './filter';
|
import { BaseFilter, Filter, FilterFactory } from './filter';
|
||||||
|
|
@ -82,6 +82,13 @@ export class DeadlineFilter extends BaseFilter implements Filter {
|
||||||
finalMetadata.set('grpc-timeout', timeoutString);
|
finalMetadata.set('grpc-timeout', timeoutString);
|
||||||
return finalMetadata;
|
return finalMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
receiveTrailers(status: StatusObject) {
|
||||||
|
if (this.timer) {
|
||||||
|
clearTimeout(this.timer);
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DeadlineFilterFactory implements FilterFactory<DeadlineFilter> {
|
export class DeadlineFilterFactory implements FilterFactory<DeadlineFilter> {
|
||||||
|
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright 2019 gRPC authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { Call } from './call-stream';
|
|
||||||
import { StatusObject } from './call-stream';
|
|
||||||
import { Channel } from './channel';
|
|
||||||
import { Status } from './constants';
|
|
||||||
import { BaseFilter, Filter, FilterFactory } from './filter';
|
|
||||||
|
|
||||||
export class MetadataStatusFilter extends BaseFilter implements Filter {
|
|
||||||
receiveTrailers(status: StatusObject): StatusObject {
|
|
||||||
// tslint:disable-next-line:prefer-const
|
|
||||||
let { code, details, metadata } = status;
|
|
||||||
if (code !== Status.UNKNOWN) {
|
|
||||||
// we already have a known status, so don't assign a new one.
|
|
||||||
return { code, details, metadata };
|
|
||||||
}
|
|
||||||
const metadataMap = metadata.getMap();
|
|
||||||
if (typeof metadataMap['grpc-status'] === 'string') {
|
|
||||||
const receivedCode = Number(metadataMap['grpc-status']);
|
|
||||||
if (receivedCode in Status) {
|
|
||||||
code = receivedCode;
|
|
||||||
}
|
|
||||||
metadata.remove('grpc-status');
|
|
||||||
}
|
|
||||||
if (typeof metadataMap['grpc-message'] === 'string') {
|
|
||||||
details = decodeURI(metadataMap['grpc-message'] as string);
|
|
||||||
metadata.remove('grpc-message');
|
|
||||||
}
|
|
||||||
return { code, details, metadata };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class MetadataStatusFilterFactory
|
|
||||||
implements FilterFactory<MetadataStatusFilter> {
|
|
||||||
constructor(private readonly channel: Channel) {}
|
|
||||||
createFilter(callStream: Call): MetadataStatusFilter {
|
|
||||||
return new MetadataStatusFilter();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue