122 lines
4.9 KiB
Racket
122 lines
4.9 KiB
Racket
#lang scribble/doc
|
|
@(require "common.ss"
|
|
scribble/bnf
|
|
(for-label net/url
|
|
unstable/contract
|
|
web-server/http
|
|
racket/list
|
|
racket/async-channel
|
|
(prefix-in raw: (for-label net/tcp-unit))
|
|
net/websocket
|
|
net/websocket/client
|
|
net/websocket/server
|
|
net/websocket/conn))
|
|
|
|
@title[#:tag "websocket"]{WebSocket}
|
|
|
|
@defmodule[net/websocket]
|
|
|
|
The @racketmodname[net/websocket] library provides
|
|
utilities to run and communicate with WebSocket servers,
|
|
as specified in @link["http://www.whatwg.org/specs/web-socket-protocol/"]{the WebSocket protocol} IETF draft
|
|
as of August 16th, 2010.
|
|
|
|
This module provides the exports from @racketmodname[net/websocket/client] and @racketmodname[net/websocket/server].
|
|
|
|
@section{Client API}
|
|
|
|
@defmodule[net/websocket/client]
|
|
|
|
@defproc[(ws-url? [x any/c]) boolean?]{ Returns true if @racket[x] is a @racket[url?] and has a @racket[url-scheme] equal to @litchar["ws"] or @litchar["wss"]. }
|
|
|
|
@defproc[(wss-url? [x any/c]) boolean?]{ Returns true if @racket[x] is a @racket[url?] and has a @racket[url-scheme] equal to @litchar["wss"]. }
|
|
|
|
@defproc[(ws-connect [u ws-url?]
|
|
[#:headers headers (listof header?) empty])
|
|
open-ws-conn?]{
|
|
Connects to the WebSocket server specified by @racket[u], providing @racket[headers] as additional headers.
|
|
Returns the connection handle.
|
|
}
|
|
|
|
This module also provides the exports from @racketmodname[net/websocket/conn].
|
|
|
|
@section{Server API}
|
|
|
|
@defmodule[net/websocket/server]
|
|
|
|
@defproc[(ws-serve [conn-handle (open-ws-conn? any/c . -> . void)]
|
|
[#:conn-headers
|
|
conn-headers
|
|
(bytes? (listof header?) . -> . (values (listof header?) any/c))
|
|
(λ (b hs) (values empty (void)))]
|
|
[#:tcp@ tcp@ (unit/c (import) (export tcp^)) raw:tcp@]
|
|
[#:port port tcp-listen-port? 80]
|
|
[#:listen-ip listen-ip (or/c string? false/c) #f]
|
|
[#:max-waiting max-waiting integer? 4]
|
|
[#:timeout timeout integer? (* 60 60)]
|
|
[#:confirmation-channel
|
|
confirm-ch
|
|
(or/c false/c async-channel?)
|
|
#f])
|
|
(-> void)]{
|
|
|
|
Starts a WebSocket server where each new connection uses @racket[conn-headers] to compute
|
|
what headers the client receives based on the client's request line and headers. @racket[conn-headers]
|
|
also returns a piece of state that will be passed to @racket[conn-handle] as its second argument.
|
|
After the connection handshake is finished, @racket[conn-handle] receives the connection and is in
|
|
sole control until the WebSocket connection completes.
|
|
|
|
All other arguments are used as in a @secref["dispatch-server-unit" #:doc '(lib "web-server/scribblings/web-server-internal.scrbl")].
|
|
|
|
The @racket[#:tcp@] keyword is provided for building an SSL server.
|
|
}
|
|
|
|
This module also provides the exports from @racketmodname[net/websocket/conn].
|
|
|
|
@section{Connections}
|
|
|
|
@defmodule[net/websocket/conn]
|
|
|
|
@defparam[framing-mode mode (symbols 'old 'new)]{ Controls whether framing is as before August 16th, 2010 or after. (Most Web browsers currently support only @racket['old] and they are incompatible, so you must choose the correct one.) Defaults to @racket['old].}
|
|
|
|
@defproc[(ws-conn? [x any/c]) boolean?]{ Returns true if @racket[x] is a WebSocket connection. }
|
|
|
|
@defproc[(open-ws-conn? [x any/c]) boolean?]{ Returns true if @racket[x] is an open WebSocket connection. }
|
|
|
|
@defproc[(ws-conn-line [ws ws-conn?]) bytes?]{ Returns the request/response line of the WebSocket connection. }
|
|
@defproc[(ws-conn-closed? [ws ws-conn?]) boolean?]{ Returns true if the WebSocket connection has been closed. }
|
|
@defproc[(ws-conn-headers [ws ws-conn?]) (listof header?)]{ Returns the headers of the WebSocket connection. }
|
|
|
|
WebSocket connection support only blocking calls:
|
|
|
|
@defproc[(ws-send! [ws open-ws-conn?] [s string?]) void]{ Sends @racket[s] over @racket[ws]. }
|
|
@defproc[(ws-recv [ws open-ws-conn?]) (or/c string? eof-object?)]{ Receives a string from @racket[ws]. Returns @racket[eof] if the other end closes the connection. }
|
|
|
|
@defproc[(ws-close! [ws open-ws-conn?]) void]{ Closes @racket[ws]. }
|
|
|
|
@section{Example}
|
|
|
|
This is a WebSocket echo server compatible with the browser origin security model:
|
|
|
|
@racketblock[
|
|
(ws-serve
|
|
#:port 8080
|
|
(λ (wsc _)
|
|
(let loop ()
|
|
(define m (ws-recv wsc))
|
|
(printf "~a\n" m)
|
|
(unless (eof-object? m)
|
|
(ws-send! wsc m)
|
|
(loop))))
|
|
#:conn-headers
|
|
(λ (_ hs)
|
|
(define origin
|
|
(header-value (headers-assq* #"Origin" hs)))
|
|
(values
|
|
(list
|
|
(make-header #"Sec-WebSocket-Origin" origin)
|
|
(make-header #"Sec-WebSocket-Location"
|
|
#"ws://localhost:8080/"))
|
|
#f)))
|
|
]
|