mirror of
https://github.com/denoland/deno.git
synced 2025-03-03 09:31:22 -05:00
feat(unstable): change Deno.serve() API (#15498)
- Merge "Deno.serve()" and "Deno.serveTls()" API - Remove first argument and use "fetch" field options instead - Update type declarations - Add more documentation
This commit is contained in:
parent
1848c7e361
commit
5beec3f106
12 changed files with 353 additions and 330 deletions
|
@ -7,4 +7,4 @@ const [hostname, port] = addr.split(":");
|
|||
const app = new Hono();
|
||||
app.get("/", (c) => c.text("Hello, World!"));
|
||||
|
||||
Deno.serve(app.fetch, { port: Number(port), hostname });
|
||||
Deno.serve({ fetch: app.fetch, port: Number(port), hostname });
|
||||
|
|
|
@ -6,9 +6,9 @@ const { serve } = Deno;
|
|||
|
||||
const path = new URL("../testdata/128k.bin", import.meta.url).pathname;
|
||||
|
||||
function handler() {
|
||||
function fetch() {
|
||||
const file = Deno.openSync(path);
|
||||
return new Response(file.readable);
|
||||
}
|
||||
|
||||
serve(handler, { hostname, port: Number(port) });
|
||||
serve({ fetch, hostname, port: Number(port) });
|
||||
|
|
|
@ -4,11 +4,12 @@ const addr = Deno.args[0] || "127.0.0.1:4500";
|
|||
const [hostname, port] = addr.split(":");
|
||||
const { serve } = Deno;
|
||||
|
||||
function handler() {
|
||||
function fetch() {
|
||||
return new Response("Hello World");
|
||||
}
|
||||
|
||||
serve(handler, {
|
||||
serve({
|
||||
fetch,
|
||||
hostname,
|
||||
port,
|
||||
});
|
||||
|
|
|
@ -19,8 +19,11 @@ const headers = {
|
|||
};
|
||||
|
||||
serve(
|
||||
async () => {
|
||||
return new Response(await renderToReadableStream(<App />), headers);
|
||||
{
|
||||
fetch: async () => {
|
||||
return new Response(await renderToReadableStream(<App />), headers);
|
||||
},
|
||||
hostname,
|
||||
port,
|
||||
},
|
||||
{ hostname, port },
|
||||
);
|
||||
|
|
5
cli/bench/testdata/deno_upgrade_http.js
vendored
5
cli/bench/testdata/deno_upgrade_http.js
vendored
|
@ -1,13 +1,14 @@
|
|||
const { serve, upgradeHttp } = Deno;
|
||||
const u8 = Deno.core.encode("HTTP/1.1 101 Switching Protocols\r\n\r\n");
|
||||
|
||||
async function handler(req) {
|
||||
async function fetch(req) {
|
||||
const [conn, _firstPacket] = upgradeHttp(req);
|
||||
await conn.write(u8);
|
||||
await conn.close();
|
||||
}
|
||||
|
||||
serve(handler, {
|
||||
serve({
|
||||
fetch,
|
||||
hostname: "127.0.0.1",
|
||||
port: 9000,
|
||||
});
|
||||
|
|
|
@ -64,7 +64,6 @@ const UNSTABLE_DENO_PROPS: &[&str] = &[
|
|||
"ChildStatus",
|
||||
"SpawnOutput",
|
||||
"serve",
|
||||
"serveTls",
|
||||
"ServeInit",
|
||||
"ServeTlsInit",
|
||||
"Handler",
|
||||
|
|
125
cli/dts/lib.deno.unstable.d.ts
vendored
125
cli/dts/lib.deno.unstable.d.ts
vendored
|
@ -1211,29 +1211,27 @@ declare namespace Deno {
|
|||
*/
|
||||
export function unrefTimer(id: number): void;
|
||||
|
||||
/**
|
||||
* A handler for HTTP requests. Consumes a request and returns a response.
|
||||
*
|
||||
* Handler allows `void` or `Promise<void>` return type to enable
|
||||
* request upgrades using `Deno.upgradeHttp()` API. It is callers responsibility
|
||||
* to write response manually to the returned connection. Failing to do so
|
||||
* (or not returning a response without an upgrade) will cause the connection
|
||||
* to hang.
|
||||
*
|
||||
* If a handler throws, the server calling the handler will assume the impact
|
||||
* of the error is isolated to the individual request. It will catch the error
|
||||
* and close the underlying connection.
|
||||
*
|
||||
* @category HTTP Server
|
||||
*/
|
||||
export type ServeHandler = (
|
||||
request: Request,
|
||||
) => Response | Promise<Response> | void | Promise<void>;
|
||||
|
||||
/**
|
||||
* @category HTTP Server
|
||||
*/
|
||||
export interface ServeInit extends Partial<Deno.ListenOptions> {
|
||||
/**
|
||||
* A handler for HTTP requests. Consumes a request and returns a response.
|
||||
*
|
||||
* Handler allows `void` or `Promise<void>` return type to enable
|
||||
* request upgrades using `Deno.upgradeHttp()` API. It is callers responsibility
|
||||
* to write response manually to the returned connection. Failing to do so
|
||||
* (or not returning a response without an upgrade) will cause the connection
|
||||
* to hang.
|
||||
*
|
||||
* If a handler throws, the server calling the handler will assume the impact
|
||||
* of the error is isolated to the individual request. It will catch the error
|
||||
* and close the underlying connection.
|
||||
*/
|
||||
fetch: (
|
||||
request: Request,
|
||||
) => Response | Promise<Response> | void | Promise<void>;
|
||||
|
||||
/** An AbortSignal to close the server and all connections. */
|
||||
signal?: AbortSignal;
|
||||
|
||||
|
@ -1263,14 +1261,36 @@ declare namespace Deno {
|
|||
* The below example serves with the port 9000.
|
||||
*
|
||||
* ```ts
|
||||
* Deno.serve((_req) => new Response("Hello, world"));
|
||||
* Deno.serve({
|
||||
* fetch: (_req) => new Response("Hello, world")
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* You can change the listening address by the `hostname` and `port` options.
|
||||
* The below example serves with the port 3000.
|
||||
*
|
||||
* ```ts
|
||||
* Deno.serve((_req) => new Response("Hello, world"), { port: 3000 });
|
||||
* Deno.serve({
|
||||
* fetch: (_req) => new Response("Hello, world"),
|
||||
* port: 3000
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* You can close the server by passing a `signal` option. To wait for the server
|
||||
* to close, await the promise returned from the `Deno.serve` API.
|
||||
*
|
||||
* ```ts
|
||||
* const ac = new AbortController();
|
||||
*
|
||||
* Deno.serve({
|
||||
* fetch: (_req) => new Response("Hello, world"),
|
||||
* signal: ac.signal
|
||||
* }).then(() => {
|
||||
* console.log("Server closed");
|
||||
* });
|
||||
*
|
||||
* console.log("Closing server...");
|
||||
* ac.abort();
|
||||
* ```
|
||||
*
|
||||
* `Deno.serve` function prints the message `Listening on http://<hostname>:<port>/`
|
||||
|
@ -1278,7 +1298,8 @@ declare namespace Deno {
|
|||
* `onListen` option to override it.
|
||||
*
|
||||
* ```ts
|
||||
* Deno.serve((_req) => new Response("Hello, world"), {
|
||||
* Deno.serve({
|
||||
* fetch: (_req) => new Response("Hello, world"),
|
||||
* onListen({ port, hostname }) {
|
||||
* console.log(`Server started at http://${hostname}:${port}`);
|
||||
* // ... more info specific to your server ..
|
||||
|
@ -1286,57 +1307,23 @@ declare namespace Deno {
|
|||
* });
|
||||
* ```
|
||||
*
|
||||
* @param handler The handler for individual HTTP requests.
|
||||
* @param options The options. See `ServeInit` documentation for details.
|
||||
* To enable TLS you must specify `key` and `cert` options.
|
||||
*
|
||||
* ```ts
|
||||
* const cert = "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n";
|
||||
* const key = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n";
|
||||
* Deno.serve({
|
||||
* fetch: (_req) => new Response("Hello, world"),
|
||||
* cert,
|
||||
* key
|
||||
* });
|
||||
*
|
||||
* @param options The options. See `ServeInit` and `ServeTlsInit` documentation for details.
|
||||
*
|
||||
* @category HTTP Server
|
||||
*/
|
||||
export function serve(
|
||||
handler: ServeHandler,
|
||||
options?: ServeInit,
|
||||
): Promise<void>;
|
||||
|
||||
/** Serves HTTPS requests with the given handler.
|
||||
*
|
||||
* You must specify `key` and `cert` options.
|
||||
*
|
||||
* You can specify an object with a port and hostname option, which is the
|
||||
* address to listen on. The default is port 9000 on hostname "127.0.0.1".
|
||||
*
|
||||
* The below example serves with the default port 8443.
|
||||
*
|
||||
* ```ts
|
||||
* const cert = "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n";
|
||||
* const key = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n";
|
||||
* Deno.serveTls((_req) => new Response("Hello, world"), { cert, key });
|
||||
*
|
||||
* ```
|
||||
*
|
||||
* `Deno.serveTls` function prints the message `Listening on https://<hostname>:<port>/`
|
||||
* on start-up by default. If you like to change this message, you can specify
|
||||
* `onListen` option to override it.
|
||||
*
|
||||
* ```ts
|
||||
* const cert = "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n";
|
||||
* const key = "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n";
|
||||
* Deno.serveTls((_req) => new Response("Hello, world"), {
|
||||
* cert,
|
||||
* key,
|
||||
* onListen({ port, hostname }) {
|
||||
* console.log(`Server started at https://${hostname}:${port}`);
|
||||
* // ... more info specific to your server ..
|
||||
* },
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* @param handler The handler for individual HTTPS requests.
|
||||
* @param options The options. See `ServeTlsInit` documentation for details.
|
||||
*
|
||||
* @category HTTP Server
|
||||
*/
|
||||
export function serveTls(
|
||||
handler: ServeHandler,
|
||||
options?: ServeTlsInit,
|
||||
options?: ServeInit | ServeTlsInit,
|
||||
): Promise<void>;
|
||||
|
||||
/** **UNSTABLE**: new API, yet to be vetter.
|
||||
|
|
|
@ -41,15 +41,16 @@ Deno.test({ permissions: { net: true } }, async function httpServerBasic() {
|
|||
const promise = deferred();
|
||||
const listeningPromise = deferred();
|
||||
|
||||
const server = Deno.serve(async (request) => {
|
||||
// FIXME(bartlomieju):
|
||||
// make sure that request can be inspected
|
||||
console.log(request);
|
||||
assertEquals(new URL(request.url).href, "http://127.0.0.1:4501/");
|
||||
assertEquals(await request.text(), "");
|
||||
promise.resolve();
|
||||
return new Response("Hello World", { headers: { "foo": "bar" } });
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (request) => {
|
||||
// FIXME(bartlomieju):
|
||||
// make sure that request can be inspected
|
||||
console.log(request);
|
||||
assertEquals(new URL(request.url).href, "http://127.0.0.1:4501/");
|
||||
assertEquals(await request.text(), "");
|
||||
promise.resolve();
|
||||
return new Response("Hello World", { headers: { "foo": "bar" } });
|
||||
},
|
||||
port: 4501,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -80,12 +81,13 @@ Deno.test(
|
|||
const ac = new AbortController();
|
||||
|
||||
let headers: Headers;
|
||||
const server = Deno.serve(async (request) => {
|
||||
await request.text();
|
||||
headers = request.headers;
|
||||
promise.resolve();
|
||||
return new Response("");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (request) => {
|
||||
await request.text();
|
||||
headers = request.headers;
|
||||
promise.resolve();
|
||||
return new Response("");
|
||||
},
|
||||
port: 2333,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -116,12 +118,13 @@ Deno.test(
|
|||
const listeningPromise = deferred();
|
||||
|
||||
let req: Request;
|
||||
const server = Deno.serve(async (request) => {
|
||||
await request.text();
|
||||
req = request;
|
||||
promise.resolve();
|
||||
return new Response("Hello World");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (request) => {
|
||||
await request.text();
|
||||
req = request;
|
||||
promise.resolve();
|
||||
return new Response("Hello World");
|
||||
},
|
||||
port: 2334,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -159,11 +162,12 @@ Deno.test(
|
|||
const ac = new AbortController();
|
||||
const listeningPromise = deferred();
|
||||
|
||||
const server = Deno.serve((request) => {
|
||||
assertEquals(request.body, null);
|
||||
promise.resolve();
|
||||
return new Response("", { headers: {} });
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: (request) => {
|
||||
assertEquals(request.body, null);
|
||||
promise.resolve();
|
||||
return new Response("", { headers: {} });
|
||||
},
|
||||
port: 4501,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -202,11 +206,11 @@ Deno.test(
|
|||
|
||||
const listeningPromise = deferred();
|
||||
const ac = new AbortController();
|
||||
|
||||
const server = Deno.serve((request) => {
|
||||
assert(!request.body);
|
||||
return new Response(stream.readable);
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: (request) => {
|
||||
assert(!request.body);
|
||||
return new Response(stream.readable);
|
||||
},
|
||||
port: 4501,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -232,11 +236,12 @@ Deno.test(
|
|||
writer.close();
|
||||
const listeningPromise = deferred();
|
||||
const ac = new AbortController();
|
||||
const server = Deno.serve(async (request) => {
|
||||
const reqBody = await request.text();
|
||||
assertEquals("hello world", reqBody);
|
||||
return new Response("yo");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (request) => {
|
||||
const reqBody = await request.text();
|
||||
assertEquals("hello world", reqBody);
|
||||
return new Response("yo");
|
||||
},
|
||||
port: 4501,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -259,7 +264,8 @@ Deno.test(
|
|||
Deno.test({ permissions: { net: true } }, async function httpServerClose() {
|
||||
const ac = new AbortController();
|
||||
const listeningPromise = deferred();
|
||||
const server = Deno.serve(() => new Response("ok"), {
|
||||
const server = Deno.serve({
|
||||
fetch: () => new Response("ok"),
|
||||
port: 4501,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -278,7 +284,8 @@ Deno.test(
|
|||
async function httpServerEmptyBlobResponse() {
|
||||
const ac = new AbortController();
|
||||
const listeningPromise = deferred();
|
||||
const server = Deno.serve(() => new Response(new Blob([])), {
|
||||
const server = Deno.serve({
|
||||
fetch: () => new Response(new Blob([])),
|
||||
port: 4501,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -298,18 +305,19 @@ Deno.test(
|
|||
Deno.test({ permissions: { net: true } }, async function httpServerWebSocket() {
|
||||
const ac = new AbortController();
|
||||
const listeningPromise = deferred();
|
||||
const server = Deno.serve(async (request) => {
|
||||
const {
|
||||
response,
|
||||
socket,
|
||||
} = Deno.upgradeWebSocket(request);
|
||||
socket.onerror = () => fail();
|
||||
socket.onmessage = (m) => {
|
||||
socket.send(m.data);
|
||||
socket.close(1001);
|
||||
};
|
||||
return response;
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (request) => {
|
||||
const {
|
||||
response,
|
||||
socket,
|
||||
} = Deno.upgradeWebSocket(request);
|
||||
socket.onerror = () => fail();
|
||||
socket.onmessage = (m) => {
|
||||
socket.send(m.data);
|
||||
socket.close(1001);
|
||||
};
|
||||
return response;
|
||||
},
|
||||
port: 4501,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -337,11 +345,12 @@ Deno.test(
|
|||
const ac = new AbortController();
|
||||
|
||||
let headers: Headers;
|
||||
const server = Deno.serve(async (request) => {
|
||||
headers = request.headers;
|
||||
promise.resolve();
|
||||
return new Response("");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (request) => {
|
||||
headers = request.headers;
|
||||
promise.resolve();
|
||||
return new Response("");
|
||||
},
|
||||
port: 2333,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -375,12 +384,13 @@ Deno.test(
|
|||
|
||||
let headers: Headers;
|
||||
let text: string;
|
||||
const server = Deno.serve(async (request) => {
|
||||
headers = request.headers;
|
||||
text = await request.text();
|
||||
promise.resolve();
|
||||
return new Response("");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (request) => {
|
||||
headers = request.headers;
|
||||
text = await request.text();
|
||||
promise.resolve();
|
||||
return new Response("");
|
||||
},
|
||||
port: 2333,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -419,10 +429,11 @@ Deno.test(
|
|||
const ac = new AbortController();
|
||||
const listeningPromise = deferred();
|
||||
|
||||
const server = Deno.serve(() => {
|
||||
promise.resolve();
|
||||
return new Response("");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: () => {
|
||||
promise.resolve();
|
||||
return new Response("");
|
||||
},
|
||||
port: 2333,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -568,10 +579,11 @@ Deno.test(
|
|||
}).pipeThrough(new TextEncoderStream());
|
||||
}
|
||||
|
||||
const finished = Deno.serve(() => {
|
||||
promise.resolve();
|
||||
return new Response(periodicStream());
|
||||
}, {
|
||||
const finished = Deno.serve({
|
||||
fetch: () => {
|
||||
promise.resolve();
|
||||
return new Response(periodicStream());
|
||||
},
|
||||
port: 4501,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -598,11 +610,12 @@ Deno.test(
|
|||
const listeningPromise = deferred();
|
||||
const promise = deferred();
|
||||
const ac = new AbortController();
|
||||
const server = Deno.serve((request) => {
|
||||
assertEquals(request.headers.get("X-Header-Test"), "á");
|
||||
promise.resolve();
|
||||
return new Response("hello", { headers: { "X-Header-Test": "Æ" } });
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: (request) => {
|
||||
assertEquals(request.headers.get("X-Header-Test"), "á");
|
||||
promise.resolve();
|
||||
return new Response("hello", { headers: { "X-Header-Test": "Æ" } });
|
||||
},
|
||||
port: 4501,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -643,13 +656,14 @@ Deno.test(
|
|||
const listeningPromise = deferred();
|
||||
const ac = new AbortController();
|
||||
|
||||
const server = Deno.serve(async (request) => {
|
||||
// FIXME:
|
||||
// assertEquals(new URL(request.url).href, "http://127.0.0.1:4501/");
|
||||
assertEquals(await request.text(), "");
|
||||
promise.resolve();
|
||||
return new Response("11");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (request) => {
|
||||
// FIXME:
|
||||
// assertEquals(new URL(request.url).href, "http://127.0.0.1:4501/");
|
||||
assertEquals(await request.text(), "");
|
||||
promise.resolve();
|
||||
return new Response("11");
|
||||
},
|
||||
port: 4501,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -696,12 +710,13 @@ Deno.test(
|
|||
const listeningPromise = deferred();
|
||||
const ac = new AbortController();
|
||||
|
||||
const server = Deno.serve(async (request) => {
|
||||
assertEquals(await request.text(), "");
|
||||
assertEquals(request.headers.get("cookie"), "foo=bar, bar=foo");
|
||||
promise.resolve();
|
||||
return new Response("ok");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (request) => {
|
||||
assertEquals(await request.text(), "");
|
||||
assertEquals(request.headers.get("cookie"), "foo=bar, bar=foo");
|
||||
promise.resolve();
|
||||
return new Response("ok");
|
||||
},
|
||||
port: 4501,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -738,11 +753,12 @@ Deno.test(
|
|||
await file.write(new Uint8Array(70 * 1024).fill(1)); // 70kb sent in 64kb + 6kb chunks
|
||||
file.close();
|
||||
|
||||
const server = Deno.serve(async (request) => {
|
||||
const f = await Deno.open(tmpFile, { read: true });
|
||||
promise.resolve();
|
||||
return new Response(f.readable);
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (request) => {
|
||||
const f = await Deno.open(tmpFile, { read: true });
|
||||
promise.resolve();
|
||||
return new Response(f.readable);
|
||||
},
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -773,10 +789,11 @@ Deno.test(
|
|||
const hostname = "localhost";
|
||||
const port = 4501;
|
||||
|
||||
const server = Deno.serve(() => {
|
||||
promise.resolve();
|
||||
return new Response("ok");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: () => {
|
||||
promise.resolve();
|
||||
return new Response("ok");
|
||||
},
|
||||
port: port,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -807,11 +824,12 @@ Deno.test(
|
|||
const listeningPromise = deferred();
|
||||
const ac = new AbortController();
|
||||
|
||||
const server = Deno.serve(async (request) => {
|
||||
assertEquals(request.body, null);
|
||||
promise.resolve();
|
||||
return new Response(new Uint8Array([128]));
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (request) => {
|
||||
assertEquals(request.body, null);
|
||||
promise.resolve();
|
||||
return new Response(new Uint8Array([128]));
|
||||
},
|
||||
port: 4501,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -837,8 +855,7 @@ Deno.test("upgradeHttp tcp", async () => {
|
|||
const promise2 = deferred();
|
||||
const ac = new AbortController();
|
||||
const signal = ac.signal;
|
||||
|
||||
const server = Deno.serve(async (req) => {
|
||||
const fetch = async (req: Request) => {
|
||||
const [conn, _] = await Deno.upgradeHttp(req);
|
||||
|
||||
await conn.write(
|
||||
|
@ -856,7 +873,9 @@ Deno.test("upgradeHttp tcp", async () => {
|
|||
|
||||
promise2.resolve();
|
||||
conn.close();
|
||||
}, {
|
||||
};
|
||||
const server = Deno.serve({
|
||||
fetch,
|
||||
port: 4501,
|
||||
signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -897,12 +916,13 @@ Deno.test(
|
|||
const listeningPromise = deferred();
|
||||
const ac = new AbortController();
|
||||
|
||||
const server = Deno.serve(async (request) => {
|
||||
assertEquals(request.method, "GET");
|
||||
assertEquals(request.headers.get("host"), "deno.land");
|
||||
promise.resolve();
|
||||
return new Response("ok");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (request) => {
|
||||
assertEquals(request.method, "GET");
|
||||
assertEquals(request.headers.get("host"), "deno.land");
|
||||
promise.resolve();
|
||||
return new Response("ok");
|
||||
},
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -930,12 +950,13 @@ Deno.test(
|
|||
const listeningPromise = deferred();
|
||||
const ac = new AbortController();
|
||||
|
||||
const server = Deno.serve(async (request) => {
|
||||
assertEquals(request.method, "GET");
|
||||
assertEquals(request.headers.get("server"), "hello\tworld");
|
||||
promise.resolve();
|
||||
return new Response("ok");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (request) => {
|
||||
assertEquals(request.method, "GET");
|
||||
assertEquals(request.headers.get("server"), "hello\tworld");
|
||||
promise.resolve();
|
||||
return new Response("ok");
|
||||
},
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -963,12 +984,13 @@ Deno.test(
|
|||
const listeningPromise = deferred();
|
||||
const ac = new AbortController();
|
||||
|
||||
const server = Deno.serve(async (request) => {
|
||||
assertEquals(request.method, "GET");
|
||||
assertEquals(await request.text(), "");
|
||||
promise.resolve();
|
||||
return new Response("ok");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (request) => {
|
||||
assertEquals(request.method, "GET");
|
||||
assertEquals(await request.text(), "");
|
||||
promise.resolve();
|
||||
return new Response("ok");
|
||||
},
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -998,12 +1020,13 @@ Deno.test(
|
|||
const listeningPromise = deferred();
|
||||
const ac = new AbortController();
|
||||
|
||||
const server = Deno.serve(async (request) => {
|
||||
assertEquals(request.method, "POST");
|
||||
assertEquals(await request.text(), "I'm a good request.");
|
||||
promise.resolve();
|
||||
return new Response("ok");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (request) => {
|
||||
assertEquals(request.method, "POST");
|
||||
assertEquals(await request.text(), "I'm a good request.");
|
||||
promise.resolve();
|
||||
return new Response("ok");
|
||||
},
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -1043,11 +1066,12 @@ function createServerLengthTest(name: string, testCase: TestCase) {
|
|||
const ac = new AbortController();
|
||||
const listeningPromise = deferred();
|
||||
|
||||
const server = Deno.serve(async (request) => {
|
||||
assertEquals(request.method, "GET");
|
||||
promise.resolve();
|
||||
return new Response(testCase.body, testCase.headers ?? {});
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (request) => {
|
||||
assertEquals(request.method, "GET");
|
||||
promise.resolve();
|
||||
return new Response(testCase.body, testCase.headers ?? {});
|
||||
},
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -1174,12 +1198,13 @@ Deno.test(
|
|||
const listeningPromise = deferred();
|
||||
const ac = new AbortController();
|
||||
|
||||
const server = Deno.serve(async (request) => {
|
||||
assertEquals(request.method, "GET");
|
||||
promises[reqCount].resolve();
|
||||
reqCount++;
|
||||
return new Response(reqCount <= 1 ? stream("foo bar baz") : "zar quux");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (request) => {
|
||||
assertEquals(request.method, "GET");
|
||||
promises[reqCount].resolve();
|
||||
reqCount++;
|
||||
return new Response(reqCount <= 1 ? stream("foo bar baz") : "zar quux");
|
||||
},
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -1236,13 +1261,14 @@ Deno.test(
|
|||
const listeningPromise = deferred();
|
||||
const ac = new AbortController();
|
||||
|
||||
const server = Deno.serve(async (request) => {
|
||||
assertEquals(request.method, "POST");
|
||||
assertEquals(request.headers.get("content-length"), "5");
|
||||
assertEquals(await request.text(), "hello");
|
||||
promise.resolve();
|
||||
return new Response("ok");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (request) => {
|
||||
assertEquals(request.method, "POST");
|
||||
assertEquals(request.headers.get("content-length"), "5");
|
||||
assertEquals(await request.text(), "hello");
|
||||
promise.resolve();
|
||||
return new Response("ok");
|
||||
},
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -1271,9 +1297,10 @@ Deno.test(
|
|||
async function httpServerPostWithInvalidPrefixContentLength() {
|
||||
const ac = new AbortController();
|
||||
const listeningPromise = deferred();
|
||||
const server = Deno.serve(() => {
|
||||
throw new Error("unreachable");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: () => {
|
||||
throw new Error("unreachable");
|
||||
},
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -1310,12 +1337,13 @@ Deno.test(
|
|||
const ac = new AbortController();
|
||||
const listeningPromise = deferred();
|
||||
|
||||
const server = Deno.serve(async (request) => {
|
||||
assertEquals(request.method, "POST");
|
||||
assertEquals(await request.text(), "qwert");
|
||||
promise.resolve();
|
||||
return new Response("ok");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (request) => {
|
||||
assertEquals(request.method, "POST");
|
||||
assertEquals(await request.text(), "qwert");
|
||||
promise.resolve();
|
||||
return new Response("ok");
|
||||
},
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -1346,11 +1374,12 @@ Deno.test(
|
|||
const ac = new AbortController();
|
||||
const listeningPromise = deferred();
|
||||
|
||||
const server = Deno.serve(async (r) => {
|
||||
promise.resolve();
|
||||
assertEquals(await r.text(), "12345");
|
||||
return new Response("ok");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (r) => {
|
||||
promise.resolve();
|
||||
assertEquals(await r.text(), "12345");
|
||||
return new Response("ok");
|
||||
},
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -1381,10 +1410,11 @@ Deno.test(
|
|||
const ac = new AbortController();
|
||||
const listeningPromise = deferred();
|
||||
|
||||
const server = Deno.serve(() => {
|
||||
promise.resolve();
|
||||
return new Response("foo bar baz");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: () => {
|
||||
promise.resolve();
|
||||
return new Response("foo bar baz");
|
||||
},
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -1428,11 +1458,12 @@ Deno.test(
|
|||
const data = new Uint8Array(70 * 1024).fill(1);
|
||||
await file.write(data);
|
||||
file.close();
|
||||
const server = Deno.serve(async () => {
|
||||
const f = await Deno.open(tmpFile, { read: true });
|
||||
promise.resolve();
|
||||
return new Response(f.readable, { status: 200 });
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async () => {
|
||||
const f = await Deno.open(tmpFile, { read: true });
|
||||
promise.resolve();
|
||||
return new Response(f.readable, { status: 200 });
|
||||
},
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -1462,11 +1493,12 @@ Deno.test(
|
|||
await file.write(data);
|
||||
file.close();
|
||||
|
||||
const server = Deno.serve(async (request) => {
|
||||
assertEquals(new Uint8Array(await request.arrayBuffer()), data);
|
||||
promise.resolve();
|
||||
return new Response("ok");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (request) => {
|
||||
assertEquals(new Uint8Array(await request.arrayBuffer()), data);
|
||||
promise.resolve();
|
||||
return new Response("ok");
|
||||
},
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -1497,11 +1529,9 @@ Deno.test(
|
|||
const listeningPromise = deferred();
|
||||
const hostname = "127.0.0.1";
|
||||
const port = 4501;
|
||||
function handler() {
|
||||
return new Response("Hello World");
|
||||
}
|
||||
|
||||
const server = Deno.serveTls(handler, {
|
||||
const server = Deno.serve({
|
||||
fetch: () => new Response("Hello World"),
|
||||
hostname,
|
||||
port,
|
||||
signal: ac.signal,
|
||||
|
@ -1535,11 +1565,12 @@ Deno.test(
|
|||
const listeningPromise = deferred();
|
||||
const promise = deferred();
|
||||
|
||||
const server = Deno.serve(async (req) => {
|
||||
assertEquals(await req.text(), "");
|
||||
promise.resolve();
|
||||
return new Response("ok");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (req) => {
|
||||
assertEquals(await req.text(), "");
|
||||
promise.resolve();
|
||||
return new Response("ok");
|
||||
},
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -1569,9 +1600,10 @@ Deno.test(
|
|||
const ac = new AbortController();
|
||||
const listeningPromise = deferred();
|
||||
|
||||
const server = Deno.serve(() => {
|
||||
throw new Error("oops");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: () => {
|
||||
throw new Error("oops");
|
||||
},
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -1617,10 +1649,11 @@ Deno.test(
|
|||
const ac = new AbortController();
|
||||
const listeningPromise = deferred();
|
||||
|
||||
const server = Deno.serve(() => {
|
||||
promise.resolve();
|
||||
return new Response(null, { status: 304 });
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: () => {
|
||||
promise.resolve();
|
||||
return new Response(null, { status: 304 });
|
||||
},
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -1660,11 +1693,12 @@ Deno.test(
|
|||
const ac = new AbortController();
|
||||
const listeningPromise = deferred();
|
||||
|
||||
const server = Deno.serve(async (req) => {
|
||||
promise.resolve();
|
||||
assertEquals(await req.text(), "hello");
|
||||
return new Response(null, { status: 304 });
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (req) => {
|
||||
promise.resolve();
|
||||
assertEquals(await req.text(), "hello");
|
||||
return new Response(null, { status: 304 });
|
||||
},
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -1720,11 +1754,12 @@ Deno.test(
|
|||
const listeningPromise = deferred();
|
||||
const ac = new AbortController();
|
||||
|
||||
const server = Deno.serve(async (req) => {
|
||||
promise.resolve();
|
||||
assertEquals(await req.text(), "");
|
||||
return new Response(null, { status: 304 });
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: async (req) => {
|
||||
promise.resolve();
|
||||
assertEquals(await req.text(), "");
|
||||
return new Response(null, { status: 304 });
|
||||
},
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -1773,9 +1808,10 @@ for (const [name, req] of badRequests) {
|
|||
const ac = new AbortController();
|
||||
const listeningPromise = deferred();
|
||||
|
||||
const server = Deno.serve(() => {
|
||||
throw new Error("oops");
|
||||
}, {
|
||||
const server = Deno.serve({
|
||||
fetch: () => {
|
||||
throw new Error("oops");
|
||||
},
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -1817,7 +1853,8 @@ Deno.test(
|
|||
const ac = new AbortController();
|
||||
const listeningPromise = deferred();
|
||||
|
||||
const server = Deno.serve(() => new Response(null), {
|
||||
const server = Deno.serve({
|
||||
fetch: () => new Response(null),
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
@ -1856,32 +1893,33 @@ Deno.test(
|
|||
|
||||
let reqCount = -1;
|
||||
let timerId: number | undefined;
|
||||
const server = Deno.serve(async (req) => {
|
||||
reqCount++;
|
||||
if (reqCount === 0) {
|
||||
const msg = new TextEncoder().encode("data: hello\r\n\r\n");
|
||||
// SSE
|
||||
const body = new ReadableStream({
|
||||
start(controller) {
|
||||
timerId = setInterval(() => {
|
||||
controller.enqueue(msg);
|
||||
}, 1000);
|
||||
},
|
||||
cancel() {
|
||||
if (typeof timerId === "number") {
|
||||
clearInterval(timerId);
|
||||
}
|
||||
},
|
||||
});
|
||||
return new Response(body, {
|
||||
headers: {
|
||||
"Content-Type": "text/event-stream",
|
||||
},
|
||||
});
|
||||
}
|
||||
const server = Deno.serve({
|
||||
fetch: async (req) => {
|
||||
reqCount++;
|
||||
if (reqCount === 0) {
|
||||
const msg = new TextEncoder().encode("data: hello\r\n\r\n");
|
||||
// SSE
|
||||
const body = new ReadableStream({
|
||||
start(controller) {
|
||||
timerId = setInterval(() => {
|
||||
controller.enqueue(msg);
|
||||
}, 1000);
|
||||
},
|
||||
cancel() {
|
||||
if (typeof timerId === "number") {
|
||||
clearInterval(timerId);
|
||||
}
|
||||
},
|
||||
});
|
||||
return new Response(body, {
|
||||
headers: {
|
||||
"Content-Type": "text/event-stream",
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return new Response(`hello ${reqCount}`);
|
||||
}, {
|
||||
return new Response(`hello ${reqCount}`);
|
||||
},
|
||||
port: 4503,
|
||||
signal: ac.signal,
|
||||
onListen: onListen(listeningPromise),
|
||||
|
|
|
@ -185,18 +185,19 @@
|
|||
return hostname === "0.0.0.0" ? "localhost" : hostname;
|
||||
}
|
||||
|
||||
function serve(handler, opts = {}) {
|
||||
delete opts.key;
|
||||
delete opts.cert;
|
||||
return serveInner(handler, opts, false);
|
||||
}
|
||||
|
||||
function serveTls(handler, opts = {}) {
|
||||
return serveInner(handler, opts, true);
|
||||
}
|
||||
|
||||
function serveInner(handler, opts, useTls) {
|
||||
opts = { hostname: "127.0.0.1", port: 9000, useTls, ...opts };
|
||||
function serve(opts = {}) {
|
||||
if (!("fetch" in opts)) {
|
||||
throw new TypeError("Options is missing 'fetch' handler");
|
||||
}
|
||||
if ("cert" in opts && !("key" in opts)) {
|
||||
throw new TypeError("Options is missing 'key' field");
|
||||
}
|
||||
if ("key" in opts && !("cert" in opts)) {
|
||||
throw new TypeError("Options is missing 'cert' field");
|
||||
}
|
||||
opts = { hostname: "127.0.0.1", port: 9000, ...opts };
|
||||
const handler = opts.fetch;
|
||||
delete opts.fetch;
|
||||
const signal = opts.signal;
|
||||
delete opts.signal;
|
||||
const onError = opts.onError ?? function (error) {
|
||||
|
@ -570,6 +571,5 @@
|
|||
|
||||
window.__bootstrap.flash = {
|
||||
serve,
|
||||
serveTls,
|
||||
};
|
||||
})(this);
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
Flash is a fast HTTP/1.1 server implementation for Deno.
|
||||
|
||||
```js
|
||||
serve((req) => new Response("Hello World"));
|
||||
serve({ fetch: (req) => new Response("Hello World") });
|
||||
```
|
||||
|
|
|
@ -935,7 +935,6 @@ pub struct ListenOpts {
|
|||
key: Option<String>,
|
||||
hostname: String,
|
||||
port: u16,
|
||||
use_tls: bool,
|
||||
}
|
||||
|
||||
fn run_server(
|
||||
|
@ -1239,11 +1238,7 @@ fn op_flash_serve<P>(
|
|||
where
|
||||
P: FlashPermissions + 'static,
|
||||
{
|
||||
if opts.use_tls {
|
||||
check_unstable(state, "Deno.serveTls");
|
||||
} else {
|
||||
check_unstable(state, "Deno.serve");
|
||||
}
|
||||
check_unstable(state, "Deno.serve");
|
||||
state
|
||||
.borrow_mut::<P>()
|
||||
.check_net(&(&opts.hostname, Some(opts.port)))?;
|
||||
|
|
|
@ -154,6 +154,5 @@
|
|||
spawn: __bootstrap.spawn.spawn,
|
||||
spawnSync: __bootstrap.spawn.spawnSync,
|
||||
serve: __bootstrap.flash.serve,
|
||||
serveTls: __bootstrap.flash.serveTls,
|
||||
};
|
||||
})(this);
|
||||
|
|
Loading…
Add table
Reference in a new issue