Skip to content

rektide/pipe-layer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

81 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Pipe Layer

bidirectional asynchronous http transport

Essence

Pipe Layer is a a bidirectional asynchronous transport for the web.

bidirectional: adj: reactive or functioning or allowing movement in two usually opposite directions [ant: {unidirectional}]

asynchronous: adj: not synchronous; not occurring or existing at the same time or having the same period or phase [ant: {synchronal},

What does this mean in practice?

Jamie Lokier, April 12, 2009, on the HyBi mailing list, wrote his vision of what an asynchronous HTTP transport would mean (((and happens to encompass bidirectional as well))). The outline he provided is pure gold:

What I think would be ideal, and it's been mentioned already as "asynchronous HTTP", is:

HTTP or simplified-HTTP message headers and body.
Bidirectional - either side can send requests and responses.
Channel id attached to each message.
Chunked encoding, with channel id attached to each chunk.
Per channel flow control exactly like BEEP over TCP profile.
Request/response id attached to each message.
Request/response id matches responses out of order to requests.
Pure messages with no response allowed, using "no-response" r/r id.
All the above features are optional.

Pipe layer is an attempt to implement this core vision.

Conceptually, Pipe Layer and async http uses a model akin to SCTP; that of a message based multi-streaming transport. Whereas http is strictly request / response, sctp and the pipe layer transports are conceptually about messages. Whereas http relies on pipelining and multiple connections for parallel operations, pipe layer and sctp add channel semantics to the transport to allow multiple simultaneous connections over a single physical connection.

High Level Implementation

With regards to implementation, Pipe Layer is an extension to HTTP that decouples the conventional request / response action of the transport, permitting HTTP to be used instead as a messaging channel. By adorning all outgoing requests with a unique identifier (((an X-Pipe and X-Seq header))) and maintaining a queue of outstanding requests, the server may reply to any request it wishes (((out of order, tagging each response with its identifier))), or may send a message for which there was no originating request (((this time tagging the message with an X-Pipe and X-RSeq identifier))), thereby fulfilling the stated goals of asynchronity and bidirectionality.

In the browser, connection to the server is delegated to a SharedWorker. XHR is proxied, and send to the SharedWorker, who attaches an identifier and submits the request to the server. The SharedWorker looks at each response, and routes the response to the appropriate XHR (((which, being out of order, may not be the originating XHR))).

Benefit

Lets return to Jamie Lokier's async http post:

That provides the message/event protocol some people are asking for,
and also provides the request/response protocol some people are asking
for, does both bidirectionally, and over a single socket, and with
multiple applications sharing the same socket if they want.

Asynchronous http conveys the following advantages:

  • It is still HTTP.
  • Multiple interleaved channels over a single connection.
  • Bidirectional over a single connection.
  • Eventing behavior; server can assert data.
  • Radically less restrictive pipelining behavior.
  • Pipeline stalls can be avoided by serving replies on alternate physical connections.

The pipe layer implementation has the following properties:

  • Extends HTTP in a compliant fashion.
  • 100% JavaScript implementation; node.js back-end.
  • Uses a SharedWorker (((this standard is not available on all browsers))).
  • No start-up handshake required.

The pipe layer implementation presently lacks the following async features:

  • Chunked encoding transfers block the pipe, no multiplexing.
  • No flow control implemented.
  • No no-response r/r; server has to send 204.

Use Cases

Speed

If a server needs some time to process a request, multi-streaming prevents this request from causing a pipe stall. Note, chunked responses will block that pipe, which only becomes a problem if all physical connections are consumed doing chunked responses.

Server sent events / comet

This is the core use case for pipe layer. Rather than consuming a physical connection for a SSE / comet connection, "push" is a part of the transport, and these messages will simply be interleaven along with other pipe messages. This permits dozens or hundreds of simultaneous push connections to exist at once.

Implementation

A page wishing to use pipe layer loads the XHR proxy pipe.xhr.js. Any future XHR requests the page creates will be sent to the SharedWorker worker.xhr.js. The request will be furnished with identifying information (((an X-Pipe and X-Seq))) and sent to the server.

The server is implemented in node.js. The runtime is assembled by runtime.js, which loads dependencies and constructs the server environment programmatically. The core construct for handling http requests is an asychronized implementation of the Common's Chain; a chain has filters that get run one by one until one filter designates that it has "handled" the request. router1 is the primary chain, and comprises a single filter; a path filter to route the request to a new chain.

Lets dive into some of the filters:

FileSystemFilter

This filter serves files out of the file system. The first parameter is the folder to operate from, and the second parameter is a prefix to strip from the request path.

DelayFilter

This filter delays the request processing, either by a default amount of time, or via a "delay" parameter in the query string. Used for concurrency unit tests.

SessionCookieFilter

Sets cookie value in the context. Builds a cookie and preps set-cookie if none exists.

UserStoreFilter

Uses cookie to retrieve or attach a user scoped context to the context.

XPipeFilter

The Pipe Layer router. Strips response off context and puts it into a users responses queue, attached a proxy response object in its place.

ReverseFilter

Proxying filter that relays the incoming request to a pipe.

About

asynchronous bidirectional pipeline aware server controlled web transport

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published