0
0
Fork 0
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:
Bartek Iwańczuk 2022-08-19 14:36:01 +02:00 committed by GitHub
parent 1848c7e361
commit 5beec3f106
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 353 additions and 330 deletions

View file

@ -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 });

View file

@ -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) });

View file

@ -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,
});

View file

@ -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 },
);

View file

@ -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,
});

View file

@ -64,7 +64,6 @@ const UNSTABLE_DENO_PROPS: &[&str] = &[
"ChildStatus",
"SpawnOutput",
"serve",
"serveTls",
"ServeInit",
"ServeTlsInit",
"Handler",

View file

@ -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.

View file

@ -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),

View file

@ -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);

View file

@ -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") });
```

View file

@ -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)))?;

View file

@ -154,6 +154,5 @@
spawn: __bootstrap.spawn.spawn,
spawnSync: __bootstrap.spawn.spawnSync,
serve: __bootstrap.flash.serve,
serveTls: __bootstrap.flash.serveTls,
};
})(this);