Added a very complicated AsyncIterableReader class.
The class was already implemented in "https://deno.land/std@0.144.0/streams/conversion.ts". So, I litterally lost 1 day of work! I hate myself.
This commit is contained in:
1 parent
17a1b4bed3
commit
0d627c9051
125 files changed
+26943
-83
No files matched your search
@@ -0,0 +1,147 @@
|
||||
// Copyright 2018-2023 the oak authors. All rights reserved. MIT license.
|
||||
|
||||
import type {
|
||||
RequestEvent,
|
||||
ServerRequest,
|
||||
ServerRequestBody,
|
||||
UpgradeWebSocketFn,
|
||||
UpgradeWebSocketOptions,
|
||||
} from "./types.d.ts";
|
||||
|
||||
// deno-lint-ignore no-explicit-any
|
||||
export const DomResponse: typeof Response = (globalThis as any).Response ??
|
||||
class MockResponse {};
|
||||
|
||||
const maybeUpgradeWebSocket: UpgradeWebSocketFn | undefined =
|
||||
"upgradeWebSocket" in Deno
|
||||
// deno-lint-ignore no-explicit-any
|
||||
? (Deno as any).upgradeWebSocket.bind(Deno)
|
||||
: undefined;
|
||||
|
||||
export function isNativeRequest(r: ServerRequest): r is NativeRequest {
|
||||
return r instanceof NativeRequest;
|
||||
}
|
||||
|
||||
export interface NativeRequestOptions {
|
||||
conn?: Deno.Conn;
|
||||
upgradeWebSocket?: UpgradeWebSocketFn;
|
||||
}
|
||||
|
||||
/** An internal oak abstraction for handling a Deno native request. Most users
|
||||
* of oak do not need to worry about this abstraction. */
|
||||
export class NativeRequest implements ServerRequest {
|
||||
#conn?: Deno.Conn;
|
||||
// deno-lint-ignore no-explicit-any
|
||||
#reject!: (reason?: any) => void;
|
||||
#request: Request;
|
||||
#requestPromise: Promise<void>;
|
||||
#resolve!: (value: Response) => void;
|
||||
#resolved = false;
|
||||
#upgradeWebSocket?: UpgradeWebSocketFn;
|
||||
|
||||
constructor(
|
||||
requestEvent: RequestEvent,
|
||||
options: NativeRequestOptions = {},
|
||||
) {
|
||||
const { conn } = options;
|
||||
this.#conn = conn;
|
||||
// this allows for the value to be explicitly undefined in the options
|
||||
this.#upgradeWebSocket = "upgradeWebSocket" in options
|
||||
? options["upgradeWebSocket"]
|
||||
: maybeUpgradeWebSocket;
|
||||
this.#request = requestEvent.request;
|
||||
const p = new Promise<Response>((resolve, reject) => {
|
||||
this.#resolve = resolve;
|
||||
this.#reject = reject;
|
||||
});
|
||||
this.#requestPromise = requestEvent.respondWith(p);
|
||||
}
|
||||
|
||||
get body(): ReadableStream<Uint8Array> | null {
|
||||
// when shimming with undici under Node.js, this is a
|
||||
// `ControlledAsyncIterable`
|
||||
// deno-lint-ignore no-explicit-any
|
||||
return this.#request.body as any;
|
||||
}
|
||||
|
||||
get donePromise(): Promise<void> {
|
||||
return this.#requestPromise;
|
||||
}
|
||||
|
||||
get headers(): Headers {
|
||||
return this.#request.headers;
|
||||
}
|
||||
|
||||
get method(): string {
|
||||
return this.#request.method;
|
||||
}
|
||||
|
||||
get remoteAddr(): string | undefined {
|
||||
return (this.#conn?.remoteAddr as Deno.NetAddr)?.hostname;
|
||||
}
|
||||
|
||||
get request(): Request {
|
||||
return this.#request;
|
||||
}
|
||||
|
||||
get url(): string {
|
||||
try {
|
||||
const url = new URL(this.#request.url);
|
||||
return this.#request.url.replace(url.origin, "");
|
||||
} catch {
|
||||
// we don't care about errors, we just want to fall back
|
||||
}
|
||||
return this.#request.url;
|
||||
}
|
||||
|
||||
get rawUrl(): string {
|
||||
return this.#request.url;
|
||||
}
|
||||
|
||||
// deno-lint-ignore no-explicit-any
|
||||
error(reason?: any): void {
|
||||
if (this.#resolved) {
|
||||
throw new Error("Request already responded to.");
|
||||
}
|
||||
this.#reject(reason);
|
||||
this.#resolved = true;
|
||||
}
|
||||
|
||||
getBody(): ServerRequestBody {
|
||||
return {
|
||||
// when emitting to Node.js, the body is not compatible, and thought it
|
||||
// doesn't run at runtime, it still gets type checked.
|
||||
// deno-lint-ignore no-explicit-any
|
||||
body: this.#request.body as any,
|
||||
readBody: async () => {
|
||||
const ab = await this.#request.arrayBuffer();
|
||||
return new Uint8Array(ab);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
respond(response: Response): Promise<void> {
|
||||
if (this.#resolved) {
|
||||
throw new Error("Request already responded to.");
|
||||
}
|
||||
this.#resolve(response);
|
||||
this.#resolved = true;
|
||||
return this.#requestPromise;
|
||||
}
|
||||
|
||||
upgrade(options?: UpgradeWebSocketOptions): WebSocket {
|
||||
if (this.#resolved) {
|
||||
throw new Error("Request already responded to.");
|
||||
}
|
||||
if (!this.#upgradeWebSocket) {
|
||||
throw new TypeError("Upgrading web sockets not supported.");
|
||||
}
|
||||
const { response, socket } = this.#upgradeWebSocket(
|
||||
this.#request,
|
||||
options,
|
||||
);
|
||||
this.#resolve(response);
|
||||
this.#resolved = true;
|
||||
return socket;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user