Description
Please answer these questions before submitting your issue. Thanks!
What version of Go are you using (go version
)?
Go 1.8.3 (but can reproduce with 1.9beta2.
What operating system and processor architecture are you using (go env
)?
darwin and linux
What did you do?
Tried to use the http2 transport to talk to a remote http2 server.
https://play.golang.org/p/W_HbQGJZK9
The server on the other end is the grpc helloworld example.
When running against the grpc-go implementation, the code works.
When running agains ruby or python(both backed by C code) I get the INTERNAL_ERROR response described above. Logging on the server side itself is silent.
Note, the HTTP POST is only to more easily reproduce the issue. What I'm trying to do instead is use httputil.ReverseProxy to proxy grpc traffic: https://play.golang.org/p/micZul79Ow
This succeeds if the upstream server is in Go
C server examples: https://github.com/grpc/grpc/tree/master/examples (connecting to these fails)
grpc-go examples: https://github.com/grpc/grpc-go/tree/master/examples (connecting to this server succeeds)
What did you expect to see?
An HTTP response.
What did you see instead?
GODEBUG=http2debug=2 go run main.go
2017/07/19 23:34:05 http2: Transport creating client conn 0xc42013c000 to [::1]:8082
2017/07/19 23:34:05 http2: Framer 0xc42014e000: wrote SETTINGS len=18, settings: ENABLE_PUSH=0, INITIAL_WINDOW_SIZE=4194304, MAX_HEADER_LIST_SIZE=10485760
2017/07/19 23:34:05 http2: Framer 0xc42014e000: wrote WINDOW_UPDATE len=4 (conn) incr=1073741824
2017/07/19 23:34:05 http2: Transport encoding header ":authority" = "localhost:8082"
2017/07/19 23:34:05 http2: Transport encoding header ":method" = "POST"
2017/07/19 23:34:05 http2: Transport encoding header ":path" = "/"
2017/07/19 23:34:05 http2: Transport encoding header ":scheme" = "https"
2017/07/19 23:34:05 http2: Transport encoding header "content-type" = "application/grpc"
2017/07/19 23:34:05 http2: Transport encoding header "content-length" = "5"
2017/07/19 23:34:05 http2: Transport encoding header "accept-encoding" = "gzip"
2017/07/19 23:34:05 http2: Transport encoding header "user-agent" = "Go-http-client/2.0"
2017/07/19 23:34:05 http2: Framer 0xc42014e000: wrote HEADERS flags=END_HEADERS stream=1 len=51
2017/07/19 23:34:05 http2: Framer 0xc42014e000: wrote DATA stream=1 len=5 data="hello"
2017/07/19 23:34:05 http2: Framer 0xc42014e000: read SETTINGS len=24, settings: INITIAL_WINDOW_SIZE=65535, MAX_FRAME_SIZE=65538, MAX_HEADER_LIST_SIZE=16384, UNKNOWN_SETTING_65027=1
2017/07/19 23:34:05 http2: Framer 0xc42014e000: wrote DATA flags=END_STREAM stream=1 len=0 data=""
2017/07/19 23:34:05 http2: Transport received SETTINGS len=24, settings: INITIAL_WINDOW_SIZE=65535, MAX_FRAME_SIZE=65538, MAX_HEADER_LIST_SIZE=16384, UNKNOWN_SETTING_65027=1
2017/07/19 23:34:05 Unhandled Setting: [MAX_HEADER_LIST_SIZE = 16384]
2017/07/19 23:34:05 Unhandled Setting: [UNKNOWN_SETTING_65027 = 1]
2017/07/19 23:34:05 http2: Framer 0xc42014e000: wrote SETTINGS flags=ACK len=0
2017/07/19 23:34:05 http2: Framer 0xc42014e000: read SETTINGS flags=ACK len=0
2017/07/19 23:34:05 http2: Transport received SETTINGS flags=ACK len=0
2017/07/19 23:34:05 http2: Framer 0xc42014e000: read RST_STREAM stream=1 len=4 ErrCode=INTERNAL_ERROR
2017/07/19 23:34:05 http2: Transport received RST_STREAM stream=1 len=4 ErrCode=INTERNAL_ERROR
2017/07/19 23:34:05 http2: Framer 0xc42014e000: read HEADERS flags=END_STREAM|END_HEADERS stream=1 len=83
2017/07/19 23:34:05 http2: decoded hpack field header field ":status" = "200"
2017/07/19 23:34:05 http2: decoded hpack field header field "content-type" = "application/grpc"
2017/07/19 23:34:05 RoundTrip failure: stream error: stream ID 1; INTERNAL_ERROR
2017/07/19 23:34:05 http2: decoded hpack field header field "grpc-status" = "1"
2017/07/19 23:34:05 http2: decoded hpack field header field "grpc-message" = "Cancelled"
2017/07/19 23:34:05 http2: Transport received HEADERS flags=END_STREAM|END_HEADERS stream=1 len=83
2017/07/19 23:34:05 Post https://localhost:8082: stream error: stream ID 1; INTERNAL_ERROR
Activity
bradfitz commentedon Jul 20, 2017
I bet it doesn't like the
:path
of/
you're sending.But that would have nothing to do with Go's HTTP/2 support.
groob commentedon Jul 20, 2017
Here is the debug output of the proxy version:
proxying to the ruby grpc greeter server.
groob commentedon Jul 20, 2017
And this is what happens when the remote is a grpc-go server:
[-]x/net/http2 transport results in stream error INTERNAL_ERROR [/-][+]x/net/http2: transport results in stream error INTERNAL_ERROR when proxying to C grpc server [/+]groob commentedon Jul 20, 2017
Here's something. I figured out how to enable http tracing on the ruby server:
GRPC_TRACE=http
bradfitz commentedon Jul 20, 2017
It's missing the "te" header.
The https://grpc.io/docs/guides/wire.html does say:
I guess you're an incompatible proxy! :-)
I forget which layer's job it is to strip/add/handle that. But that's what should be investigated here.
/cc @tombergan
groob commentedon Jul 20, 2017
Yep, commenting out
Te
in the httputil.ReverseProxy makes the C server behave as expected.go/src/net/http/httputil/reverseproxy.go
Line 135 in 3498012
Doesn't sound like the right solution for a proxy to keep that header though. Should I open a issue with grpc/grpc?
groob commentedon Jul 20, 2017
Found this article from the nginx blog https://nghttp2.org/blog/2015/03/24/proxying-grpc-with-nghttpx/
groob commentedon Jul 21, 2017
@bradfitz is it too late in the 1.9 cycle or would you accept a CL to update this behavior in httputil/reverseproxy.go?
Something like this is what I had in mind:
bradfitz commentedon Jul 21, 2017
It's way too late. But your proxy can add those lines.
It's not obvious that we want to add application-specific hacks to reverseproxy.go.
Let's think about it during Go 1.10 development.
[-]x/net/http2: transport results in stream error INTERNAL_ERROR when proxying to C grpc server [/-][+]net/http/httputil: ReverseProxy doesn't proxy grpc without help due to 'te' header handling[/+]bradfitz commentedon Dec 4, 2017
Pushing to Go 1.11.
@tombergan, do you know what's right here?
8 remaining items
Cas-pian commentedon Jul 25, 2018
@gopherbot I've tested the go1.11beta2, the "Te" header in the client still missing when request backend server, I'm using traefik. Thanks.
bradfitz commentedon Jul 25, 2018
@Cas-pian, you probably didn't recompile your application or didn't do so with the right version of Go.
Cas-pian commentedon Jul 25, 2018
@bradfitz Thanks for your reply. I've recompile my application. And I found the application didn't use your function. I've fixed it. Thanks again!
idefixcert commentedon Jan 16, 2019
I have the same problem but cant find a solution:
I have a ProxyServer written in go
If I make a call from gnmi server to client, I get:
Fix gRPC proxying
Fix gRPC proxying
Fix gRPC and add test (#2119)