Silk

silk/websocket_upgrade

Profiles: aarch64-apple-darwin, aarch64-unknown-linux-gnu, aarch64-unknown-linux-gnu-no-libc, wasm32-unknown-unknown, x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu-no-libc.

Bounded WebSocket server handshake inspection and explicit application acceptance.

Details

inspect borrows a parsed HTTP head without allocation. withUpgrade runs the application decision before output, flushes the switching response, then lends the existing buffered channel. Origin is policy input, not authentication. Valid extension offers are declined; frames and compression are outside this module.

Import as WebSocketUpgrade with import silk.websocket_upgrade as WebSocketUpgrade.

Public declarations: 14.

Limits

pub struct Limits

Finite handshake budgets. Zero forbids the corresponding resource.

Field maxProtocols

pub maxProtocols: usize

Maximum offered subprotocol tokens across all fields.

Field maxProtocolBytes

pub maxProtocolBytes: usize

Maximum bytes in each offered subprotocol token.

Field maxExtensionBytes

pub maxExtensionBytes: usize

Maximum aggregate extension field-value bytes.

Field maxResponseBytes

pub maxResponseBytes: usize

Maximum serialized response bytes, including generated fields.

Field maxOwnedBytes

pub maxOwnedBytes: usize

Maximum simultaneous owned payload and index capacities for the response plan.

Associated function Limits.default

pub fn default() -> Limits

Returns the default finite handshake budgets.

Details

The defaults are 32 protocols, 128 token bytes, 4096 extension bytes, 8192 response bytes, and 16384 owned bytes.

Implementation Copy for Limits

impl Copy for Limits

ValidationReason

pub enum ValidationReason

The peer-input rule that rejected an offer.

Request

Request = 0

The method or HTTP version is unsupported.

Singleton

Singleton = 1

A required field is absent or a singleton field repeats.

Host

Host = 2

Host is not a valid HTTP authority.

Tokens

Tokens = 3

A comma-token field has invalid syntax or lacks a required token.

ConnectionClose

ConnectionClose = 4

Connection explicitly requests closure.

Version

Version = 5

The version field has invalid decimal syntax.

Key

Key = 6

The key is not canonical padded Base64 for sixteen bytes.

Body

Body = 7

Request framing permits a nonempty body.

Expect

Expect = 8

An Expect field is present.

Origin

Origin = 9

Origin is not one serialized HTTP(S) origin or null.

DuplicateProtocol

DuplicateProtocol = 10

A subprotocol token occurs more than once.

Extensions

Extensions = 11

The extension field grammar is malformed.

LimitKind

pub enum LimitKind

The finite budget that rejected the handshake.

Protocols

Protocols = 0

Too many offered protocols.

ProtocolBytes

ProtocolBytes = 1

An offered protocol is too long.

ExtensionBytes

ExtensionBytes = 2

Extension fields exceed their aggregate budget.

ResponseBytes

ResponseBytes = 3

Serialized response bytes exceed the budget.

OwnedBytes

OwnedBytes = 4

Owned capacities exceed the budget.

SizeOverflow

SizeOverflow = 5

Checked size arithmetic overflowed.

DecisionReason

pub enum DecisionReason

The application decision rule that failed before output.

Protocol

Protocol = 0

The selected protocol is not exactly one offered token.

Header = 1

An extra response field overrides a generated or framing field.

Status

Status = 2

Application rejection must use a final response status.

UpgradeError

pub union UpgradeError

A typed inspection or decision failure. No variant writes a response by itself.

Validation

UpgradeError.Validation { reason: ValidationReason }: UpgradeError

Peer metadata violates the selected WebSocket handshake profile.

Field reason

pub reason: ValidationReason

The failed peer-input rule.

UnsupportedVersion

UpgradeError.UnsupportedVersion { supported: u16 }: UpgradeError

A well-formed version is unsupported; the server supports version 13.

Field supported

pub supported: u16

The supported protocol version, always 13.

Limit

UpgradeError.Limit { kind: LimitKind }: UpgradeError

A finite budget or checked size operation failed.

Field kind

pub kind: LimitKind

The exceeded budget or overflow category.

InvalidDecision

UpgradeError.InvalidDecision { reason: DecisionReason }: UpgradeError

Application acceptance cannot be serialized as a valid handshake.

Field reason

pub reason: DecisionReason

The failed application decision rule.

UnsupportedNegotiation

UpgradeError.UnsupportedNegotiation: UpgradeError

Application acceptance requested an unimplemented extension.

Value

UpgradeError.Value { error: ValueError }: UpgradeError

Shared HTTP value validation rejected response metadata.

Field error

pub error: ValueError

The original structured HTTP value failure.

Offer

pub struct Offer<'head>

Validated metadata that borrows one parsed request and cannot authorize another request.

Method Offer.target

pub fn target<'head, 'life1>(self: &'life1 Offer<'head>) -> silk/http_target.RequestTarget<'head>

Returns the request target borrowed from the parsed head.

Method Offer.host

pub fn host<'head, 'life1>(self: &'life1 Offer<'head>) -> &'head [u8]

Returns the validated Host field bytes.

Method Offer.origin

pub fn origin<'head, 'life1>(self: &'life1 Offer<'head>) -> silk/option.Option<&'head [u8]>

Returns absent Origin or its exact validated bytes, including literal null.

Method Offer.protocolCount

pub fn protocolCount<'head, 'life1>(self: &'life1 Offer<'head>) -> usize

Returns the number of unique protocols in combined wire order.

Method Offer.protocolAt

pub fn protocolAt<'head, 'life1>(self: &'life1 Offer<'head>, index: usize) -> silk/option.Option<&'head [u8]>

Returns one protocol by combined wire index, or None for an absent index.

Method Offer.extensionsPresent

pub fn extensionsPresent<'head, 'life1>(self: &'life1 Offer<'head>) -> bool

Returns whether at least one syntactically valid extension field was supplied.

Method Offer.acceptInto

pub fn acceptInto<'head, 'life1, 'life2>(self: &'life1 Offer<'head>, output: &'life2 mut [u8]) -> silk/result.Result<usize, silk/websocket_upgrade.UpgradeError>

Writes the 28-byte accept value into caller storage without allocation.

acceptInto

pub fn acceptInto<'life0, 'life1>(key: &'life0 [u8], output: &'life1 mut [u8]) -> silk/result.Result<usize, silk/websocket_upgrade.UpgradeError>

Validates a canonical sixteen-byte WebSocket key and writes its 28-byte accept value.

Details

This pure transformation trims outer HTTP OWS and hashes the original encoded key. It does not authorize an upgrade. Invalid input or insufficient output capacity leaves output unchanged.

Outcome

pub union Outcome<A>

The completed handshake outcome, including ordinary application rejection.

Upgraded

Outcome<A>.Upgraded { value: A }: Outcome<A>

The upgraded channel callback completed successfully.

Field value

pub value: A

The callback's result.

Rejected

Outcome<A>.Rejected { status: u16 }: Outcome<A>

The application rejection was sent as an ordinary HTTP response.

Field status

pub status: u16

The sent HTTP status code.

Decision

pub union Decision<'value>

An explicit application decision whose values borrow the scoped policy or request offer.

Accept

Decision<'value>.Accept { protocol: silk/option.Option<string<'value>>, headers: silk/option.Option<silk/http_headers.Headers<'value>>, extensions: bool }: Decision<'value>

Accepts an optional offered protocol and ordinary response headers. Extensions must be false.

Field protocol

pub protocol: silk/option.Option<string<'value>>

No protocol, or exactly one case-sensitive offered token.

Field headers

pub headers: silk/option.Option<silk/http_headers.Headers<'value>>

Validated extra fields; repeated ordinary fields remain in order.

Field extensions

pub extensions: bool

Requests extension negotiation. True fails with UnsupportedNegotiation.

Reject

Decision<'value>.Reject { status: Status, headers: silk/option.Option<silk/http_headers.Headers<'value>> }: Decision<'value>

Sends an ordinary final body-free rejection and does not lend the channel.

Field status

pub status: Status

The application-selected final HTTP status.

Field headers

pub headers: silk/option.Option<silk/http_headers.Headers<'value>>

Optional ordinary response fields, including authentication headers.

DecisionHandler

pub interface DecisionHandler<D, ?R>

A compile-time policy that makes one explicit decision from a scoped request offer.

Operation decide

effect<'call> fn decide<'call: 'call, 'head: 'call>(handler: &'call Self, offer: &'call silk/websocket_upgrade.Offer<'head>) -> silk/websocket_upgrade.Decision<'call> ! D ? R

Borrows policy and offer data for one decision and preserves failure and requirement channels.

inspect

pub fn inspect<'head, 'life1>(head: &'life1 silk/http_head.RequestHead<'head>, limits: Limits) -> silk/result.Result<silk/websocket_upgrade.Offer<'head>, silk/websocket_upgrade.UpgradeError>

Validates one borrowed parsed request without allocation or ambient services.

rejectionStatus

pub fn rejectionStatus<'life0>(error: &'life0 silk/websocket_upgrade.UpgradeError) -> u16

Returns the default rejection status without writing: 417 for Expect, 426 for version, otherwise 400.

withUpgrade

pub effect<'env> fn withUpgrade<'loan: 'env, 'request: 'loan + 'env, 'connection: 'request + 'env, 'transport: 'connection + 'env, 'callback: 'env, A, D, E, ?DecisionRequirements, ?CallbackRequirements, P: 'env, H: 'env, 'env>(request: &'loan mut silk/http_server.Request<'request, 'connection, 'transport, P>, limits: Limits, deadline: silk/option.Option<silk/system_clock.Instant>, handler: H, use: for<'call, 'transportView: 'call> once fn<'callback>(&'call mut silk/buffered_duplex.BufferedDuplex<'transportView, P>) -> once Effect<'call; A ! E ? CallbackRequirements>) -> silk/websocket_upgrade.Outcome<A> ! D | E | UpgradeError | ServerError | OutOfMemoryError ? DecisionRequirements | CallbackRequirements | &mut Allocator | &mut MonotonicClock where &mut P provides &ByteDuplex from &mut ByteDuplex | &mut MonotonicClock

Runs explicit acceptance and lends the existing channel only after the complete 101 flush.

Details

The decision borrows the policy or current offer. The operation copies its response before the HTTP handoff, so borrowed metadata cannot escape the handshake. Rejected retains the sent application status. Errors before output leave HTTP active. Use the same absolute deadline for the enclosing HTTP request acquisition.

Gotchas

After switching output starts, transport failure is terminal. The enclosing server scope keeps its close authority armed. This operation provides no frame or native TLS server implementation.

reject

pub effect<'env> fn reject<'loan: 'env, 'request: 'loan + 'env, 'connection: 'request + 'env, 'transport: 'connection + 'env, P: 'env, 'life5: 'env, 'env>(request: &'loan mut silk/http_server.Request<'request, 'connection, 'transport, P>, error: &'life5 silk/websocket_upgrade.UpgradeError, limits: Limits, deadline: silk/option.Option<silk/system_clock.Instant>) -> () ! UpgradeError | ServerError | OutOfMemoryError ? &mut Allocator | &mut MonotonicClock where &mut P provides &ByteDuplex from &mut ByteDuplex | &mut MonotonicClock

Sends the deterministic body-free HTTP rejection for a typed handshake failure.

Details

UnsupportedVersion sends 426 with Sec-WebSocket-Version: 13. Expect sends 417; other failures send 400. This operation is available only before switching output starts.

On this page