Reverse HTTP

From Second Life Wiki
Jump to navigation Jump to search

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?