Skip to content

Instantly share code, notes, and snippets.

@tobias

tobias/foo.clj Secret

Created January 20, 2015 17:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tobias/d1270180f4857826af1e to your computer and use it in GitHub Desktop.
Save tobias/d1270180f4857826af1e to your computer and use it in GitHub Desktop.
(defprotocol Channel
"Streaming channel interface"
(open? [ch] "Is the channel open?")
(close [ch]
"Gracefully close the channel.
This will trigger the :on-close callback if one is registered. with
[[as-channel]].")
(handshake [ch]
"Returns a [[WebsocketHandshake]] for `ch` if `ch` is a WebSocket channel.")
(send! [ch message & options]
"Send a message to the channel.
`message` can either be a String or byte[].
The following options are supported [default]:
* :close? - if `true`, the channel will be closed when the send completes.
Setting this to `true` 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-complete - `(fn [] ...)` - called when the send has completed [nil]
* :on-error - `(fn [throwable] ...)` - called when an error occurs on the
send. For HTTP stream channels, this includes when the client closes the
connection before the server does (which will also trigger a call to
the :on-close handler of [[as-channel]]) [nil]
Sending is asynchronous for WebSockets, but blocking for
HTTP channels. TODO: this may change to all-async
Returns nil if the channel is closed when the send is initiated, true
otherwise."))
(defn as-channel
"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, a Websocket channel will be created.
Otherwise, an HTTP stream channel is created. You interact with both
channel types through the [[Channel]] protocol, and through the
given `callbacks`.
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-close - `(fn [ch {:keys [code reason]}] ...)` -
called for *any* close, including a call to [[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. Both will be nil for
HTTP streams.
If the channel is a Websocket, the following callbacks are also used:
* :on-message - `(fn [ch message] ...)` - Called for each message
from the client. `message` will be a `String` or `byte[]`
* :on-error - `(fn [ch throwable] ...)` - Called for any error
that occurs outside of a [[send!]] call. To handle `send!` errors,
provide an error callback to it.
TODO: discuss: sessions, headers, ws vs http diffs (utf8, no headers)
provide usage example
Returns a ring response map, at least the :body of which *must* be
returned in the response map from the calling ring handler."
[request & callbacks]
...)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment