Skip to content

Commit

Permalink
feat: add web socket upgrade method to context
Browse files Browse the repository at this point in the history
  • Loading branch information
kitsonk committed Jul 11, 2023
1 parent e1ed289 commit 4030953
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 2 deletions.
46 changes: 44 additions & 2 deletions context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,18 @@
* @module
*/

import { type SecureCookieMap, UserAgent } from "./deps.ts";
import { type Addr, type Deserializer } from "./types.ts";
import {
createHttpError,
type SecureCookieMap,
Status,
UserAgent,
} from "./deps.ts";
import {
type Addr,
type Deserializer,
type UpgradeWebSocketOptions,
type WebSocketUpgrade,
} from "./types.ts";

interface ContextOptions<BodyType, Params extends Record<string, string>> {
cookies: SecureCookieMap;
Expand Down Expand Up @@ -119,6 +129,38 @@ export class Context<
return this.#body;
}

/** Attempt to upgrade the request to a web socket, returning the socket and
* the response to be returned.
*
* ## Example
*
* ```ts
* import { Router } from "https://deno.land/x/acorn/mod.ts";
*
* const router = new Router();
*
* router.get("/ws", (ctx) => {
* const { socket, response } = ctx.upgrade();
* // Perform actions with the socket.
* return response;
* });
*
* router.listen({ port: 8000 });
* ```
*
* @param options
* @returns
*/
upgrade(options?: UpgradeWebSocketOptions): WebSocketUpgrade {
if (!Deno || !("upgradeWebSocket" in Deno)) {
throw createHttpError(
Status.ServiceUnavailable,
"Web sockets not supported.",
);
}
return Deno.upgradeWebSocket(this.#request, options);
}

/** Returns the request URL as a parsed {@linkcode URL} object. */
url(): URL {
if (!this.#url) {
Expand Down
25 changes: 25 additions & 0 deletions types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,28 @@ export interface HttpConn extends AsyncIterable<RequestEvent> {
nextRequest(): Promise<RequestEvent | null>;
close(): void;
}

export interface UpgradeWebSocketOptions {
/** Sets the `.protocol` property on the client side web socket to the
* value provided here, which should be one of the strings specified in the
* `protocols` parameter when requesting the web socket. This is intended
* for clients and servers to specify sub-protocols to use to communicate to
* each other. */
protocol?: string;
/** If the client does not respond to this frame with a
* `pong` within the timeout specified, the connection is deemed
* unhealthy and is closed. The `close` and `error` event will be emitted.
*
* The default is 120 seconds. Set to `0` to disable timeouts. */
idleTimeout?: number;
}

export interface WebSocketUpgrade {
/** The response object that represents the HTTP response to the client,
* which should be used to the {@linkcode RequestEvent} `.respondWith()` for
* the upgrade to be successful. */
response: Response;
/** The {@linkcode WebSocket} interface to communicate to the client via a
* web socket. */
socket: WebSocket;
}

0 comments on commit 4030953

Please sign in to comment.