Issue
Your application returns a Connection: close
header when you test sending requests to it locally, but you get Connection: keep-alive
headers for requests to your application on Heroku.
Resolution
This is expected and is due to a difference in routing behavior based on the version of HTTP being used for requests. This behavior is described in our routing documentation here:
Additionally, while HTTP/1.1 requests and responses are expected to be
keep-alive
by default, if the initial request had an explicitconnection: close
header from the router to the dyno, the dyno can send a response delimited by the connection termination, without a specific content-encoding nor an explicit content-length.
So, requests over HTTP/1.1 use keep-alive by default if no Connection
header is sent specifying otherwise. You can see this in action using curl:
$ curl -v -X POST http://test-app.com/test
...
> POST /test HTTP/1.1
...
>
< HTTP/1.1 200 OK
< Connection: keep-alive
...
Note that the POST is using HTTP/1.1. If you force curl to use HTTP/1.0 you get this:
$ curl -v -X POST --http1.0 http://test-app.com/test
...
> POST /test HTTP/1.0
...
>
< HTTP/1.1 200 OK
< Connection: close
...
Note that HTTP/1.0 is being used now and that the connection header coming back is Connection: close
this time. As per the RFC and routing documentation, if the request uses HTTP/1.1, but specifies a Connection: close
header, then it respects that:
$ curl -v -X POST -H 'Connection: close' http://test-app.com/test
...
> POST /test HTTP/1.1
...
> Connection: close
>
< HTTP/1.1 200 OK
< Connection: close
...
You can see that this is expected behavior in this whitepaper doc that outlines differences between HTTP/1.0 and HTTP/1.1 (search for "keep-alive" to find the "Persistent Connections" section that discusses this). The relevant bit is as follows:
HTTP/1.0, in its documented form, made no provision for persistent connections. Some HTTP/1.0 implementations, however, use a Keep-Alive header (described in [Fie95]) to request that a connection persist. This design did not interoperate with intermediate proxies (see Section 19.6.2 of [FGM+98]); HTTP/1.1 specifies a more general solution.
In recognition of their desirable properties, HTTP/1.1 makes persistent connections the default. HTTP/1.1 clients, servers, and proxies assume that a connection will be kept open after the transmission of a request and its response. The protocol does allow an implementation to close a connection at any time, in order to manage its resources, although it is best to do so only after the end of a response.
Because an implementation may prefer not to use persistent connections if it cannot efficiently scale to large numbers of connections or may want to cleanly terminate one for resource-management reasons, the protocol permits it to send a Connection: close header to inform the recipient that the connection will not be reused.
As such, to ensure Connection: close
is used under HTTP/1.1 you need to specify that header in the original request.