bun-types 1.3.2-canary.20251106T140813 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bun.d.ts +102 -6
- package/docs/bundler/bytecode.mdx +465 -0
- package/docs/bundler/css.mdx +1024 -0
- package/docs/bundler/esbuild.mdx +253 -0
- package/docs/bundler/executables.mdx +535 -0
- package/docs/bundler/fullstack.mdx +1064 -0
- package/docs/bundler/hot-reloading.mdx +229 -0
- package/docs/bundler/html-static.mdx +386 -0
- package/docs/bundler/index.mdx +1499 -0
- package/docs/bundler/loaders.mdx +356 -0
- package/docs/bundler/macros.mdx +328 -0
- package/docs/bundler/minifier.mdx +1306 -0
- package/docs/bundler/plugins.mdx +411 -0
- package/docs/feedback.mdx +85 -0
- package/docs/guides/binary/arraybuffer-to-array.mdx +29 -0
- package/docs/guides/binary/arraybuffer-to-blob.mdx +26 -0
- package/docs/guides/binary/arraybuffer-to-buffer.mdx +27 -0
- package/docs/guides/binary/arraybuffer-to-string.mdx +17 -0
- package/docs/guides/binary/arraybuffer-to-typedarray.mdx +41 -0
- package/docs/guides/binary/blob-to-arraybuffer.mdx +16 -0
- package/docs/guides/binary/blob-to-dataview.mdx +16 -0
- package/docs/guides/binary/blob-to-stream.mdx +16 -0
- package/docs/guides/binary/blob-to-string.mdx +17 -0
- package/docs/guides/binary/blob-to-typedarray.mdx +16 -0
- package/docs/guides/binary/buffer-to-arraybuffer.mdx +16 -0
- package/docs/guides/binary/buffer-to-blob.mdx +16 -0
- package/docs/guides/binary/buffer-to-readablestream.mdx +43 -0
- package/docs/guides/binary/buffer-to-string.mdx +27 -0
- package/docs/guides/binary/buffer-to-typedarray.mdx +16 -0
- package/docs/guides/binary/dataview-to-string.mdx +17 -0
- package/docs/guides/binary/typedarray-to-arraybuffer.mdx +27 -0
- package/docs/guides/binary/typedarray-to-blob.mdx +18 -0
- package/docs/guides/binary/typedarray-to-buffer.mdx +16 -0
- package/docs/guides/binary/typedarray-to-dataview.mdx +16 -0
- package/docs/guides/binary/typedarray-to-readablestream.mdx +43 -0
- package/docs/guides/binary/typedarray-to-string.mdx +18 -0
- package/docs/guides/deployment/aws-lambda.mdx +204 -0
- package/docs/guides/deployment/digital-ocean.mdx +161 -0
- package/docs/guides/deployment/google-cloud-run.mdx +197 -0
- package/docs/guides/deployment/railway.mdx +145 -0
- package/docs/guides/deployment/render.mdx +82 -0
- package/docs/guides/deployment/vercel.mdx +99 -0
- package/docs/guides/ecosystem/astro.mdx +82 -0
- package/docs/guides/ecosystem/discordjs.mdx +80 -0
- package/docs/guides/ecosystem/docker.mdx +151 -0
- package/docs/guides/ecosystem/drizzle.mdx +195 -0
- package/docs/guides/ecosystem/edgedb.mdx +257 -0
- package/docs/guides/ecosystem/elysia.mdx +31 -0
- package/docs/guides/ecosystem/express.mdx +43 -0
- package/docs/guides/ecosystem/hono.mdx +47 -0
- package/docs/guides/ecosystem/mongoose.mdx +92 -0
- package/docs/guides/ecosystem/neon-drizzle.mdx +234 -0
- package/docs/guides/ecosystem/neon-serverless-postgres.mdx +60 -0
- package/docs/guides/ecosystem/nextjs.mdx +57 -0
- package/docs/guides/ecosystem/nuxt.mdx +90 -0
- package/docs/guides/ecosystem/pm2.mdx +55 -0
- package/docs/guides/ecosystem/prisma-postgres.mdx +169 -0
- package/docs/guides/ecosystem/prisma.mdx +164 -0
- package/docs/guides/ecosystem/qwik.mdx +114 -0
- package/docs/guides/ecosystem/react.mdx +52 -0
- package/docs/guides/ecosystem/remix.mdx +97 -0
- package/docs/guides/ecosystem/sentry.mdx +54 -0
- package/docs/guides/ecosystem/solidstart.mdx +66 -0
- package/docs/guides/ecosystem/ssr-react.mdx +49 -0
- package/docs/guides/ecosystem/stric.mdx +54 -0
- package/docs/guides/ecosystem/sveltekit.mdx +138 -0
- package/docs/guides/ecosystem/systemd.mdx +114 -0
- package/docs/guides/ecosystem/upstash.mdx +87 -0
- package/docs/guides/ecosystem/vite.mdx +77 -0
- package/docs/guides/html-rewriter/extract-links.mdx +72 -0
- package/docs/guides/html-rewriter/extract-social-meta.mdx +97 -0
- package/docs/guides/http/cluster.mdx +69 -0
- package/docs/guides/http/fetch-unix.mdx +35 -0
- package/docs/guides/http/fetch.mdx +26 -0
- package/docs/guides/http/file-uploads.mdx +97 -0
- package/docs/guides/http/hot.mdx +28 -0
- package/docs/guides/http/proxy.mdx +26 -0
- package/docs/guides/http/server.mdx +48 -0
- package/docs/guides/http/simple.mdx +20 -0
- package/docs/guides/http/stream-file.mdx +50 -0
- package/docs/guides/http/stream-iterator.mdx +49 -0
- package/docs/guides/http/stream-node-streams-in-bun.mdx +22 -0
- package/docs/guides/http/tls.mdx +32 -0
- package/docs/guides/index.mdx +10 -0
- package/docs/guides/install/add-dev.mdx +28 -0
- package/docs/guides/install/add-git.mdx +38 -0
- package/docs/guides/install/add-optional.mdx +27 -0
- package/docs/guides/install/add-peer.mdx +45 -0
- package/docs/guides/install/add-tarball.mdx +35 -0
- package/docs/guides/install/add.mdx +44 -0
- package/docs/guides/install/azure-artifacts.mdx +76 -0
- package/docs/guides/install/cicd.mdx +43 -0
- package/docs/guides/install/custom-registry.mdx +32 -0
- package/docs/guides/install/from-npm-install-to-bun-install.mdx +230 -0
- package/docs/guides/install/git-diff-bun-lockfile.mdx +47 -0
- package/docs/guides/install/jfrog-artifactory.mdx +28 -0
- package/docs/guides/install/npm-alias.mdx +25 -0
- package/docs/guides/install/registry-scope.mdx +40 -0
- package/docs/guides/install/trusted.mdx +50 -0
- package/docs/guides/install/workspaces.mdx +70 -0
- package/docs/guides/install/yarnlock.mdx +50 -0
- package/docs/guides/process/argv.mdx +66 -0
- package/docs/guides/process/ctrl-c.mdx +18 -0
- package/docs/guides/process/ipc.mdx +69 -0
- package/docs/guides/process/nanoseconds.mdx +15 -0
- package/docs/guides/process/os-signals.mdx +41 -0
- package/docs/guides/process/spawn-stderr.mdx +34 -0
- package/docs/guides/process/spawn-stdout.mdx +28 -0
- package/docs/guides/process/spawn.mdx +43 -0
- package/docs/guides/process/stdin.mdx +62 -0
- package/docs/guides/read-file/arraybuffer.mdx +30 -0
- package/docs/guides/read-file/buffer.mdx +21 -0
- package/docs/guides/read-file/exists.mdx +18 -0
- package/docs/guides/read-file/json.mdx +19 -0
- package/docs/guides/read-file/mime.mdx +22 -0
- package/docs/guides/read-file/stream.mdx +28 -0
- package/docs/guides/read-file/string.mdx +24 -0
- package/docs/guides/read-file/uint8array.mdx +23 -0
- package/docs/guides/read-file/watch.mdx +66 -0
- package/docs/guides/runtime/build-time-constants.mdx +295 -0
- package/docs/guides/runtime/cicd.mdx +45 -0
- package/docs/guides/runtime/codesign-macos-executable.mdx +61 -0
- package/docs/guides/runtime/define-constant.mdx +149 -0
- package/docs/guides/runtime/delete-directory.mdx +39 -0
- package/docs/guides/runtime/delete-file.mdx +21 -0
- package/docs/guides/runtime/heap-snapshot.mdx +28 -0
- package/docs/guides/runtime/import-html.mdx +17 -0
- package/docs/guides/runtime/import-json.mdx +46 -0
- package/docs/guides/runtime/import-toml.mdx +32 -0
- package/docs/guides/runtime/import-yaml.mdx +104 -0
- package/docs/guides/runtime/read-env.mdx +37 -0
- package/docs/guides/runtime/set-env.mdx +51 -0
- package/docs/guides/runtime/shell.mdx +42 -0
- package/docs/guides/runtime/timezone.mdx +38 -0
- package/docs/guides/runtime/tsconfig-paths.mdx +31 -0
- package/docs/guides/runtime/typescript.mdx +51 -0
- package/docs/guides/runtime/vscode-debugger.mdx +48 -0
- package/docs/guides/runtime/web-debugger.mdx +103 -0
- package/docs/guides/streams/node-readable-to-arraybuffer.mdx +13 -0
- package/docs/guides/streams/node-readable-to-blob.mdx +13 -0
- package/docs/guides/streams/node-readable-to-json.mdx +14 -0
- package/docs/guides/streams/node-readable-to-string.mdx +14 -0
- package/docs/guides/streams/node-readable-to-uint8array.mdx +13 -0
- package/docs/guides/streams/to-array.mdx +16 -0
- package/docs/guides/streams/to-arraybuffer.mdx +16 -0
- package/docs/guides/streams/to-blob.mdx +16 -0
- package/docs/guides/streams/to-buffer.mdx +17 -0
- package/docs/guides/streams/to-json.mdx +16 -0
- package/docs/guides/streams/to-string.mdx +16 -0
- package/docs/guides/streams/to-typedarray.mdx +24 -0
- package/docs/guides/test/bail.mdx +24 -0
- package/docs/guides/test/coverage-threshold.mdx +67 -0
- package/docs/guides/test/coverage.mdx +49 -0
- package/docs/guides/test/happy-dom.mdx +73 -0
- package/docs/guides/test/migrate-from-jest.mdx +125 -0
- package/docs/guides/test/mock-clock.mdx +50 -0
- package/docs/guides/test/mock-functions.mdx +70 -0
- package/docs/guides/test/rerun-each.mdx +16 -0
- package/docs/guides/test/run-tests.mdx +116 -0
- package/docs/guides/test/skip-tests.mdx +43 -0
- package/docs/guides/test/snapshot.mdx +102 -0
- package/docs/guides/test/spy-on.mdx +49 -0
- package/docs/guides/test/svelte-test.mdx +113 -0
- package/docs/guides/test/testing-library.mdx +93 -0
- package/docs/guides/test/timeout.mdx +17 -0
- package/docs/guides/test/todo-tests.mdx +74 -0
- package/docs/guides/test/update-snapshots.mdx +49 -0
- package/docs/guides/test/watch-mode.mdx +24 -0
- package/docs/guides/util/base64.mdx +17 -0
- package/docs/guides/util/deep-equals.mdx +41 -0
- package/docs/guides/util/deflate.mdx +20 -0
- package/docs/guides/util/detect-bun.mdx +25 -0
- package/docs/guides/util/entrypoint.mdx +19 -0
- package/docs/guides/util/escape-html.mdx +24 -0
- package/docs/guides/util/file-url-to-path.mdx +16 -0
- package/docs/guides/util/gzip.mdx +20 -0
- package/docs/guides/util/hash-a-password.mdx +56 -0
- package/docs/guides/util/import-meta-dir.mdx +15 -0
- package/docs/guides/util/import-meta-file.mdx +15 -0
- package/docs/guides/util/import-meta-path.mdx +15 -0
- package/docs/guides/util/javascript-uuid.mdx +25 -0
- package/docs/guides/util/main.mdx +43 -0
- package/docs/guides/util/path-to-file-url.mdx +16 -0
- package/docs/guides/util/sleep.mdx +24 -0
- package/docs/guides/util/version.mdx +23 -0
- package/docs/guides/util/which-path-to-executable-bin.mdx +17 -0
- package/docs/guides/websocket/compression.mdx +33 -0
- package/docs/guides/websocket/context.mdx +74 -0
- package/docs/guides/websocket/pubsub.mdx +40 -0
- package/docs/guides/websocket/simple.mdx +35 -0
- package/docs/guides/write-file/append.mdx +54 -0
- package/docs/guides/write-file/basic.mdx +46 -0
- package/docs/guides/write-file/blob.mdx +30 -0
- package/docs/guides/write-file/cat.mdx +19 -0
- package/docs/guides/write-file/file-cp.mdx +18 -0
- package/docs/guides/write-file/filesink.mdx +54 -0
- package/docs/guides/write-file/response.mdx +19 -0
- package/docs/guides/write-file/stdout.mdx +23 -0
- package/docs/guides/write-file/stream.mdx +19 -0
- package/docs/guides/write-file/unlink.mdx +18 -0
- package/docs/index.mdx +133 -0
- package/docs/installation.mdx +365 -0
- package/docs/pm/bunx.mdx +83 -0
- package/docs/pm/catalogs.mdx +292 -0
- package/docs/pm/cli/add.mdx +179 -0
- package/docs/pm/cli/audit.mdx +60 -0
- package/docs/pm/cli/install.mdx +471 -0
- package/docs/pm/cli/link.mdx +48 -0
- package/docs/pm/cli/outdated.mdx +197 -0
- package/docs/pm/cli/patch.mdx +69 -0
- package/docs/pm/cli/pm.mdx +319 -0
- package/docs/pm/cli/publish.mdx +123 -0
- package/docs/pm/cli/remove.mdx +16 -0
- package/docs/pm/cli/update.mdx +140 -0
- package/docs/pm/cli/why.mdx +84 -0
- package/docs/pm/filter.mdx +102 -0
- package/docs/pm/global-cache.mdx +72 -0
- package/docs/pm/isolated-installs.mdx +205 -0
- package/docs/pm/lifecycle.mdx +57 -0
- package/docs/pm/lockfile.mdx +64 -0
- package/docs/pm/npmrc.mdx +111 -0
- package/docs/pm/overrides.mdx +83 -0
- package/docs/pm/scopes-registries.mdx +35 -0
- package/docs/pm/security-scanner-api.mdx +95 -0
- package/docs/pm/workspaces.mdx +109 -0
- package/docs/project/benchmarking.mdx +218 -0
- package/docs/project/bindgen.mdx +223 -0
- package/docs/project/building-windows.mdx +133 -0
- package/docs/project/contributing.mdx +343 -0
- package/docs/project/feedback.mdx +20 -0
- package/docs/project/license.mdx +78 -0
- package/docs/project/roadmap.mdx +8 -0
- package/docs/quickstart.mdx +240 -0
- package/docs/runtime/auto-install.mdx +97 -0
- package/docs/runtime/binary-data.mdx +846 -0
- package/docs/runtime/bun-apis.mdx +59 -0
- package/docs/runtime/bunfig.mdx +642 -0
- package/docs/runtime/c-compiler.mdx +204 -0
- package/docs/runtime/child-process.mdx +532 -0
- package/docs/runtime/color.mdx +267 -0
- package/docs/runtime/console.mdx +67 -0
- package/docs/runtime/cookies.mdx +454 -0
- package/docs/runtime/debugger.mdx +335 -0
- package/docs/runtime/environment-variables.mdx +214 -0
- package/docs/runtime/ffi.mdx +565 -0
- package/docs/runtime/file-io.mdx +306 -0
- package/docs/runtime/file-system-router.mdx +118 -0
- package/docs/runtime/file-types.mdx +354 -0
- package/docs/runtime/glob.mdx +181 -0
- package/docs/runtime/globals.mdx +72 -0
- package/docs/runtime/hashing.mdx +315 -0
- package/docs/runtime/html-rewriter.mdx +340 -0
- package/docs/runtime/http/cookies.mdx +79 -0
- package/docs/runtime/http/error-handling.mdx +40 -0
- package/docs/runtime/http/metrics.mdx +36 -0
- package/docs/runtime/http/routing.mdx +289 -0
- package/docs/runtime/http/server.mdx +647 -0
- package/docs/runtime/http/tls.mdx +101 -0
- package/docs/runtime/http/websockets.mdx +404 -0
- package/docs/runtime/index.mdx +223 -0
- package/docs/runtime/jsx.mdx +115 -0
- package/docs/runtime/module-resolution.mdx +342 -0
- package/docs/runtime/networking/dns.mdx +111 -0
- package/docs/runtime/networking/fetch.mdx +468 -0
- package/docs/runtime/networking/tcp.mdx +239 -0
- package/docs/runtime/networking/udp.mdx +129 -0
- package/docs/runtime/node-api.mdx +19 -0
- package/docs/runtime/nodejs-compat.mdx +468 -0
- package/docs/runtime/plugins.mdx +405 -0
- package/docs/runtime/redis.mdx +582 -0
- package/docs/runtime/s3.mdx +863 -0
- package/docs/runtime/secrets.mdx +336 -0
- package/docs/runtime/semver.mdx +57 -0
- package/docs/runtime/shell.mdx +637 -0
- package/docs/runtime/sql.mdx +1404 -0
- package/docs/runtime/sqlite.mdx +699 -0
- package/docs/runtime/streams.mdx +232 -0
- package/docs/runtime/templating/create.mdx +269 -0
- package/docs/runtime/templating/init.mdx +58 -0
- package/docs/runtime/transpiler.mdx +288 -0
- package/docs/runtime/typescript.mdx +58 -0
- package/docs/runtime/utils.mdx +922 -0
- package/docs/runtime/watch-mode.mdx +161 -0
- package/docs/runtime/web-apis.mdx +29 -0
- package/docs/runtime/workers.mdx +328 -0
- package/docs/runtime/yaml.mdx +469 -0
- package/docs/snippets/cli/add.mdx +166 -0
- package/docs/snippets/cli/build.mdx +196 -0
- package/docs/snippets/cli/feedback.mdx +17 -0
- package/docs/snippets/cli/init.mdx +84 -0
- package/docs/snippets/cli/install.mdx +173 -0
- package/docs/snippets/cli/link.mdx +163 -0
- package/docs/snippets/cli/outdated.mdx +140 -0
- package/docs/snippets/cli/patch.mdx +171 -0
- package/docs/snippets/cli/publish.mdx +198 -0
- package/docs/snippets/cli/remove.mdx +146 -0
- package/docs/snippets/cli/run.mdx +293 -0
- package/docs/snippets/cli/test.mdx +100 -0
- package/docs/snippets/cli/update.mdx +144 -0
- package/docs/snippets/product-card.mdx +32 -0
- package/docs/snippets/product-tiles.mdx +94 -0
- package/docs/test/code-coverage.mdx +409 -0
- package/docs/test/configuration.mdx +467 -0
- package/docs/test/dates-times.mdx +129 -0
- package/docs/test/discovery.mdx +90 -0
- package/docs/test/dom.mdx +226 -0
- package/docs/test/index.mdx +380 -0
- package/docs/test/lifecycle.mdx +348 -0
- package/docs/test/mocks.mdx +637 -0
- package/docs/test/reporters.mdx +117 -0
- package/docs/test/runtime-behavior.mdx +342 -0
- package/docs/test/snapshots.mdx +434 -0
- package/docs/test/writing-tests.mdx +635 -0
- package/docs/typescript.mdx +54 -0
- package/package.json +8 -6
- package/test.d.ts +2 -2
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: TLS
|
|
3
|
+
description: Enable TLS in Bun.serve
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Bun supports TLS out of the box, powered by [BoringSSL](https://boringssl.googlesource.com/boringssl). Enable TLS by passing in a value for `key` and `cert`; both are required to enable TLS.
|
|
7
|
+
|
|
8
|
+
```ts
|
|
9
|
+
Bun.serve({
|
|
10
|
+
tls: {
|
|
11
|
+
key: Bun.file("./key.pem"), // [!code ++]
|
|
12
|
+
cert: Bun.file("./cert.pem"), // [!code ++]
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The `key` and `cert` fields expect the _contents_ of your TLS key and certificate, _not a path to it_. This can be a string, `BunFile`, `TypedArray`, or `Buffer`.
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
Bun.serve({
|
|
21
|
+
tls: {
|
|
22
|
+
key: Bun.file("./key.pem"), // BunFile
|
|
23
|
+
key: fs.readFileSync("./key.pem"), // Buffer
|
|
24
|
+
key: fs.readFileSync("./key.pem", "utf8"), // string
|
|
25
|
+
key: [Bun.file("./key1.pem"), Bun.file("./key2.pem")], // array of above
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Passphrase
|
|
31
|
+
|
|
32
|
+
If your private key is encrypted with a passphrase, provide a value for `passphrase` to decrypt it.
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
Bun.serve({
|
|
36
|
+
tls: {
|
|
37
|
+
key: Bun.file("./key.pem"),
|
|
38
|
+
cert: Bun.file("./cert.pem"),
|
|
39
|
+
passphrase: "my-secret-passphrase", // [!code ++]
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### CA Certificates
|
|
45
|
+
|
|
46
|
+
Optionally, you can override the trusted CA certificates by passing a value for `ca`. By default, the server will trust the list of well-known CAs curated by Mozilla. When `ca` is specified, the Mozilla list is overwritten.
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
Bun.serve({
|
|
50
|
+
tls: {
|
|
51
|
+
key: Bun.file("./key.pem"), // path to TLS key
|
|
52
|
+
cert: Bun.file("./cert.pem"), // path to TLS cert
|
|
53
|
+
ca: Bun.file("./ca.pem"), // path to root CA certificate // [!code ++]
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Diffie-Hellman
|
|
59
|
+
|
|
60
|
+
To override Diffie-Hellman parameters:
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
Bun.serve({
|
|
64
|
+
tls: {
|
|
65
|
+
dhParamsFile: "/path/to/dhparams.pem", // path to Diffie Hellman parameters // [!code ++]
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Server name indication (SNI)
|
|
73
|
+
|
|
74
|
+
To configure the server name indication (SNI) for the server, set the `serverName` field in the `tls` object.
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
Bun.serve({
|
|
78
|
+
tls: {
|
|
79
|
+
serverName: "my-server.com", // SNI // [!code ++]
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
To allow multiple server names, pass an array of objects to `tls`, each with a `serverName` field.
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
Bun.serve({
|
|
88
|
+
tls: [
|
|
89
|
+
{
|
|
90
|
+
key: Bun.file("./key1.pem"),
|
|
91
|
+
cert: Bun.file("./cert1.pem"),
|
|
92
|
+
serverName: "my-server1.com", // [!code ++]
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
key: Bun.file("./key2.pem"),
|
|
96
|
+
cert: Bun.file("./cert2.pem"),
|
|
97
|
+
serverName: "my-server2.com", // [!code ++]
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
});
|
|
101
|
+
```
|
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: WebSockets
|
|
3
|
+
description: Server-side WebSockets in Bun
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
`Bun.serve()` supports server-side WebSockets, with on-the-fly compression, TLS support, and a Bun-native publish-subscribe API.
|
|
7
|
+
|
|
8
|
+
<Info>
|
|
9
|
+
|
|
10
|
+
**⚡️ 7x more throughput**
|
|
11
|
+
|
|
12
|
+
Bun's WebSockets are fast. For a [simple chatroom](https://github.com/oven-sh/bun/tree/main/bench/websocket-server/README.md) on Linux x64, Bun can handle 7x more requests per second than Node.js + [`"ws"`](https://github.com/websockets/ws).
|
|
13
|
+
|
|
14
|
+
| **Messages sent per second** | **Runtime** | **Clients** |
|
|
15
|
+
| ---------------------------- | ------------------------------ | ----------- |
|
|
16
|
+
| ~700,000 | (`Bun.serve`) Bun v0.2.1 (x64) | 16 |
|
|
17
|
+
| ~100,000 | (`ws`) Node v18.10.0 (x64) | 16 |
|
|
18
|
+
|
|
19
|
+
Internally Bun's WebSocket implementation is built on [uWebSockets](https://github.com/uNetworking/uWebSockets).
|
|
20
|
+
|
|
21
|
+
</Info>
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Start a WebSocket server
|
|
26
|
+
|
|
27
|
+
Below is a simple WebSocket server built with `Bun.serve`, in which all incoming requests are [upgraded](https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism) to WebSocket connections in the `fetch` handler. The socket handlers are declared in the `websocket` parameter.
|
|
28
|
+
|
|
29
|
+
```ts server.ts icon="/icons/typescript.svg"
|
|
30
|
+
Bun.serve({
|
|
31
|
+
fetch(req, server) {
|
|
32
|
+
// upgrade the request to a WebSocket
|
|
33
|
+
if (server.upgrade(req)) {
|
|
34
|
+
return; // do not return a Response
|
|
35
|
+
}
|
|
36
|
+
return new Response("Upgrade failed", { status: 500 });
|
|
37
|
+
},
|
|
38
|
+
websocket: {}, // handlers
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
The following WebSocket event handlers are supported:
|
|
43
|
+
|
|
44
|
+
```ts server.ts icon="/icons/typescript.svg"
|
|
45
|
+
Bun.serve({
|
|
46
|
+
fetch(req, server) {}, // upgrade logic
|
|
47
|
+
websocket: {
|
|
48
|
+
message(ws, message) {}, // a message is received
|
|
49
|
+
open(ws) {}, // a socket is opened
|
|
50
|
+
close(ws, code, message) {}, // a socket is closed
|
|
51
|
+
drain(ws) {}, // the socket is ready to receive more data
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
<Accordion title="An API designed for speed">
|
|
57
|
+
|
|
58
|
+
In Bun, handlers are declared once per server, instead of per socket.
|
|
59
|
+
|
|
60
|
+
`ServerWebSocket` expects you to pass a `WebSocketHandler` object to the `Bun.serve()` method which has methods for `open`, `message`, `close`, `drain`, and `error`. This is different than the client-side `WebSocket` class which extends `EventTarget` (onmessage, onopen, onclose),
|
|
61
|
+
|
|
62
|
+
Clients tend to not have many socket connections open so an event-based API makes sense.
|
|
63
|
+
|
|
64
|
+
But servers tend to have **many** socket connections open, which means:
|
|
65
|
+
|
|
66
|
+
- Time spent adding/removing event listeners for each connection adds up
|
|
67
|
+
- Extra memory spent on storing references to callbacks function for each connection
|
|
68
|
+
- Usually, people create new functions for each connection, which also means more memory
|
|
69
|
+
|
|
70
|
+
So, instead of using an event-based API, `ServerWebSocket` expects you to pass a single object with methods for each event in `Bun.serve()` and it is reused for each connection.
|
|
71
|
+
|
|
72
|
+
This leads to less memory usage and less time spent adding/removing event listeners.
|
|
73
|
+
|
|
74
|
+
</Accordion>
|
|
75
|
+
|
|
76
|
+
The first argument to each handler is the instance of `ServerWebSocket` handling the event. The `ServerWebSocket` class is a fast, Bun-native implementation of [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) with some additional features.
|
|
77
|
+
|
|
78
|
+
```ts server.ts icon="/icons/typescript.svg"
|
|
79
|
+
Bun.serve({
|
|
80
|
+
fetch(req, server) {}, // upgrade logic
|
|
81
|
+
websocket: {
|
|
82
|
+
message(ws, message) {
|
|
83
|
+
ws.send(message); // echo back the message
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Sending messages
|
|
90
|
+
|
|
91
|
+
Each `ServerWebSocket` instance has a `.send()` method for sending messages to the client. It supports a range of input types.
|
|
92
|
+
|
|
93
|
+
```ts server.ts icon="/icons/typescript.svg" focus={4-6}
|
|
94
|
+
Bun.serve({
|
|
95
|
+
fetch(req, server) {}, // upgrade logic
|
|
96
|
+
websocket: {
|
|
97
|
+
message(ws, message) {
|
|
98
|
+
ws.send("Hello world"); // string
|
|
99
|
+
ws.send(response.arrayBuffer()); // ArrayBuffer
|
|
100
|
+
ws.send(new Uint8Array([1, 2, 3])); // TypedArray | DataView
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Headers
|
|
107
|
+
|
|
108
|
+
Once the upgrade succeeds, Bun will send a `101 Switching Protocols` response per the [spec](https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism). Additional `headers` can be attached to this `Response` in the call to `server.upgrade()`.
|
|
109
|
+
|
|
110
|
+
```ts server.ts icon="/icons/typescript.svg"
|
|
111
|
+
Bun.serve({
|
|
112
|
+
fetch(req, server) {
|
|
113
|
+
const sessionId = await generateSessionId();
|
|
114
|
+
server.upgrade(req, {
|
|
115
|
+
headers: {
|
|
116
|
+
// [!code ++]
|
|
117
|
+
"Set-Cookie": `SessionId=${sessionId}`, // [!code ++]
|
|
118
|
+
}, // [!code ++]
|
|
119
|
+
});
|
|
120
|
+
},
|
|
121
|
+
websocket: {}, // handlers
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Contextual data
|
|
126
|
+
|
|
127
|
+
Contextual `data` can be attached to a new WebSocket in the `.upgrade()` call. This data is made available on the `ws.data` property inside the WebSocket handlers.
|
|
128
|
+
|
|
129
|
+
```ts server.ts icon="/icons/typescript.svg"
|
|
130
|
+
type WebSocketData = {
|
|
131
|
+
createdAt: number;
|
|
132
|
+
channelId: string;
|
|
133
|
+
authToken: string;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
Bun.serve({
|
|
137
|
+
fetch(req, server) {
|
|
138
|
+
const cookies = new Bun.CookieMap(req.headers.get("cookie")!);
|
|
139
|
+
|
|
140
|
+
server.upgrade(req, {
|
|
141
|
+
// this object must conform to WebSocketData
|
|
142
|
+
data: {
|
|
143
|
+
createdAt: Date.now(),
|
|
144
|
+
channelId: new URL(req.url).searchParams.get("channelId"),
|
|
145
|
+
authToken: cookies.get("X-Token"),
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
return undefined;
|
|
150
|
+
},
|
|
151
|
+
websocket: {
|
|
152
|
+
// TypeScript: specify the type of ws.data like this
|
|
153
|
+
data: {} as WebSocketData,
|
|
154
|
+
// handler called when a message is received
|
|
155
|
+
async message(ws, message) {
|
|
156
|
+
// ws.data is now properly typed as WebSocketData
|
|
157
|
+
const user = getUserFromToken(ws.data.authToken);
|
|
158
|
+
|
|
159
|
+
await saveMessageToDatabase({
|
|
160
|
+
channel: ws.data.channelId,
|
|
161
|
+
message: String(message),
|
|
162
|
+
userId: user.id,
|
|
163
|
+
});
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
To connect to this server from the browser, create a new `WebSocket`.
|
|
170
|
+
|
|
171
|
+
```ts browser.js icon="file-code"
|
|
172
|
+
const socket = new WebSocket("ws://localhost:3000/chat");
|
|
173
|
+
|
|
174
|
+
socket.addEventListener("message", event => {
|
|
175
|
+
console.log(event.data);
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
<Info>
|
|
180
|
+
**Identifying users**
|
|
181
|
+
|
|
182
|
+
The cookies that are currently set on the page will be sent with the WebSocket upgrade request and available on `req.headers` in the `fetch` handler. Parse these cookies to determine the identity of the connecting user and set the value of `data` accordingly.
|
|
183
|
+
|
|
184
|
+
</Info>
|
|
185
|
+
|
|
186
|
+
### Pub/Sub
|
|
187
|
+
|
|
188
|
+
Bun's `ServerWebSocket` implementation implements a native publish-subscribe API for topic-based broadcasting. Individual sockets can `.subscribe()` to a topic (specified with a string identifier) and `.publish()` messages to all other subscribers to that topic (excluding itself). This topic-based broadcast API is similar to [MQTT](https://en.wikipedia.org/wiki/MQTT) and [Redis Pub/Sub](https://redis.io/topics/pubsub).
|
|
189
|
+
|
|
190
|
+
```ts server.ts icon="/icons/typescript.svg"
|
|
191
|
+
const server = Bun.serve({
|
|
192
|
+
fetch(req, server) {
|
|
193
|
+
const url = new URL(req.url);
|
|
194
|
+
if (url.pathname === "/chat") {
|
|
195
|
+
console.log(`upgrade!`);
|
|
196
|
+
const username = getUsernameFromReq(req);
|
|
197
|
+
const success = server.upgrade(req, { data: { username } });
|
|
198
|
+
return success ? undefined : new Response("WebSocket upgrade error", { status: 400 });
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return new Response("Hello world");
|
|
202
|
+
},
|
|
203
|
+
websocket: {
|
|
204
|
+
// TypeScript: specify the type of ws.data like this
|
|
205
|
+
data: {} as { username: string },
|
|
206
|
+
open(ws) {
|
|
207
|
+
const msg = `${ws.data.username} has entered the chat`;
|
|
208
|
+
ws.subscribe("the-group-chat");
|
|
209
|
+
server.publish("the-group-chat", msg);
|
|
210
|
+
},
|
|
211
|
+
message(ws, message) {
|
|
212
|
+
// this is a group chat
|
|
213
|
+
// so the server re-broadcasts incoming message to everyone
|
|
214
|
+
server.publish("the-group-chat", `${ws.data.username}: ${message}`);
|
|
215
|
+
},
|
|
216
|
+
close(ws) {
|
|
217
|
+
const msg = `${ws.data.username} has left the chat`;
|
|
218
|
+
ws.unsubscribe("the-group-chat");
|
|
219
|
+
server.publish("the-group-chat", msg);
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
console.log(`Listening on ${server.hostname}:${server.port}`);
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Calling `.publish(data)` will send the message to all subscribers of a topic _except_ the socket that called `.publish()`. To send a message to all subscribers of a topic, use the `.publish()` method on the `Server` instance.
|
|
228
|
+
|
|
229
|
+
```ts
|
|
230
|
+
const server = Bun.serve({
|
|
231
|
+
websocket: {
|
|
232
|
+
// ...
|
|
233
|
+
},
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// listen for some external event
|
|
237
|
+
server.publish("the-group-chat", "Hello world");
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Compression
|
|
241
|
+
|
|
242
|
+
Per-message [compression](https://websockets.readthedocs.io/en/stable/topics/compression.html) can be enabled with the `perMessageDeflate` parameter.
|
|
243
|
+
|
|
244
|
+
```ts server.ts icon="/icons/typescript.svg"
|
|
245
|
+
Bun.serve({
|
|
246
|
+
websocket: {
|
|
247
|
+
perMessageDeflate: true, // [!code ++]
|
|
248
|
+
},
|
|
249
|
+
});
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Compression can be enabled for individual messages by passing a `boolean` as the second argument to `.send()`.
|
|
253
|
+
|
|
254
|
+
```ts
|
|
255
|
+
ws.send("Hello world", true);
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
For fine-grained control over compression characteristics, refer to the [Reference](#reference).
|
|
259
|
+
|
|
260
|
+
### Backpressure
|
|
261
|
+
|
|
262
|
+
The `.send(message)` method of `ServerWebSocket` returns a `number` indicating the result of the operation.
|
|
263
|
+
|
|
264
|
+
- `-1` — The message was enqueued but there is backpressure
|
|
265
|
+
- `0` — The message was dropped due to a connection issue
|
|
266
|
+
- `1+` — The number of bytes sent
|
|
267
|
+
|
|
268
|
+
This gives you better control over backpressure in your server.
|
|
269
|
+
|
|
270
|
+
### Timeouts and limits
|
|
271
|
+
|
|
272
|
+
By default, Bun will close a WebSocket connection if it is idle for 120 seconds. This can be configured with the `idleTimeout` parameter.
|
|
273
|
+
|
|
274
|
+
```ts
|
|
275
|
+
Bun.serve({
|
|
276
|
+
fetch(req, server) {}, // upgrade logic
|
|
277
|
+
websocket: {
|
|
278
|
+
idleTimeout: 60, // 60 seconds // [!code ++]
|
|
279
|
+
},
|
|
280
|
+
});
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Bun will also close a WebSocket connection if it receives a message that is larger than 16 MB. This can be configured with the `maxPayloadLength` parameter.
|
|
284
|
+
|
|
285
|
+
```ts
|
|
286
|
+
Bun.serve({
|
|
287
|
+
fetch(req, server) {}, // upgrade logic
|
|
288
|
+
websocket: {
|
|
289
|
+
maxPayloadLength: 1024 * 1024, // 1 MB // [!code ++]
|
|
290
|
+
},
|
|
291
|
+
});
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## Connect to a `Websocket` server
|
|
297
|
+
|
|
298
|
+
Bun implements the `WebSocket` class. To create a WebSocket client that connects to a `ws://` or `wss://` server, create an instance of `WebSocket`, as you would in the browser.
|
|
299
|
+
|
|
300
|
+
```ts
|
|
301
|
+
const socket = new WebSocket("ws://localhost:3000");
|
|
302
|
+
|
|
303
|
+
// With subprotocol negotiation
|
|
304
|
+
const socket2 = new WebSocket("ws://localhost:3000", ["soap", "wamp"]);
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
In browsers, the cookies that are currently set on the page will be sent with the WebSocket upgrade request. This is a standard feature of the `WebSocket` API.
|
|
308
|
+
|
|
309
|
+
For convenience, Bun lets you setting custom headers directly in the constructor. This is a Bun-specific extension of the `WebSocket` standard. _This will not work in browsers._
|
|
310
|
+
|
|
311
|
+
```ts
|
|
312
|
+
const socket = new WebSocket("ws://localhost:3000", {
|
|
313
|
+
headers: {
|
|
314
|
+
/* custom headers */
|
|
315
|
+
}, // [!code ++]
|
|
316
|
+
});
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
To add event listeners to the socket:
|
|
320
|
+
|
|
321
|
+
```ts
|
|
322
|
+
// message is received
|
|
323
|
+
socket.addEventListener("message", event => {});
|
|
324
|
+
|
|
325
|
+
// socket opened
|
|
326
|
+
socket.addEventListener("open", event => {});
|
|
327
|
+
|
|
328
|
+
// socket closed
|
|
329
|
+
socket.addEventListener("close", event => {});
|
|
330
|
+
|
|
331
|
+
// error handler
|
|
332
|
+
socket.addEventListener("error", event => {});
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## Reference
|
|
338
|
+
|
|
339
|
+
```ts See Typescript Definitions expandable
|
|
340
|
+
namespace Bun {
|
|
341
|
+
export function serve(params: {
|
|
342
|
+
fetch: (req: Request, server: Server) => Response | Promise<Response>;
|
|
343
|
+
websocket?: {
|
|
344
|
+
message: (ws: ServerWebSocket, message: string | ArrayBuffer | Uint8Array) => void;
|
|
345
|
+
open?: (ws: ServerWebSocket) => void;
|
|
346
|
+
close?: (ws: ServerWebSocket, code: number, reason: string) => void;
|
|
347
|
+
error?: (ws: ServerWebSocket, error: Error) => void;
|
|
348
|
+
drain?: (ws: ServerWebSocket) => void;
|
|
349
|
+
|
|
350
|
+
maxPayloadLength?: number; // default: 16 * 1024 * 1024 = 16 MB
|
|
351
|
+
idleTimeout?: number; // default: 120 (seconds)
|
|
352
|
+
backpressureLimit?: number; // default: 1024 * 1024 = 1 MB
|
|
353
|
+
closeOnBackpressureLimit?: boolean; // default: false
|
|
354
|
+
sendPings?: boolean; // default: true
|
|
355
|
+
publishToSelf?: boolean; // default: false
|
|
356
|
+
|
|
357
|
+
perMessageDeflate?:
|
|
358
|
+
| boolean
|
|
359
|
+
| {
|
|
360
|
+
compress?: boolean | Compressor;
|
|
361
|
+
decompress?: boolean | Compressor;
|
|
362
|
+
};
|
|
363
|
+
};
|
|
364
|
+
}): Server;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
type Compressor =
|
|
368
|
+
| `"disable"`
|
|
369
|
+
| `"shared"`
|
|
370
|
+
| `"dedicated"`
|
|
371
|
+
| `"3KB"`
|
|
372
|
+
| `"4KB"`
|
|
373
|
+
| `"8KB"`
|
|
374
|
+
| `"16KB"`
|
|
375
|
+
| `"32KB"`
|
|
376
|
+
| `"64KB"`
|
|
377
|
+
| `"128KB"`
|
|
378
|
+
| `"256KB"`;
|
|
379
|
+
|
|
380
|
+
interface Server {
|
|
381
|
+
pendingWebSockets: number;
|
|
382
|
+
publish(topic: string, data: string | ArrayBufferView | ArrayBuffer, compress?: boolean): number;
|
|
383
|
+
upgrade(
|
|
384
|
+
req: Request,
|
|
385
|
+
options?: {
|
|
386
|
+
headers?: HeadersInit;
|
|
387
|
+
data?: any;
|
|
388
|
+
},
|
|
389
|
+
): boolean;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
interface ServerWebSocket {
|
|
393
|
+
readonly data: any;
|
|
394
|
+
readonly readyState: number;
|
|
395
|
+
readonly remoteAddress: string;
|
|
396
|
+
send(message: string | ArrayBuffer | Uint8Array, compress?: boolean): number;
|
|
397
|
+
close(code?: number, reason?: string): void;
|
|
398
|
+
subscribe(topic: string): void;
|
|
399
|
+
unsubscribe(topic: string): void;
|
|
400
|
+
publish(topic: string, message: string | ArrayBuffer | Uint8Array): void;
|
|
401
|
+
isSubscribed(topic: string): boolean;
|
|
402
|
+
cork(cb: (ws: ServerWebSocket) => void): void;
|
|
403
|
+
}
|
|
404
|
+
```
|