grpc / grpc/grpc-java

"HTTP/1 Only" Support for grpc-java

オープン
#9,999 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る
enhancement
主要言語
Java
スター
12.1k
フォーク
4k
平均マージ
2日 17時間
マージ済み PR(30日)
37

説明

### Problem
My Java gRPC server cannot accept HTTP/1 requests as already reported with https://github.com/grpc/grpc-java/issues/4067 because the following exception is thrown:

```
io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2Exception: Unexpected HTTP/1.x request: POST /org.foo.BarService/Check
at io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2Exception.connectionError(Http2Exception.java:103)
at io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2ConnectionHandler$PrefaceDecoder.readClientPrefaceString(Http2ConnectionHandler.java:302)
at io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2ConnectionHandler$PrefaceDecoder.decode(Http2ConnectionHandler.java:239)
at io.grpc.netty.shaded.io.netty.handler.codec.http2.Http2ConnectionHandler.decode(Http2ConnectionHandler.java:438)
at io.grpc.netty.shaded.io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:501)
at io.grpc.netty.shaded.io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:440)
at io.grpc.netty.shaded.io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
at io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
at io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.grpc.netty.shaded.io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.grpc.netty.shaded.io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at io.grpc.netty.shaded.io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
at io.grpc.netty.shaded.io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714)
at io.grpc.netty.shaded.io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650)
at io.grpc.netty.shaded.io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576)
at io.grpc.netty.shaded.io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
at io.grpc.netty.shaded.io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
at io.grpc.netty.shaded.io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.grpc.netty.shaded.io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:750)
```
(grpc-netty-shaded-1.41.1)

The mentioned issue was closed by @ejona86 in favor of https://github.com/grpc/grpc-java/issues/3458. However, #3458 is about accepting both HTTP/1 and HTTP/2 on the same port which is not my request.

### Request
I want to be able to run a gRPC server that accepts unsecured HTTP/1 requests (_instead_ of HTTP/2 requests). Due to technical restrictions, my clients can only send HTTP/1 requests with JSON bodies.

I plan to implement an interceptor that transcodes JSON strings of given requests to gRPC messages but `ServerInterceptor#interceptCall` is never reached due to the exception above.

### Not Working Workarounds
I also tried to use Nginx with a configuration like this:

```
location ~* /org.foo.BarService*/ {
grpc_pass grpc://172.17.0.1:49209;
grpc_connect_timeout 600s;
grpc_send_timeout 600s;
grpc_read_timeout 600s;
grpc_set_header Host $host;
grpc_set_header X-Real-IP $remote_addr;
grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
grpc_set_header X-Forwarded-Proto $scheme;
grpc_set_header Content-Type application/grpc-web+proto;
grpc_set_header Accept-Encoding identity,gzip;
}
```

but grpc-java doesn't support the "grpc-web+proto" content-type.

### Working Workarounds
I can implement a usual REST server that creates gRPC messages for given JSON strings and forwards them via `io.grpc.inprocess.InProcessServerBuilder`. But since gRPC supports [transcoding](https://cloud.google.com/endpoints/docs/grpc/transcoding#deploying_a_service_that_uses_transcoding) out of the box, I'd like to be able to benefit from this directly (maybe even without having to write an interceptor myself).

コントリビューションガイド

コントリビューションガイドを開く

調査の方向性

Start by reading grpc-java issues #4067 and #3458, then inspect the ServerInterceptor#interceptCall path and the HTTP/2 handling that prevents it from being reached. Compare the requested HTTP/1-only, unsecured JSON behavior with the existing InProcessServerBuilder workaround. Done means a server can accept these requests and expose a defined validation path, with coverage for the supported request format.

索引モデルが issue の本文から書いたものです。

評価

技術スタック
grpc, java
領域
api, backend
issue の種類
機能追加
難易度
5/5
見積もり時間
1週間以上
活発さ
停滞
明瞭さ
おおむね明確
初心者へのやさしさ
25/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。