From a99afaf5eb3ea7172dea7c6d0f81f313043a5ee5 Mon Sep 17 00:00:00 2001 From: Michael Lumish Date: Thu, 19 Mar 2020 09:42:17 -0700 Subject: [PATCH] grpc-js: Make filter stack handle status in all code paths --- packages/grpc-js/src/call-stream.ts | 19 +++++-- packages/grpc-js/src/channel.ts | 2 - packages/grpc-js/src/deadline-filter.ts | 9 +++- .../grpc-js/src/metadata-status-filter.ts | 54 ------------------- 4 files changed, 24 insertions(+), 60 deletions(-) delete mode 100644 packages/grpc-js/src/metadata-status-filter.ts diff --git a/packages/grpc-js/src/call-stream.ts b/packages/grpc-js/src/call-stream.ts index 99d1f8dd..70c728e0 100644 --- a/packages/grpc-js/src/call-stream.ts +++ b/packages/grpc-js/src/call-stream.ts @@ -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 { diff --git a/packages/grpc-js/src/channel.ts b/packages/grpc-js/src/channel.ts index 1d555ea2..ad45f654 100644 --- a/packages/grpc-js/src/channel.ts +++ b/packages/grpc-js/src/channel.ts @@ -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 diff --git a/packages/grpc-js/src/deadline-filter.ts b/packages/grpc-js/src/deadline-filter.ts index f659c866..b5e4cabc 100644 --- a/packages/grpc-js/src/deadline-filter.ts +++ b/packages/grpc-js/src/deadline-filter.ts @@ -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 { diff --git a/packages/grpc-js/src/metadata-status-filter.ts b/packages/grpc-js/src/metadata-status-filter.ts deleted file mode 100644 index f3879d7a..00000000 --- a/packages/grpc-js/src/metadata-status-filter.ts +++ /dev/null @@ -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 { - constructor(private readonly channel: Channel) {} - createFilter(callStream: Call): MetadataStatusFilter { - return new MetadataStatusFilter(); - } -}