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 */
|
||||
if (!this.statusOutput) {
|
||||
this.statusOutput = true;
|
||||
this.listener!.onReceiveStatus(this.finalStatus!);
|
||||
const filteredStatus = this.filterStack.receiveTrailers(this.finalStatus!);
|
||||
this.listener!.onReceiveStatus(filteredStatus);
|
||||
if (this.subchannel) {
|
||||
this.subchannel.callUnref();
|
||||
this.subchannel.removeDisconnectListener(this.disconnectListener);
|
||||
|
|
@ -353,14 +354,26 @@ export class Http2CallStream implements Call {
|
|||
|
||||
private handleTrailers(headers: http2.IncomingHttpHeaders) {
|
||||
this.trace('received HTTP/2 trailing headers frame');
|
||||
const code: Status = this.mappedStatusCode;
|
||||
const details = '';
|
||||
let metadata: Metadata;
|
||||
try {
|
||||
metadata = Metadata.fromHttp2Headers(headers);
|
||||
} catch (e) {
|
||||
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 };
|
||||
let finalStatus;
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ import { Status, LogVerbosity } from './constants';
|
|||
import { FilterStackFactory } from './filter-stack';
|
||||
import { CallCredentialsFilterFactory } from './call-credentials-filter';
|
||||
import { DeadlineFilterFactory } from './deadline-filter';
|
||||
import { MetadataStatusFilterFactory } from './metadata-status-filter';
|
||||
import { CompressionFilterFactory } from './compression-filter';
|
||||
import { getDefaultAuthority } from './resolver';
|
||||
import { LoadBalancingConfig } from './load-balancing-config';
|
||||
|
|
@ -192,7 +191,6 @@ export class ChannelImplementation implements Channel {
|
|||
this.filterStackFactory = new FilterStackFactory([
|
||||
new CallCredentialsFilterFactory(this),
|
||||
new DeadlineFilterFactory(this),
|
||||
new MetadataStatusFilterFactory(this),
|
||||
new CompressionFilterFactory(this),
|
||||
]);
|
||||
// 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 { Status } from './constants';
|
||||
import { BaseFilter, Filter, FilterFactory } from './filter';
|
||||
|
|
@ -82,6 +82,13 @@ export class DeadlineFilter extends BaseFilter implements Filter {
|
|||
finalMetadata.set('grpc-timeout', timeoutString);
|
||||
return finalMetadata;
|
||||
}
|
||||
|
||||
receiveTrailers(status: StatusObject) {
|
||||
if (this.timer) {
|
||||
clearTimeout(this.timer);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
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