std.net.http.client.WebsocketRequest
type pub inline WebsocketRequestA type for upgrading an HTTP connection to a WebSocket connection.
Instance methods
header
Show source codeHide source code
fn pub move header(header: Header, value: String) -> Self {
@request.headers.add(header, value)
self
}fn pub move header(header: Header, value: String) -> WebsocketRequestAdds the header with the given value.
Refer to the documentation of std.net.http.HeaderMap.add for more details.
protocols
Show source codeHide source code
fn pub move protocols(values: Array[String]) -> Self {
for value in values { @protocols.insert(value) }
self
}fn pub move protocols(values: Array[String]) -> WebsocketRequestAdds the given protocols to the protocols supported by the server.
Examples
import std.net.http.client (Client)
import std.uri (Uri)
type async Main {
fn async main {
let client = Client.new
let uri = Uri.parse('https://echo.websocket.org').or_panic
client.websocket(uri).protocols(['foo', 'bar']).send.or_panic
}
}
query
Show source codeHide source code
fn pub move query(key: String, value: String) -> Self {
@request.query.add(key, value)
self
}fn pub move query(key: String, value: String) -> WebsocketRequestAdds a query string parameter and value to self.
Refer to the documentation of std.uri.Values.add for more details.
send
Show source codeHide source code
fn pub move send -> Result[
(Websocket[WebsocketConnection], Response),
WebsocketError,
] {
let buf = ByteArray.new
let key = ByteArray.new
let enc = Encoder.new
@request.client.random.bytes(into: buf, size: 16)
enc.encode(buf, into: key)
buf.clear
let key = key.into_string
enc.encode(Sha1.hash(key + WEBSOCKET_KEY).bytes, into: buf)
@request.headers.set(Header.connection, 'upgrade')
@request.headers.set(Header.upgrade, 'websocket')
@request.headers.set(Header.sec_websocket_key, key)
@request.headers.set(Header.sec_websocket_version, WEBSOCKET_VERSION)
if @protocols.size > 0 {
let proto = String.join(@protocols.iter, ', ')
@request.headers.set(Header.sec_websocket_protocol, proto)
}
let rng = @request.client.random
let (resp, con) = match @request.send_with_body('') {
case Ok(v) -> v
case Error(e) -> throw WebsocketError.Other(e)
}
match resp.status.to_int {
case
101
if header_eq(resp, Header.upgrade, 'websocket')
and header_eq(resp, Header.connection, 'upgrade')
and header_eq(resp, Header.sec_websocket_accept, buf)
-> {}
case 101 -> throw WebsocketError.InvalidHandshake
case _ -> throw WebsocketError.ServerError(resp.status)
}
# For websockets the connection is managed by the Websocket that we return,
# not the Response.
con.state = State.Websocket
# Extensions are not supported at this time.
if resp.headers.get(Header.sec_websocket_extensions).ok? {
throw WebsocketError.InvalidExtension
}
let proto = match resp.headers.get(Header.sec_websocket_protocol) {
case Ok(v) if @protocols.contains?(v) -> Option.Some(v.to_slice)
case Ok(_) -> throw WebsocketError.InvalidProtocol
case _ -> Option.None
}
let ws = Websocket.client(WebsocketConnection(con), rng, proto)
return Result.Ok((ws, resp))
}fn pub move send -> Result[(Websocket[WebsocketConnection], Response), WebsocketError]Sends the request and returns a websocket and its raw response.
The returned Response is the response returned by the server. This is
returned such that additional data (e.g. headers) can be used if necessary.
When the Websocket is dropped the underlying connection is closed.