immutant.web.async
Provides a common interface for WebSockets and HTTP streaming.
as-channel
(as-channel request & options)
Converts the current ring request
in to an asynchronous channel.
The type of channel created depends on the request - if the request is a Websocket upgrade request (the :websocket?
key is true), a Websocket channel will be created. Otherwise, an HTTP stream channel is created. You interact with both channel types using the other functions in this namespace, and through callbacks in options
.
The callbacks common to both channel types are:
:on-open
-(fn [ch] ...)
- called when the channel is available for sending. Will only be invoked once.:on-error
-(fn [ch throwable] ...)
- Called for any error that occurs in relation to the channel. If the error requires the channel to be closed,:on-close
will also be invoked. To handlesend!
errors separately, provide it a completion callback.:on-close
-(fn [ch {
- called for any close, including a call to:keys
[code reason]}] ...)close
, but will only be invoked once.ch
will already be closed by the time this is invoked.
code
and reason
will be the numeric closure code and text reason, respectively, if the channel is a WebSocket (see http://tools.ietf.org/html/rfc6455#section-7.4). Both will be nil for HTTP streams.
If the channel is a Websocket, the following callback is also used:
:on-message
-(fn [ch message] ...)
- Called for each message from the client.message
will be aString
orbyte[]
You can also specify a
option, that will cause a Websocket to be closed if idle more than the timeout, or an HTTP stream to be closed if open more than the timeout. This means that once opened, an HTTP stream will be closed after :timeout
:timeout
elapses, regardless of activity. It defaults to 0 (no timeout), and is in milliseconds.
When the ring handler is called during a WebSocket upgrade request, any changes to the session in the response map are applied, and any headers from the response map are included in the upgrade response.
Returns a ring response map, at least the :body
of which must be returned in the response map from the calling ring handler.
close
(close ch)
Gracefully close the channel.
This will trigger the :on-close
callback if one is registered with as-channel
.
originating-request
(originating-request ch)
Returns the request map for the request that initiated the channel.
send!
(send! ch message & options)
Send a message to the channel, asynchronously.
message
can either be a String
, File
, InputStream
, ISeq
, byte[]
, or map. If it is a String
, it will be encoded to the character set of the response for HTTP streams, and as UTF-8 for WebSockets. File
s and InputStream
s will be sent as up to 16k chunks (each chunk being a byte[]
message for WebSockets). Each item in an ISeq
will pass through send!
, and can be any of the valid message types.
If message
is a map, its :body
entry must be one of the other valid message types, and its :status
and :headers
entries will be used to override the status or headers returned from the handler that called as-channel
for HTTP streams. A map is only a valid message on the first send to an HTTP stream channel - an exception is thrown if it is passed on a subsequent send or passed to a WebSocket channel.
The following options are supported [default]:
:close?
- iftrue
, the channel will be closed when the send completes. Setting this totrue
on the first send to an HTTP stream channel will cause it to behave like a standard HTTP response, and not chunk the response. [false]:on-success
-(fn [] ...)
- called when the send attempt has completed successfully. If this callback throws an exception, it will be reported to theas-channel
:on-error
callback [nil]:on-error
-(fn [throwable] ...)
- Called when an error occurs on the send. If the error requires the channel to be closed, theas-channel
:on-close
callback will also be invoked. If this callback throws an exception, it will be reported to theas-channel
:on-error
callback [#(throw %)
]
Returns nil if the channel is closed when the send is initiated, true otherwise. If the channel is already closed, :on-success
won’t be invoked.