Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hosting Behind Cloudflare: Must be Grpc-Web/GrpcWebSocketBridge #3

Open
Sen-Gupta opened this issue Jan 5, 2024 · 2 comments
Open

Comments

@Sen-Gupta
Copy link

Hello Again!

Looking at the example solution, if we try to host and route requests through cloudflare.
The headers are not being returned.

Cloudflare does not support Http2 end to end.

More information here:

https://blog.cloudflare.com/road-to-grpc

The issues is
#if GRPC_SSL

    Configuration = provider.GetService<IConfiguration>();
    var configuration = provider.GetService<IConfiguration>();
    //Make sure certificate file's copytooutputdirectory is set to always copy
    var certificatePath = Path.Combine(Environment.CurrentDirectory, Configuration.GetSection("Certificate").Value);
    
    var certificate = new X509Certificate2(File.ReadAllBytes(certificatePath));

    var SslAuthOptions = CreateSslClientAuthOptions(certificate);

    **var socketHandler = CreateHttpClientWithSocketsHandler(SslAuthOptions, Timeout.InfiniteTimeSpan, TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(30));**

    var channelOptions = CreateGrpcChannelOptions(socketHandler);

    var channel = GrpcChannel.ForAddress(baseUrl, channelOptions);

#else
var channel = GrpcChannel.ForAddress(baseUrl);
#endif

    Client = MagicOnionClient.Create<TService>(channel, MemoryPackMagicOnionSerializerProvider.Instance, filters);

}#if GRPC_SSL

    
    Configuration = provider.GetService<IConfiguration>();
    var configuration = provider.GetService<IConfiguration>();
    //Make sure certificate file's copytooutputdirectory is set to always copy
    var certificatePath = Path.Combine(Environment.CurrentDirectory, Configuration.GetSection("Certificate").Value);
    
    var certificate = new X509Certificate2(File.ReadAllBytes(certificatePath));

    var SslAuthOptions = CreateSslClientAuthOptions(certificate);

    var socketHandler = CreateHttpClientWithSocketsHandler(SslAuthOptions, Timeout.InfiniteTimeSpan, TimeSpan.FromSeconds(60), TimeSpan.FromSeconds(30));

    var channelOptions = CreateGrpcChannelOptions(socketHandler);

    var channel = GrpcChannel.ForAddress(baseUrl, channelOptions);

#else
var channel = GrpcChannel.ForAddress(baseUrl);
#endif

    **Client = MagicOnionClient.Create<TService>(channel, MemoryPackMagicOnionSerializerProvider.Instance, filters);**

}

In short anyone who is using cloudflare as proxy must use Grpc-Web Client or more apt with magic onion.
https://github.com/Cysharp/GrpcWebSocketBridge
[https://github.com/Cysharp/GrpcWebSocketBridge]

There must be a way to let client choose Client Channels to make this solution truly generic.

Great effort!

@licentia88
Copy link
Owner

I'll also look into this as I was not aware of this repo -> https://github.com/Cysharp/GrpcWebSocketBridge

meanwhile if you already have a working example of magiconion working on http1, It would save me time in reading and implementing to the project

@Sen-Gupta
Copy link
Author

Sen-Gupta commented Jan 18, 2024

Hello,

Yes, our solution is already hosted and is being access via cloudflare.

All we did is to replace channels with GrpcWebSocketBridge and it worked like charm. (Code is specific to our implementation, yours will differ as suggested below.)

public class NativeGrpcClientChannel : IGrpcClient
{
public GrpcChannel GetGrpcChannel(string baseUri)
{
HttpClient httpClient = new HttpClient();
var httpHandler = new GrpcWebSocketBridgeHandler();
//httpClient.DefaultRequestHeaders.Add("grpc-internal-encoding-request", "gzip");
//httpClient.DefaultRequestVersion = HttpVersion.Version20;
//httpClient.DefaultVersionPolicy = HttpVersionPolicy.RequestVersionExact;
var channel = GrpcChannel.ForAddress(baseUri, new GrpcChannelOptions {
HttpHandler = httpHandler,
MaxReceiveMessageSize = 10 * 1024 * 1024, // 10 MB
MaxSendMessageSize = 10 * 1024 * 1024, // 10 MB
});
return channel;
}
}

#To Create Client
private IEquitiesGrpcService GetClient()
{
string baseUri = _configuration.GetSection("EndPoints").GetValue("APIGateway");
var channel = _nativeGrpcClient.GetGrpcChannel(baseUri);
return MagicOnionClient.Create(channel, new IClientFilter[]
{
new LoggingFilter()
});
}

BTW, the only portion that changes is the highlighted code.

You may to want to create another condition -http2Only for template flag.

Default for -http2Only is false.

If user passes --http2Only: true, (like you have done for -SSL)
The existing code is good.
-http2Only: true,
GrpcWebSockectChannels will be required.

If required, ping me, I can drop a pull request. ;-)

Happy to help you on this, have burnt my hands on Grpc Hosting a lot so can help a little.

BTW, the client can run on Web, Blazor, or even Blazor MAUI. We have all cases in production.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants