diff options
author | 2023-02-23 17:13:30 -0800 | |
---|---|---|
committer | 2023-02-23 17:13:30 -0800 | |
commit | f54300578b1edc7f67daddbfae29575cbf305264 (patch) | |
tree | 1437f3274122c011f879dca71f59a74d75a33fd0 /docs/api/http.md | |
parent | 5929daeeae1f528abab31979a0a28bc87a03b1f4 (diff) | |
download | bun-f54300578b1edc7f67daddbfae29575cbf305264.tar.gz bun-f54300578b1edc7f67daddbfae29575cbf305264.tar.zst bun-f54300578b1edc7f67daddbfae29575cbf305264.zip |
Add documentation (#2148)bun-v0.5.7
* Add documentation
* Tweaks
* Fixes
* Rearrange
* Update
Diffstat (limited to 'docs/api/http.md')
-rw-r--r-- | docs/api/http.md | 257 |
1 files changed, 257 insertions, 0 deletions
diff --git a/docs/api/http.md b/docs/api/http.md new file mode 100644 index 000000000..d05691556 --- /dev/null +++ b/docs/api/http.md @@ -0,0 +1,257 @@ +{% callout %} +**Note** — Bun provides an [almost complete](/docs/runtime/nodejs#node_http) implementation of the Node.js [`http`](https://nodejs.org/api/http.html) and [`https`](https://nodejs.org/api/https.html) modules. This page only documents Bun-native APIs. +{% /callout %} + +## Start a server + +`Bun.serve(options) => Server` + +Start an HTTP server in Bun with `Bun.serve`. + +```ts +Bun.serve({ + fetch(req) { + return new Response(`Bun!`); + }, +}); +``` + +The `fetch` handler handles incoming requests. It receives a [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) object and returns a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) or `Promise<Response>`. + +```ts +Bun.serve({ + fetch(req) { + const url = new URL(req.url); + if (url.pathname === "/") return new Response(`Home page!`); + if (url.pathname === "/blog") return new Response("Blog!"); + return new Response(`404!`); + }, +}); +``` + +To configure which port and hostname the server will listen on: + +```ts +Bun.serve({ + port: 8080, // defaults to $PORT, then 3000 + hostname: "mydomain.com", // defaults to "0.0.0.0" + fetch(req) { + return new Response(`404!`); + }, +}); +``` + +## Error handling + +To activate development mode, set `development: true`. By default, development mode is _enabled_ unless `NODE_ENV` is `production`. + +```ts +Bun.serve({ + development: true, + fetch(req) { + throw new Error("woops!"); + }, +}); +``` + +In development mode, Bun will surface errors in-browser with a built-in error page. + +{% image src="/images/exception_page.png" caption="Bun's built-in 500 page" /%} + +To handle server-side errors, implement an `error` handler. This function should return a `Response` to served to the client when an error occurs. This response will supercede Bun's default error page in `development` mode. + +```ts +Bun.serve({ + fetch(req) { + throw new Error("woops!"); + }, + error(error: Error) { + return new Response(`<pre>${error}\n${error.stack}</pre>`, { + headers: { + "Content-Type": "text/html", + }, + }); + }, +}); +``` + +{% callout %} +**Note** — Full debugger support is planned. +{% /callout %} + +The call to `Bun.serve` returns a `Server` object. To stop the server, call the `.stop()` method. + +```ts +const server = Bun.serve({ + fetch() { + return new Response("Bun!"); + }, +}); + +server.stop(); +``` + +## TLS + +Bun supports TLS out of the box, powered by [OpenSSL](https://www.openssl.org/). Enable TLS by passing in a value for `keyFile` and `certFile`; both are required to enable TLS. If needed, supply a `passphrase` to decrypt the `keyFile`. + +```ts +Bun.serve({ + fetch(req) { + return new Response("Hello!!!"); + }, + keyFile: "./key.pem", // path to TLS key + certFile: "./cert.pem", // path to TLS cert + passphrase: "super-secret", // optional passphrase +}); +``` + +The root CA and Diffie-Helman parameters can be configured as well. + +```ts +Bun.serve({ + fetch(req) { + return new Response("Hello!!!"); + }, + keyFile: "./key.pem", // path to TLS key + certFile: "./cert.pem", // path to TLS cert + caFile: "./ca.pem", // path to root CA certificate + dhParamsFile: "./dhparams.pem", // Diffie Helman parameters +}); +``` + +## Hot reloading + +Thus far, the examples on this page have used the explicit `Bun.serve` API. Bun also supports an alternate syntax. + +```ts#server.ts +export default { + fetch(req) { + return new Response(`Bun!`); + }, +}; +``` + +Instead of passing the server options into `Bun.serve`, export it. This file can be executed as-is; when Bun runs a file with a `default` export containing a `fetch` handler, it passes it into `Bun.serve` under the hood. + +This syntax has one major advantage: it is hot-reloadable out of the box. When any source file is changed, Bun will reload the server with the updated code _without restarting the process_. This makes hot reloads nearly instantaneous. Use the `--hot` flag when starting the server to enable hot reloading. + +```bash +$ bun --hot server.ts +``` + +It's possible to configure hot reloading while using the explicit `Bun.serve` API; for details refer to [Runtime > Hot reloading](/docs/runtime/hot). + +## Streaming files + +To stream a file, return a `Response` object with a `BunFile` object as the body. + +```ts +import { serve, file } from "bun"; + +serve({ + fetch(req) { + return new Response(Bun.file("./hello.txt")); + }, +}); +``` + +{% callout %} +⚡️ **Speed** — Bun automatically uses the [`sendfile(2)`](https://man7.org/linux/man-pages/man2/sendfile.2.html) system call when possible, enabling zero-copy file transfers in the kernel—the fastest way to send files. +{% /callout %} + +**[v0.3.0+]** You can send part of a file using the [`slice(start, end)`](https://developer.mozilla.org/en-US/docs/Web/API/Blob/slice) method on the `Bun.file` object. This automatically sets the `Content-Range` and `Content-Length` headers on the `Response` object. + +```ts +Bun.serve({ + fetch(req) { + // parse `Range` header + const [start = 0, end = Infinity] = req.headers + .get("Range") // Range: bytes=0-100 + .split("=") // ["Range: bytes", "0-100"] + .at(-1) // "0-100" + .split("-") // ["0", "100"] + .map(Number); // [0, 100] + + // return a slice of the file + const bigFile = Bun.file("./big-video.mp4"); + return new Response(bigFile.slice(start, end)); + }, +}); +``` + +## Benchmarks + +Below are Bun and Node.js implementations of a simple HTTP server that responds `Bun!` to each incoming `Request`. + +{% codetabs %} + +```ts#Bun +Bun.serve({ + fetch(req: Request) { + return new Response(`Bun!`); + }, + port: 3000, +}); +``` + +```ts#Node +require("http") + .createServer((req, res) => res.end("Bun!")) + .listen(8080); +``` + +{% /codetabs %} +The `Bun.serve` server can handle roughly 2.5x more requests per second than Node.js on Linux. + +{% table %} + +- Runtime +- Requests per second + +--- + +- Node 16 +- ~64,000 + +--- + +- Bun +- ~160,000 + +{% /table %} + +{% image width="499" alt="image" src="https://user-images.githubusercontent.com/709451/162389032-fc302444-9d03-46be-ba87-c12bd8ce89a0.png" /%} + +## Reference + +{% details summary="See TypeScript definitions" %} + +```ts +interface Bun { + serve(options: { + fetch: (req: Request, server: Server) => Response | Promise<Response>; + hostname?: string; + port?: number; + development?: boolean; + error?: (error: Error) => Response | Promise<Response>; + keyFile?: string; + certFile?: string; + caFile?: string; + dhParamsFile?: string; + passphrase?: string; + maxRequestBodySize?: number; + lowMemoryMode?: boolean; + }): Server; +} + +interface Server { + development: boolean; + hostname: string; + port: number; + pendingRequests: number; + stop(): void; +} +``` + +{% /details %} |