У меня есть сервер golang, который отправляет поток GRPC, и я пытаюсь подключиться к нему через клиент Windows .NET, но я могу сделать это только в том случае, если я подключаюсь к веб-серверу grpc напрямую, и соединение не работает, если Я использую proxy_pass или grpc_pass через nginx, чтобы пройти через это соединение.
Это моя конфигурация nginx:
server {
listen 8081;
server_name localhost;
location / {
root /usr/share/nginx/html/app-mobile;
index index.html;
add_header Pragma public;
add_header Cache-Control "public";
expires $expires;
etag off;
# First attempt to serve request as file, then as directory, then fall back to index.html.
try_files $uri $uri/ /index.html;
}
location /api/printerconnection/v1/ {
proxy_pass http://0.0.0.0:8107/;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Вот как я подключаюсь к нему из клиента .NET:
private static async Task waitForOrderGRPCstream()
{
var httpHandler = new HttpClientHandler() { UseProxy = true, AllowAutoRedirect = true };
using var channel = GrpcChannel.ForAddress("http://localhost:3031/api/printerconnection/v1", new GrpcChannelOptions
{
HttpHandler = new GrpcWebHandler(httpHandler)
});
var client = new PrinterConnectionClient(channel);
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5000));
try
{
var myRequest = new GetPrinterConnectionRequest {};
Console.WriteLine($"Making GRPC Call for streaming");
using var streamingCall = client.GetPrinterConnectionStream(myRequest, cancellationToken: cts.Token);
Console.WriteLine($"Will now wait GRPC streaming...");
while (await streamingCall.ResponseStream.MoveNext(cancellationToken: cts.Token))
{
var response = streamingCall.ResponseStream.Current;
// Handle the incoming response from the server.
Console.WriteLine($"Received GRPC message: {response.Content}");
}
}
catch (Exception ex)
{
Console.WriteLine("Stream cancelled because of : "+ex);
}
}
Приведенное выше соединение дает ошибку Stream cancelled because of : Grpc.Core.RpcException: Status(StatusCode = "Unknown", Detail = "Bad gRPC response. HTTP status code: 405") Я пытался изменить заголовки nginx и добавить разные параметры в HttpClienthandler на стороне клиента .NET, но ошибка сохраняется.
Но когда я заменяю http://localhost:8081/api/printerconnection/v1 на http://localhost:8107 для прямого подключения к моему веб-серверу GRPC, он работает без проблем, и я могу видеть контент, который отправляю со своего сервера.





Проблема оказалась в том, что службы, размещенные в подкаталогах, не поддерживались.
Для получения дополнительной информации: https://learn.microsoft.com/en-us/aspnet/core/grpc/troubleshoot?view=aspnetcore-7.0#calling-grpc-services-hosted-in-a-sub-directory
Поэтому мне пришлось добавить обработчик подкаталога следующим образом:
/// <summary>
/// A delegating handler that adds a subdirectory to the URI of gRPC requests.
/// </summary>
public class SubdirectoryHandler : DelegatingHandler
{
private readonly string _subdirectory;
public SubdirectoryHandler(HttpMessageHandler innerHandler, string subdirectory)
: base(innerHandler)
{
_subdirectory = subdirectory;
}
protected override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var old = request.RequestUri;
var url = $"{old.Scheme}://{old.Host}:{old.Port}";
url += $"{_subdirectory}{request.RequestUri.AbsolutePath}";
request.RequestUri = new Uri(url, UriKind.Absolute);
return base.SendAsync(request, cancellationToken);
}
}
И используйте это из кода следующим образом:
var handler = new SubdirectoryHandler(new HttpClientHandler(), "/api/printerconnection/v1");
Почему вы пытаетесь подключиться к порту
3031(localhost:3031), когда ваша конфигурация nginx прослушивает8081(listen 8081;)?