Whilst tinkering apiman’s Vert.x gateway implementation I ran into a strange issue when invoking an API via curl --http2
. It seemed to work fine in Chrome and using Go’s h2c:
$ * http2 error: Invalid HTTP header field was received: frame type: 1, stream: 1, name: [connection], value: [keep-alive]
This is what the setup looks like (distilled):
HTTP/2 Client <--> Apiman Gateway (HTTP/2) <--> Test API (HTTP/1)
What’s going on?
I took to Twitter to figure out what was going on.
@apiman_io @clementplop although the cURL --http2 doesn't like the headers Vert.x sends - interesting https://t.co/0dK81huCmb
— Marc Savy (@marcsavy) August 20, 2016
Out of the blue, Mr cURL himself (Daniel Stenberg) popped up with the answer quoted from RFC 7540:
@marcsavy @apiman_io @clementplop "An endpoint MUST NOT generate an HTTP/2 message containing connection-specific header fields"
— Daniel Stenberg (@bagder) August 20, 2016
Mystery solved
Aha! The backend API apiman was proxying the response from returned a Connection: keep-alive
header. Apiman simply forwarded this on, but it turns out this violates the HTTP/2 spec as there should be no connection-specific header fields - in response cURL spits out the error we see above. [1]
HTTP/2 Client (http2 error...) <- Apiman Gateway <- Test API (sets "Connection: keep-alive")
The solution was just to filter out Connection
headers in apiman, but I wonder whether Vert.x should do it by default (or show an error message, exception, etc).
That said, I think "it’s the app’s responsibility not to do stupid things" or "we should handle it and filter out Connection headers" are both valid responses depending upon philosophy.
So, I let the Vert.x guys know, and let’s see.