From 65c71c7959fe46ba343bfe3f3d1b35a6efef0487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Fern=C3=A1ndez=20L=C3=B3pez?= Date: Wed, 13 Sep 2023 11:41:18 +0200 Subject: [PATCH] Document catch all routes (#214) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: document catch-all routes --------- Co-authored-by: Ángel M --- docs/docs/features/all.md | 16 ++--- docs/docs/features/dynamic-routes.md | 66 ++++++++++++++++++--- docs/docs/features/environment-variables.md | 16 ++--- docs/docs/features/http-requests.md | 16 ++--- docs/docs/features/key-value.md | 16 ++--- docs/docs/features/machine-learning.md | 14 ++--- docs/docs/features/mount-folders.md | 16 ++--- examples/js-catchall/README.md | 23 +++++++ examples/js-catchall/[...slug]/index.js | 58 ++++++++++++++++++ examples/js-catchall/about.js | 58 ++++++++++++++++++ examples/js-catchall/other/[...slug].js | 58 ++++++++++++++++++ 11 files changed, 302 insertions(+), 55 deletions(-) create mode 100644 examples/js-catchall/README.md create mode 100644 examples/js-catchall/[...slug]/index.js create mode 100644 examples/js-catchall/about.js create mode 100644 examples/js-catchall/other/[...slug].js diff --git a/docs/docs/features/all.md b/docs/docs/features/all.md index c2a9ff66..3c2bf85b 100644 --- a/docs/docs/features/all.md +++ b/docs/docs/features/all.md @@ -29,11 +29,11 @@ You can develop workers in different languages. However, not all of them support The following table shows the language compatibility for the different worker functions: -| Language | K/V Store | Environment Variables | Dynamic Routes | Folders | HTTP Requests | -| --- | --- | --- | --- | --- | --- | -| JavaScript | ✅ | ✅ | ✅ | ❌ | ✅ | -| Rust | ✅ | ✅ | ✅ | ✅ | ✅ | -| Go | ✅ | ✅ | ✅ | ✅ | ✅ | -| Ruby | ✅ | ✅ | ✅ | ✅ | ❌ | -| Python | ✅ | ✅ | ✅ | ✅ | ❌ | -| Zig | ✅ | ❌ | ✅ | ✅ | ❌ | +| Language | K/V Store | Environment Variables | Dynamic Routes | Folders | HTTP Requests | +|------------|-----------|-----------------------|----------------|---------|---------------| +| JavaScript | ✅ | ✅ | ✅ | ❌ | ✅ | +| Rust | ✅ | ✅ | ✅ | ✅ | ✅ | +| Go | ✅ | ✅ | ✅ | ✅ | ✅ | +| Ruby | ✅ | ✅ | ✅ | ✅ | ❌ | +| Python | ✅ | ✅ | ✅ | ✅ | ❌ | +| Zig | ✅ | ❌ | ✅ | ✅ | ❌ | diff --git a/docs/docs/features/dynamic-routes.md b/docs/docs/features/dynamic-routes.md index 7c0724b9..05b3a3c1 100644 --- a/docs/docs/features/dynamic-routes.md +++ b/docs/docs/features/dynamic-routes.md @@ -56,13 +56,63 @@ $ tree . In this case, the `./[resource]/[id]/show.js` worker replies to URLs like `/articles/2/show`. +## Catch-all routes + +Catch-all routes are route segments that can be matched with any path segment on the route. For example, you can use catch-all routes by having a directory structure like the following: + +``` +$ tree . +. +└── [...slug] + └── index.js +``` + +This means, that the JavaScript worker at `[...slug]/index.js` will serve any path beneath. You can mix and match specific routes with catch-all routes. For example, given the following directory structure: + +``` +$ tree . +. +├── about.js +└── [...slug] + └── index.js +``` + +In this example, two workers are fulfilling HTTP requests: + +- `/about` is served by the `about.js` worker. +- Anything else under `/` is served by the `[...slug]/index.js` worker. + +You can also place multiple catch-all routes as long as they are splitted by a non-catch-all segment. For example: + +``` +$ tree . +. +├── about.js +├── other +│   └── [...slug] +│   └── index.js +└── [...slug] + └── index.js +``` + +Here, we have the same structure as in the previous example, but we have two catch-all, under two different roots: + +- One catch-all, `[...slug]/index.js` is serving all requests, except for requests whose path starts with `/about` or `/other`. +- Another catch-all, `other/[...slug]/index.js` serves all requests under the `/other` path. + +**You can also define segments at at the trailing of the URL**, by having a worker in the filesystem of the form `/some/resource/[...slug].js`. This worker will serve requests at the path `/some/resource/`. + +### Routing priority + +Given catch-all routes could potentially shadow other routes, it is important to settle precedence when routing requests. **The rule of thumb is more specific routes win**. For example, a route with no catch-all will always against a route with catch-all when they are at the same depth. + ## Language compatibility -| Language | Dynamic routes | -| --- | --- | -| JavaScript | ✅ | -| Rust | ✅ | -| Go | ✅ | -| Ruby | ✅ | -| Python | ✅ | -| Zig | ✅ | +| Language | Dynamic routes | +|------------|----------------| +| JavaScript | ✅ | +| Rust | ✅ | +| Go | ✅ | +| Ruby | ✅ | +| Python | ✅ | +| Zig | ✅ | diff --git a/docs/docs/features/environment-variables.md b/docs/docs/features/environment-variables.md index fea3fdfd..f6f9917a 100644 --- a/docs/docs/features/environment-variables.md +++ b/docs/docs/features/environment-variables.md @@ -43,11 +43,11 @@ This feature allows you to configure environment variables dynamically. ## Language compatibility -| Language | Environment variables | -| --- | --- | -| JavaScript | ✅ | -| Rust | ✅ | -| Go | ✅ | -| Ruby | ✅ | -| Python | ✅ | -| Zig | ❌ | +| Language | Environment variables | +|------------|-----------------------| +| JavaScript | ✅ | +| Rust | ✅ | +| Go | ✅ | +| Ruby | ✅ | +| Python | ✅ | +| Zig | ❌ | diff --git a/docs/docs/features/http-requests.md b/docs/docs/features/http-requests.md index d1abda7a..9d1da915 100644 --- a/docs/docs/features/http-requests.md +++ b/docs/docs/features/http-requests.md @@ -37,11 +37,11 @@ Check these guides to perform HTTP requests in the different supported languages ## Language compatibility -| Language | HTTP Requests | -| --- | --- | -| JavaScript | ✅ | -| Rust | ✅ | -| Go | ✅ | -| Ruby | ❌ | -| Python | ❌ | -| Zig | ❌ | +| Language | HTTP Requests | +|------------|---------------| +| JavaScript | ✅ | +| Rust | ✅ | +| Go | ✅ | +| Ruby | ❌ | +| Python | ❌ | +| Zig | ❌ | diff --git a/docs/docs/features/key-value.md b/docs/docs/features/key-value.md index b46e40bb..41682c7e 100644 --- a/docs/docs/features/key-value.md +++ b/docs/docs/features/key-value.md @@ -29,11 +29,11 @@ A known limitation of the snapshot approach is the data override when concurrent ## Language compatibility -| Language | K/V store | -| --- | --- | -| JavaScript | ✅ | -| Rust | ✅ | -| Go | ✅ | -| Ruby | ✅ | -| Python | ✅ | -| Zig | ✅ | +| Language | K/V store | +|------------|-----------| +| JavaScript | ✅ | +| Rust | ✅ | +| Go | ✅ | +| Ruby | ✅ | +| Python | ✅ | +| Zig | ✅ | diff --git a/docs/docs/features/machine-learning.md b/docs/docs/features/machine-learning.md index 4ebf9c12..e056c7a9 100644 --- a/docs/docs/features/machine-learning.md +++ b/docs/docs/features/machine-learning.md @@ -63,10 +63,10 @@ We recommend to check this example to get started with ML and Wasm Workers Serve ## Language compatibility -| Language | Machine learning inference | -| --- | --- | -| JavaScript | ❌ | -| Rust | ✅ | -| Go | ❌ | -| Ruby | ❌ | -| Python | ❌ | +| Language | Machine learning inference | +|------------|----------------------------| +| JavaScript | ❌ | +| Rust | ✅ | +| Go | ❌ | +| Ruby | ❌ | +| Python | ❌ | diff --git a/docs/docs/features/mount-folders.md b/docs/docs/features/mount-folders.md index 12f1c1d2..ea199892 100644 --- a/docs/docs/features/mount-folders.md +++ b/docs/docs/features/mount-folders.md @@ -42,11 +42,11 @@ Note that those folders may include files that `wws` recognizes as workers (like ## Language compatibility -| Language | Mount folders | -| --- | --- | -| JavaScript | ❌ | -| Rust | ✅ | -| Go | ✅ | -| Ruby | ✅ | -| Python | ✅ | -| Zig | ✅ | +| Language | Mount folders | +|------------|---------------| +| JavaScript | ❌ | +| Rust | ✅ | +| Go | ✅ | +| Ruby | ✅ | +| Python | ✅ | +| Zig | ✅ | diff --git a/examples/js-catchall/README.md b/examples/js-catchall/README.md new file mode 100644 index 00000000..acbaad2a --- /dev/null +++ b/examples/js-catchall/README.md @@ -0,0 +1,23 @@ +# JavaScript catch-all example + +This worker showcases how catch-all routes can be used by your workers. + + +## Prerequisites + +* Wasm Workers Server (wws): + + ```shell-session + curl -fsSL https://workers.wasmlabs.dev/install | bash + ``` + +## Run + +```shell-session +wws https://github.com/vmware-labs/wasm-workers-server.git -i --git-folder "examples/js-catchall" +``` + +## Resources + +* [Catch-all routes](https://workers.wasmlabs.dev/docs/features/catch-all-routes) +* [JavaScript documentation](https://workers.wasmlabs.dev/docs/languages/javascript) diff --git a/examples/js-catchall/[...slug]/index.js b/examples/js-catchall/[...slug]/index.js new file mode 100644 index 00000000..d29449fc --- /dev/null +++ b/examples/js-catchall/[...slug]/index.js @@ -0,0 +1,58 @@ +/** + * Builds a reply to the given request + */ +const reply = (request) => { + if (request.method != "GET") { + // Don't allow other methods. + // Here you can see how to return a custom status + return new Response("Method not allowed", { + status: 405 + }); + } + + // Body response + const body = ` + + Wasm Workers Server + + + + + + +
+

Hello from Wasm Workers Server 👋

+
Replying to ${request.url}
+Method: ${request.method}
+User Agent: ${request.headers.get("user-agent")}
+Payload: ${request.body || "-"}
+

+ This worker is replying to the top-level catch-all endpoint. +

+

+ This page was generated by a JavaScript file running in WebAssembly. +

+
+`; + + // Build a new response + let response = new Response(body); + + // Add a new header + response.headers.set("x-generated-by", "wasm-workers-server"); + + return response; +} + +// Subscribe to the Fetch event +addEventListener("fetch", event => { + return event.respondWith(reply(event.request)); +}); diff --git a/examples/js-catchall/about.js b/examples/js-catchall/about.js new file mode 100644 index 00000000..8aa5a5b6 --- /dev/null +++ b/examples/js-catchall/about.js @@ -0,0 +1,58 @@ +/** + * Builds a reply to the given request + */ +const reply = (request) => { + if (request.method != "GET") { + // Don't allow other methods. + // Here you can see how to return a custom status + return new Response("Method not allowed", { + status: 405 + }); + } + + // Body response + const body = ` + + Wasm Workers Server + + + + + + +
+

Hello from Wasm Workers Server 👋

+
Replying to ${request.url}
+Method: ${request.method}
+User Agent: ${request.headers.get("user-agent")}
+Payload: ${request.body || "-"}
+

+ This worker is replying to the /about endpoint. +

+

+ This page was generated by a JavaScript file running in WebAssembly. +

+
+`; + + // Build a new response + let response = new Response(body); + + // Add a new header + response.headers.set("x-generated-by", "wasm-workers-server"); + + return response; +} + +// Subscribe to the Fetch event +addEventListener("fetch", event => { + return event.respondWith(reply(event.request)); +}); diff --git a/examples/js-catchall/other/[...slug].js b/examples/js-catchall/other/[...slug].js new file mode 100644 index 00000000..b3fd6d4d --- /dev/null +++ b/examples/js-catchall/other/[...slug].js @@ -0,0 +1,58 @@ +/** + * Builds a reply to the given request + */ +const reply = (request) => { + if (request.method != "GET") { + // Don't allow other methods. + // Here you can see how to return a custom status + return new Response("Method not allowed", { + status: 405 + }); + } + + // Body response + const body = ` + + Wasm Workers Server + + + + + + +
+

Hello from Wasm Workers Server 👋

+
Replying to ${request.url}
+Method: ${request.method}
+User Agent: ${request.headers.get("user-agent")}
+Payload: ${request.body || "-"}
+

+ This worker is replying to the catch-all endpoint under /other. +

+

+ This page was generated by a JavaScript file running in WebAssembly. +

+
+`; + + // Build a new response + let response = new Response(body); + + // Add a new header + response.headers.set("x-generated-by", "wasm-workers-server"); + + return response; +} + +// Subscribe to the Fetch event +addEventListener("fetch", event => { + return event.respondWith(reply(event.request)); +});