From Second Life Wiki

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?