grpc-dart
grpc-dart copied to clipboard
Use URI path in requests
Hey, I'd like to pass a URI with a path to the client, so that I can use a proxy in front of my application on the server side to redirect to the correct service.
final channel = GrpcWebClientChannel.xhr(Uri.parse('http://localhost:6060/grpc'));
Now, looking at the source code after trying a couple of things, I can see that the path is simply overwritten by whatever the generated file has. As of now I am not sure if that's a gRPC requirement or just not implemented in this project.
In line 167 I can see that the path is simply passed into the URI. https://github.com/grpc/grpc-dart/blob/ae17e712e4f5431eb6664f0589899c77462e5475/lib/src/client/transport/xhr_transport.dart#L164-L167
Part of my pubspec.lock
grpc:
dependency: "direct main"
description:
name: grpc
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
This should work, try ending the Uri with a '/' then Uri.resolve is supposed to do the right thing
Sadly that doesn't work...
I think the uri.resolve(path).toString() overwrites the path entirely, if I'm not mistaken.
I think I'm misunderstanding something. Why would it overwrite it?
void main() {
final path = 'abc/def';
final uri = Uri.parse('http://localhost:6060/grpc');
final uri2 = Uri.parse('http://localhost:6060/grpc/');
print(uri.resolve(path));
print(uri2.resolve(path));
}
prints:
http://localhost:6060/abc/def
http://localhost:6060/grpc/abc/def
Any update here? This is the problem with gRPC-dart not with Uri.parse
Uri correctly parse the sub path but the gRPC client code does not use it (https://github.com/grpc/grpc-dart/blob/e4947e290924f98de48437686122c2ba482d4326/lib/src/client/method.dart#L22).
For example, the generated code will pass down the path /some_random.Service/SomeMethod as the proto file does not need to know about the client path. This is correct.
And then it should be prefixed by the client method (/grpc/some_random.Service/SomeMethod). But, it just takes the path as is (/some_random.Service/SomeMethod)
now i understand the problem. the generated code (stub output from protoc --dart_out=...) has a prefix "/"
so the URI will ignore the path
void main() {
final path = '/abc/def';
final uri = Uri.parse('http://localhost:6060/grpc');
final uri2 = Uri.parse('http://localhost:6060/grpc/');
print(uri.resolve(path));
print(uri2.resolve(path));
}
prints
http://localhost:6060/abc/def
http://localhost:6060/abc/def
Either the generated code should not be prefixed with "/" or we need to modify https://github.com/grpc/grpc-dart/blob/e4947e290924f98de48437686122c2ba482d4326/lib/src/client/transport/xhr_transport.dart#L138
or Uri.resolve should be fixed?
Still waiting on this :(
For those that need somewhat of a fix, here is what I used:
import 'package:grpc/grpc_connection_interface.dart';
// ignore: implementation_imports
import 'package:grpc/src/client/transport/xhr_transport.dart';
///
/// This file exists because of IIS.
/// Applications hosted on IIS come prefixed with a base path.
///
/// Issue described here: https://github.com/grpc/grpc-dart/issues/258
/// The gRPC-dart team currently have a PR for this: https://github.com/grpc/grpc-dart/pull/335
///
/// Hopefully this can be removed in due time.
///
class IisWorkaroundChannel extends ClientChannelBase {
final Uri uri;
IisWorkaroundChannel.xhr(this.uri) : super();
@override
ClientConnection createConnection() {
return IisClientConnection(uri);
}
}
class IisClientConnection extends XhrClientConnection {
IisClientConnection(Uri uri) : super(uri);
@override
GrpcTransportStream makeRequest(String path, Duration? timeout,
Map<String, String> metadata, ErrorHandler onError,
{CallOptions? callOptions}) {
var pathWithoutFirstSlash = path.substring(1);
return super.makeRequest(pathWithoutFirstSlash, timeout, metadata, onError,
callOptions: callOptions);
}
}