Reverse HTTP
Reverse HTTP is an experimental protocol which takes advantage of the HTTP/1.1 Upgrade: header to turn one HTTP socket around. When a client makes a request to a server with the Upgrade: PTTH/0.9 header, the server may respond with an Upgrade: PTTH/1.0 header, after which point the server starts using the socket as a client, and the client starts using the socket as a server. There is also a COMET-style protocol which will work with HTTP/0.9 or 1.1 clients that do not know how to perform this upgrade.
March 2009: Zero and Donovan submitted an Internet-Draft formally describing this.
Below is an example transcript using Reverse HTTP. Lines on the left are traffic from the client to the server. Lines on the right are traffic from the server to client. Lines with a red background are HTTP requests. Lines with a green background are HTTP responses.
The transcript was created by sniffing the traffic from running this script [1].
Request |
Response |
client -> server | server -> client |
---|---|
POST / HTTP/1.1 | |
Host: localhost:9999 | |
Accept-Encoding: identity | |
Upgrade: PTTH/0.9 | |
HTTP/1.1 101 Switching Protocols | |
Content-type: text/plain | |
Upgrade: PTTH/0.9 | |
Date: Tue, 13 May 2008 20:14:45 GMT | |
Content-Length: 0 | |
GET / HTTP/1.1 | |
Host: 127.0.0.1:65331 | |
Accept-Encoding: identity | |
accept: text/plain;q=1,*/*;q=0 | |
HTTP/1.1 200 OK | |
Content-type: text/plain | |
Date: Tue, 13 May 2008 20:14:45 GMT | |
Content-Length: 15 | |
!dlrow ,olleH | |
COMET Fallback
If the client or server is incapable of upgrading from HTTP, a COMET-style protocol can be used instead. The server can maintain an event queue and require that the client repeatedly POST to the queue's resource to receive events. Below is a protocol trace using JSON as the protocol encoding.
POST / HTTP/1.1 | |
Host: localhost:9999 | |
Accept-Encoding: identity | |
HTTP/1.1 200 OK | |
Content-type: application/json | |
Date: Tue, 13 May 2008 20:14:45 GMT | |
Content-Length: 210 | |
{'message-id': 'xxx', 'method': 'GET', 'request-uri': '/', 'http-version': 'PTTH/0.9', 'headers': [['Host', '127.0.0.1:65331'], ['Accept-Encoding', 'identity'], ['Accept','text/plain;q=1,*/*;q=0']], 'body': } | |
POST / HTTP/1.1 | |
Host: localhost:9999 | |
Accept-Encoding: identity | |
Content-type: application/json | |
Content-length: 193 | |
{'message-id': 'xxx', 'http-version': 'PTTH/0.9', 'status': 200, 'reason': 'OK', 'headers': [['Content-type', 'text/plain'], ['Date', 'Tue, 13 May 2008 20:14:45 GMT']], 'body': '!dlrow ,olleH'} | |
HTTP/1.1 200 OK | |
Content-type: application/json | |
Date: Tue, 13 May 2008 20:14:45 GMT | |
Content-Length: 2 | |
{} |
A response of {} from the server means no server-side event occurred within some timeout, and that the client should poll again if it wants to keep receiving events.
Another idea is to use text/plain encoding instead of JSON, and just have the actual text of the HTTP request in the response, and the text of the response in the next request. In this case, the message-id would be relayed in a header instead of in the body. Perhaps the message id should always be relayed in a header and never in the body?