From fdc836e13462110dcaad077c0e106c4174d7749f Mon Sep 17 00:00:00 2001 From: Guillermo De La Cruz Date: Fri, 12 Apr 2024 16:25:52 +0800 Subject: [PATCH] feat(http2_channel.dart): add support for prefixPath in ClientChannel to allow setting a prefix path for all requests feat(http2_connection.dart): add support for prefixPath in Http2ClientConnection to include a prefix path in request paths feat(xhr_transport.dart): update requestUri construction to include prefixPath in XhrClientConnection feat(web_channel.dart): add validation for prefixPath in GrpcWebClientChannel to ensure it starts and ends with / --- lib/src/client/http2_channel.dart | 9 +++++++-- lib/src/client/http2_connection.dart | 10 +++++++--- lib/src/client/transport/xhr_transport.dart | 7 +------ lib/src/client/web_channel.dart | 6 +++++- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/lib/src/client/http2_channel.dart b/lib/src/client/http2_channel.dart index 2657eb06..b22716b1 100644 --- a/lib/src/client/http2_channel.dart +++ b/lib/src/client/http2_channel.dart @@ -30,18 +30,23 @@ class ClientChannel extends ClientChannelBase { /// case it can be a Unix Domain Socket address. final Object host; final int port; + final String prefixPath; final ChannelOptions options; ClientChannel( this.host, { this.port = 443, + this.prefixPath = '', this.options = const ChannelOptions(), super.channelShutdownHandler, - }); + }) : assert( + prefixPath.isEmpty || + prefixPath.isNotEmpty && !prefixPath.endsWith('/'), + 'prefixPath must be empty or does not start and end with /'); @override ClientConnection createConnection() => - Http2ClientConnection(host, port, options); + Http2ClientConnection(host, port, options, prefixPath: '/$prefixPath'); } class ClientTransportConnectorChannel extends ClientChannelBase { diff --git a/lib/src/client/http2_connection.dart b/lib/src/client/http2_connection.dart index 998410a1..a83eb3b1 100644 --- a/lib/src/client/http2_connection.dart +++ b/lib/src/client/http2_connection.dart @@ -62,11 +62,15 @@ class Http2ClientConnection implements connection.ClientConnection { ClientKeepAlive? keepAliveManager; - Http2ClientConnection(Object host, int port, this.options) + final String prefixPath; + + Http2ClientConnection(Object host, int port, this.options, + {this.prefixPath = ''}) : _transportConnector = SocketTransportConnector(host, port, options); Http2ClientConnection.fromClientTransportConnector( - this._transportConnector, this.options); + this._transportConnector, this.options, + {this.prefixPath = ''}); ChannelCredentials get credentials => options.credentials; @@ -178,7 +182,7 @@ class Http2ClientConnection implements connection.ClientConnection { final headers = createCallHeaders( credentials.isSecure, _transportConnector.authority, - path, + prefixPath + path, timeout, metadata, compressionCodec, diff --git a/lib/src/client/transport/xhr_transport.dart b/lib/src/client/transport/xhr_transport.dart index 039c1814..0089963c 100644 --- a/lib/src/client/transport/xhr_transport.dart +++ b/lib/src/client/transport/xhr_transport.dart @@ -180,12 +180,7 @@ class XhrClientConnection implements ClientConnection { metadata['X-Grpc-Web'] = '1'; } - if (prefixPath.isNotEmpty && prefixPath.endsWith('/')) { - throw ArgumentError.value( - prefixPath, 'prefixPath', 'must not end with a slash'); - } - - var requestUri = uri.resolve('$prefixPath$path'); + var requestUri = uri.resolve(prefixPath + path); if (callOptions is WebCallOptions && callOptions.bypassCorsPreflight == true) { requestUri = cors.moveHttpHeadersToQueryParam(metadata, requestUri); diff --git a/lib/src/client/web_channel.dart b/lib/src/client/web_channel.dart index a78a822c..7381cbab 100644 --- a/lib/src/client/web_channel.dart +++ b/lib/src/client/web_channel.dart @@ -25,7 +25,11 @@ class GrpcWebClientChannel extends ClientChannelBase { final String prefixPath; GrpcWebClientChannel.xhr(this.uri, - {this.prefixPath = '', super.channelShutdownHandler}); + {this.prefixPath = '', super.channelShutdownHandler}) + : assert( + prefixPath.isEmpty || + prefixPath.isNotEmpty && !prefixPath.endsWith('/'), + 'prefixPath must be empty or does not start and end with /'); @override ClientConnection createConnection() {