@fastly/expressly 1.0.1-0 → 1.1.0
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/.nvmrc +1 -1
- package/README.md +0 -1
- package/dist/lib/routing/common.d.ts +11 -11
- package/dist/lib/routing/common.js +32 -33
- package/dist/lib/routing/error-middleware.d.ts +5 -5
- package/dist/lib/routing/request/index.d.ts +16 -9
- package/dist/lib/routing/request/index.js +17 -22
- package/dist/lib/routing/request-handler.d.ts +5 -5
- package/dist/lib/routing/response/headers.d.ts +9 -0
- package/dist/lib/routing/response/headers.js +29 -0
- package/dist/lib/routing/response/index.d.ts +16 -3
- package/dist/lib/routing/response/index.js +10 -7
- package/dist/lib/routing/router.js +48 -9
- package/package.json +13 -14
- package/tsconfig.json +4 -1
- package/yarn-error.log +2484 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -16
- package/.github/workflows/docs.yml +0 -52
- package/.github/workflows/release.yml +0 -39
- package/.husky/pre-commit +0 -4
- package/CHANGELOG.md +0 -9
- package/docs/.nvmrc +0 -1
- package/docs/README.md +0 -27
- package/docs/babel.config.js +0 -3
- package/docs/docs/config.md +0 -52
- package/docs/docs/handling-data/_category_.json +0 -4
- package/docs/docs/handling-data/cookies.md +0 -103
- package/docs/docs/handling-data/headers.md +0 -110
- package/docs/docs/handling-data/request.md +0 -82
- package/docs/docs/handling-data/response.md +0 -162
- package/docs/docs/handling-data/search-params.md +0 -45
- package/docs/docs/intro.md +0 -61
- package/docs/docs/middleware/_category_.json +0 -5
- package/docs/docs/middleware/controlling-flow.md +0 -41
- package/docs/docs/middleware/error-middleware.md +0 -41
- package/docs/docs/middleware/what-is-middleware.md +0 -31
- package/docs/docs/origin-data/_category_.json +0 -4
- package/docs/docs/origin-data/working-with-origins.md +0 -49
- package/docs/docs/routing.md +0 -163
- package/docs/docusaurus.config.js +0 -119
- package/docs/package.json +0 -48
- package/docs/sidebars.js +0 -31
- package/docs/src/components/HomepageFeatures.module.css +0 -11
- package/docs/src/components/HomepageFeatures.tsx +0 -62
- package/docs/src/css/custom.css +0 -45
- package/docs/src/pages/index.module.css +0 -35
- package/docs/src/pages/index.tsx +0 -109
- package/docs/static/.nojekyll +0 -0
- package/docs/static/img/favicon.ico +0 -0
- package/docs/static/img/logo-black.png +0 -0
- package/docs/static/img/logo-transparent.png +0 -0
- package/docs/static/img/logo.png +0 -0
- package/docs/static-host/Cargo.lock +0 -435
- package/docs/static-host/Cargo.toml +0 -16
- package/docs/static-host/fastly.toml +0 -9
- package/docs/static-host/rust-toolchain +0 -3
- package/docs/static-host/src/main.rs +0 -115
- package/docs/tsconfig.json +0 -7
- package/docs/yarn.lock +0 -8416
- package/src/index.ts +0 -11
- package/src/lib/routing/common.ts +0 -34
- package/src/lib/routing/error-middleware.ts +0 -23
- package/src/lib/routing/errors.ts +0 -18
- package/src/lib/routing/index.d.ts +0 -18
- package/src/lib/routing/request/cookie-map.ts +0 -42
- package/src/lib/routing/request/index.ts +0 -64
- package/src/lib/routing/request-handler.ts +0 -22
- package/src/lib/routing/response/index.ts +0 -113
- package/src/lib/routing/response/status-codes.ts +0 -57
- package/src/lib/routing/response/surrogate-keys.ts +0 -32
- package/src/lib/routing/router.ts +0 -191
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
sidebar_position: 5
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Query strings
|
|
6
|
-
|
|
7
|
-
Search (query string) parameters can be accessed in the `req.query` object, which implements the [URLSearchParams](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) interface.
|
|
8
|
-
|
|
9
|
-
## Get the value of a search parameter
|
|
10
|
-
|
|
11
|
-
Use `req.query.get(key)` to get the first value associated with a given search parameter. If you need to check whether a parameter is set, use `*.query.has(name)`:
|
|
12
|
-
|
|
13
|
-
```javascript
|
|
14
|
-
router.get("/page", (req, res) => {
|
|
15
|
-
if (req.query.has("id")) {
|
|
16
|
-
res.send(`Your page id is: ${req.query.get("id")}`)
|
|
17
|
-
} else {
|
|
18
|
-
res.send("No id! Add one like this: /page?id=123")
|
|
19
|
-
}
|
|
20
|
-
})
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
> 💡 You can use `req.query.getAll(key)` to get all the values of query string array.
|
|
24
|
-
|
|
25
|
-
## Listing search parameters
|
|
26
|
-
|
|
27
|
-
Use `req.query.entries()` method to iterate through all key/value pairs in the same order as they appear in the query string.
|
|
28
|
-
|
|
29
|
-
```javascript
|
|
30
|
-
for (const [key, value] of req.query.entries()) {
|
|
31
|
-
console.log(`Query parameter: ${key}`, value);
|
|
32
|
-
}
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
If you need only the keys or values, use `req.query.keys()` or `req.query.values()`, respectively.
|
|
36
|
-
|
|
37
|
-
## Manipulating query strings
|
|
38
|
-
|
|
39
|
-
`req.query` is a [URLSearchParams](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) object. You can use a bunch of utility methods to work with query parameters:
|
|
40
|
-
|
|
41
|
-
* **req.query.set(name, value)** sets the value of a given search parameter.
|
|
42
|
-
* **req.query.append(name, value)** appends a new search parameter.
|
|
43
|
-
* **req.query.delete(name)** removes a search parameter and its value(s).
|
|
44
|
-
* **req.query.sort()** sorts all query string parameters by name.
|
|
45
|
-
* **req.query.toString()** returns a serialized query string suitable for use in a URL.
|
package/docs/docs/intro.md
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
sidebar_position: 1
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Getting started
|
|
6
|
-
|
|
7
|
-
Discover **expressly** _in less than 5 minutes_.
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
First, head over to [developer.fastly.com](https://developer.fastly.com) to get started with JavaScript on Fastly's Compute@Edge:
|
|
12
|
-
|
|
13
|
-
1. Learn about Compute@Edge: [developer.fastly.com/learning/compute/](https://developer.fastly.com/learning/compute/)
|
|
14
|
-
2. Create your first JavaScript app: [developer.fastly.com/learning/compute/javascript/](https://developer.fastly.com/learning/compute/javascript/)
|
|
15
|
-
|
|
16
|
-
## Install expressly
|
|
17
|
-
|
|
18
|
-
Install expressly from the [npm registry](https://www.npmjs.com/package/@fastly/expressly):
|
|
19
|
-
|
|
20
|
-
```shell
|
|
21
|
-
npm i @fastly/expressly
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
```shell
|
|
25
|
-
yarn add @fastly/expressly
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Your first expressly app
|
|
29
|
-
|
|
30
|
-
Replace the contents of your Compute@Edge app's `src/index.js` with the following:
|
|
31
|
-
|
|
32
|
-
```javascript
|
|
33
|
-
import { Router } from "@fastly/expressly";
|
|
34
|
-
|
|
35
|
-
const router = new Router();
|
|
36
|
-
|
|
37
|
-
router.get("/", async (req, res) => {
|
|
38
|
-
return res.send("Hello world!");
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
router.listen();
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
## Try it out
|
|
45
|
-
|
|
46
|
-
Start your app locally:
|
|
47
|
-
|
|
48
|
-
```shell
|
|
49
|
-
fastly compute serve
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
This will start your service on [http://localhost:7676](http://localhost:7676).
|
|
53
|
-
|
|
54
|
-
### Live reloading
|
|
55
|
-
|
|
56
|
-
You can use a tool called [`nodemon`](https://www.npmjs.com/package/nodemon) to automatically reload your app when you make a change in your local development environment.
|
|
57
|
-
|
|
58
|
-
```shell
|
|
59
|
-
npx nodemon --exec \
|
|
60
|
-
"npm run build && fastly compute serve --skip-build"
|
|
61
|
-
```
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
sidebar_position: 2
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Controlling flow
|
|
6
|
-
|
|
7
|
-
**expressly** allows you to control the flow of a request with middleware.
|
|
8
|
-
|
|
9
|
-
For example, you could edit the Request object:
|
|
10
|
-
|
|
11
|
-
```javascript
|
|
12
|
-
router.use((req, res) => {
|
|
13
|
-
if (req.url.pathname == "/") {
|
|
14
|
-
req.url.pathname = "/home";
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
This will **not** redirect the user; instead, it will affect the route selection logic downstream. In this case, a subsequent `router.get("/")` will not match the request, but `router.get("/home")` will.
|
|
20
|
-
|
|
21
|
-
## Stopping a request
|
|
22
|
-
|
|
23
|
-
If you need to end the response process early (for example, in order to block unauthenticated requests), you can call [`res.end`](../handling-data/response.md#resend) (or [`res.send`](../handling-data/response.md#ressend)) from middleware.
|
|
24
|
-
|
|
25
|
-
```javascript
|
|
26
|
-
router.use("/account/", (req, res) => {
|
|
27
|
-
if(!("userId" in req.cookies)){
|
|
28
|
-
res.end("You must be logged in to view this page");
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
You can also end the response process by _redirecting_ to a different route:
|
|
34
|
-
|
|
35
|
-
```javascript
|
|
36
|
-
router.use("/account/", (req, res) => {
|
|
37
|
-
if(!("userId" in req.cookies)){
|
|
38
|
-
res.redirect("/login");
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
```
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
sidebar_position: 3
|
|
3
|
-
title: Handling errors
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Error middleware
|
|
7
|
-
|
|
8
|
-
**expressly** catches and processes errors that occur both synchronously and asynchronously.
|
|
9
|
-
|
|
10
|
-
```javascript
|
|
11
|
-
router.get("/", (req, res) => {
|
|
12
|
-
throw new Error("BROKEN"); // expressly will catch this.
|
|
13
|
-
})
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
## The default error handler
|
|
17
|
-
|
|
18
|
-
**expressly** comes with a built-in error handler that takes care of any errors that might be encountered in the app. This [default error-handling middleware](https://github.com/fastly/expressly/blob/main/src/lib/routing/router.ts#L12) function is added at the end of the router stack, after all other middleware and request handlers.
|
|
19
|
-
|
|
20
|
-
## Error-handling middleware
|
|
21
|
-
|
|
22
|
-
You can define custom error-handling middleware functions in the same way as other middleware functions, except with **three** arguments instead of two, specifically with the signature `(err, req, res)`.
|
|
23
|
-
|
|
24
|
-
The example below shows how to use error middleware to serve a custom error page:
|
|
25
|
-
|
|
26
|
-
```javascript
|
|
27
|
-
router.use((err, req, res) => {
|
|
28
|
-
console.error(err);
|
|
29
|
-
res.withStatus(500).send(`Uh-oh! Something went wrong: ${e.message}`);
|
|
30
|
-
});
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
If you only want error middleware to run on specific routes, you can pass a path to the middleware:
|
|
34
|
-
|
|
35
|
-
```javascript
|
|
36
|
-
router.use("/api/(.*)", (err, req, res) => {
|
|
37
|
-
console.log("Errored on handling a request to the API!");
|
|
38
|
-
});
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
> **expressly** uses [path-to-regexp](https://www.npmjs.com/package/path-to-regexp) to [pattern-match routes](../routing.md#route-matching).
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
sidebar_position: 1
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# What is middleware?
|
|
6
|
-
|
|
7
|
-
Middleware allows you to run code on a request before any routes are run. This is useful for things like authentication, header manipulation, and anything else that needs to happen before your routes are handled.
|
|
8
|
-
|
|
9
|
-
## router.use()
|
|
10
|
-
|
|
11
|
-
Middleware is attached by calling the `router.use()` method.
|
|
12
|
-
|
|
13
|
-
The example below shows how to use middleware to add a header to all requests:
|
|
14
|
-
|
|
15
|
-
```javascript
|
|
16
|
-
router.use((req, res) => {
|
|
17
|
-
res.setHeader("x-powered-by", "expressly");
|
|
18
|
-
});
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
> 🚨 **Unlike Express**, middleware accept only two arguments, `req` and `res`. **expressly** does away with the `next` function; all errors are caught and handled by [error middleware](error-middleware.md).
|
|
22
|
-
|
|
23
|
-
If you only want middleware to run on specific routes, you can pass a path to the middleware:
|
|
24
|
-
|
|
25
|
-
```javascript
|
|
26
|
-
router.use("/api/(.*)", (req, res) => {
|
|
27
|
-
console.log("Got a request to the API!");
|
|
28
|
-
});
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
> **expressly** uses [path-to-regexp](https://www.npmjs.com/package/path-to-regexp) to [pattern-match routes](../routing.md#route-matching). This means that your middleware mount paths can contain wildcards and even regular expressions.
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
sidebar_position: 1
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Working with origins
|
|
6
|
-
|
|
7
|
-
Accessing data from origins is done via the standard Fetch API available in Compute@Edge. [Read more on developer.fastly.com.](https://developer.fastly.com/learning/compute/javascript/#communicating-with-backend-servers-and-the-fastly-cache)
|
|
8
|
-
|
|
9
|
-
## Performance
|
|
10
|
-
|
|
11
|
-
> 💡 The most efficient way of proxying data from your origin to the client is to ensure you do not consume the body in your code.
|
|
12
|
-
|
|
13
|
-
Below, a `fetch()` request is made to an origin and the entire Response object passed through to `res.send()`. Doing this avoids reading the content of the response which saves processing time and memory.
|
|
14
|
-
|
|
15
|
-
```javascript
|
|
16
|
-
router.get("/origin", async (req, res) => {
|
|
17
|
-
res.send(await fetch(
|
|
18
|
-
"https://example.com", { backend: "my-origin" }
|
|
19
|
-
));
|
|
20
|
-
});
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
### `req` and `res`
|
|
24
|
-
|
|
25
|
-
`req` and `res` are compatible with anything that expects a `Request` or `Response`. It's therefore possible to pass `req` directly to `fetch()`, for example:
|
|
26
|
-
|
|
27
|
-
```javascript
|
|
28
|
-
router.get("/origin", async (req, res) => {
|
|
29
|
-
res.send(await fetch(
|
|
30
|
-
req, { backend: "my-origin" }
|
|
31
|
-
));
|
|
32
|
-
});
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## Reading a response
|
|
36
|
-
|
|
37
|
-
If you need to read the body of a response, you can do so like this:
|
|
38
|
-
|
|
39
|
-
```javascript
|
|
40
|
-
router.get("/api", async (req, res) => {
|
|
41
|
-
let originRequest = await fetch(
|
|
42
|
-
"https://example.com", { backend: "my-origin" }
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
let body = await originRequest.text();
|
|
46
|
-
|
|
47
|
-
res.send(`Body had a length of ${body.length}`);
|
|
48
|
-
});
|
|
49
|
-
```
|
package/docs/docs/routing.md
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
sidebar_position: 3
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Routing
|
|
6
|
-
|
|
7
|
-
**expressly** provides the `Router` object which stores configuration for your routing. Create a new router like this:
|
|
8
|
-
|
|
9
|
-
```javascript
|
|
10
|
-
import { Router } from "@fastly/expressly";
|
|
11
|
-
|
|
12
|
-
const router = new Router();
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
> 💡 `Router` supports additional [configuration](config.md).
|
|
16
|
-
|
|
17
|
-
## Creating a route
|
|
18
|
-
|
|
19
|
-
Then add a route by calling `router.HTTP_METHOD(PATH, handler)`. Adding a route for `GET` requests to `/hello-world` looks like this:
|
|
20
|
-
|
|
21
|
-
```javascript
|
|
22
|
-
router.get("/hello-world", (req, res) => {
|
|
23
|
-
res.send("Hello world!");
|
|
24
|
-
});
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
In the example above, if a request is made to the `/hello-world` path, your handler will run and return "Hello world!"
|
|
28
|
-
|
|
29
|
-
### What is a handler?
|
|
30
|
-
|
|
31
|
-
A handler is the function **expressly** will call to get a response to send back to the client. It is passed two arguments, the **req**uest and the **res**ponse.
|
|
32
|
-
|
|
33
|
-
```javascript
|
|
34
|
-
router.post("/", (req, res) => {
|
|
35
|
-
res.send("<h1>This is the response!</h1>");
|
|
36
|
-
});
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
> 🚨 **Unlike Express**, handlers accept only two arguments, `req` and `res`. **expressly** does away with the `next` function; uncaught errors are passed to [error middleware](./middleware/error-middleware.md).
|
|
40
|
-
|
|
41
|
-
## Listening for requests
|
|
42
|
-
|
|
43
|
-
After you have configured your routing logic, you **must** call `router.listen()` to bind the router to incoming requests.
|
|
44
|
-
|
|
45
|
-
### Hello world!
|
|
46
|
-
|
|
47
|
-
```javascript
|
|
48
|
-
import { Router } from "@fastly/expressly";
|
|
49
|
-
|
|
50
|
-
const router = new Router();
|
|
51
|
-
|
|
52
|
-
router.get("/", async (req, res) => {
|
|
53
|
-
return res.send("Hello world!");
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
router.listen();
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
## Route matching
|
|
60
|
-
|
|
61
|
-
### HTTP methods
|
|
62
|
-
|
|
63
|
-
With **expressly**, you can handle multiple HTTP methods per route:
|
|
64
|
-
|
|
65
|
-
```javascript
|
|
66
|
-
router.route(["GET", "POST"], "/my-page", async (req, res) => {
|
|
67
|
-
return res.send(`You made a ${req.method} request to my page!`);
|
|
68
|
-
});
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
If you want to handle _all_ HTTP methods on one route you can use `router.all`:
|
|
72
|
-
|
|
73
|
-
```javascript
|
|
74
|
-
router.all("/dead-end", (req, res) => {
|
|
75
|
-
res.end("Nothing to see here!");
|
|
76
|
-
});
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
### Route matching
|
|
80
|
-
|
|
81
|
-
**expressly** uses [path-to-regexp](https://www.npmjs.com/package/path-to-regexp) for pattern-matching routes:
|
|
82
|
-
|
|
83
|
-
- `router.HTTP_METHOD(PATTERN, handler)`
|
|
84
|
-
- `router.all(PATTERN, handler)`
|
|
85
|
-
- `router.route(HTTP_METHOD[], PATTERN, handler)`
|
|
86
|
-
|
|
87
|
-
#### Wildcards
|
|
88
|
-
|
|
89
|
-
You can use wildcard parameters `(.*)` in order to match multiple URLs with one route.
|
|
90
|
-
|
|
91
|
-
```javascript
|
|
92
|
-
router.get("/assets/(.*)", (req, res) => {
|
|
93
|
-
res.send(`You are visiting: ${req.path}`);
|
|
94
|
-
});
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
> 🚨 There is no wildcard asterisk (`*`) in **expressly** - use parameters instead (`(.*)` or `:splat*`).
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
```javascript
|
|
101
|
-
router.get("(.*)", (req, res) => {
|
|
102
|
-
res.send("Hello world!");
|
|
103
|
-
});
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
The above will match `GET` requests to any path.
|
|
107
|
-
|
|
108
|
-
#### Regular expressions
|
|
109
|
-
|
|
110
|
-
You can use regular expressions in order to match multiple URLs with one route.
|
|
111
|
-
|
|
112
|
-
```javascript
|
|
113
|
-
router.get(/.*fly$/, (req, res) => {
|
|
114
|
-
res.send(`You are visiting: ${req.path}`);
|
|
115
|
-
});
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
The route path above will match `butterfly` and `dragonfly`, but not `butterfly-net` or `flyer`.
|
|
119
|
-
|
|
120
|
-
#### Path parameters
|
|
121
|
-
|
|
122
|
-
You can specify parameters on your routes. The values of these parameters will be parsed and available inside your handler, in the `req.params` object.
|
|
123
|
-
|
|
124
|
-
```javascript
|
|
125
|
-
router.get("/profile/:userId", (req, res) => {
|
|
126
|
-
let userId = req.params.userId;
|
|
127
|
-
res.send(`This is the profile for user ${userId}`);
|
|
128
|
-
});
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
You can use regular expressions to constrain matching rules for parameters.
|
|
132
|
-
|
|
133
|
-
```javascript
|
|
134
|
-
router.get("/books/:id(\\d+)", (req, res) => {
|
|
135
|
-
let bookId = req.params.id;
|
|
136
|
-
res.send(`Book ID: ${bookId}`);
|
|
137
|
-
});
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
## Custom 404
|
|
141
|
-
|
|
142
|
-
For a custom 404 response, you can add a catch-all request handler after all other routes and middleware:
|
|
143
|
-
|
|
144
|
-
```javascript
|
|
145
|
-
router.all(("(.*)", (req, res) => {
|
|
146
|
-
res.status = 404;
|
|
147
|
-
return res.send("Page not found!");
|
|
148
|
-
});
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
Alternatively, you can achieve the same using [error middleware](middleware/error-middleware.md):
|
|
152
|
-
|
|
153
|
-
```javascript
|
|
154
|
-
router.use((err, req, res) => {
|
|
155
|
-
if(err.status === 404) {
|
|
156
|
-
res.send("Page not found!");
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
> 💡 **expressly** decorates errors with a `status` property as follows:
|
|
162
|
-
> * `404` – when no route was matched for the request path
|
|
163
|
-
> * `405` – when a route was found, but the request's HTTP method did not match.
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
// Note: type annotations allow type checking and IDEs autocompletion
|
|
3
|
-
|
|
4
|
-
const lightCodeTheme = require("prism-react-renderer/themes/github");
|
|
5
|
-
const darkCodeTheme = require("prism-react-renderer/themes/nightOwl");
|
|
6
|
-
|
|
7
|
-
/** @type {import('@docusaurus/types').Config} */
|
|
8
|
-
const config = {
|
|
9
|
-
title: "expressly",
|
|
10
|
-
tagline: "Express-style router for Fastly's Compute@Edge",
|
|
11
|
-
url: "https://expressly.edgecompute.app",
|
|
12
|
-
baseUrl: "/",
|
|
13
|
-
onBrokenLinks: "throw",
|
|
14
|
-
onBrokenMarkdownLinks: "warn",
|
|
15
|
-
favicon: "img/favicon.ico",
|
|
16
|
-
organizationName: "fastly",
|
|
17
|
-
projectName: "expressly",
|
|
18
|
-
|
|
19
|
-
presets: [
|
|
20
|
-
[
|
|
21
|
-
"@docusaurus/preset-classic",
|
|
22
|
-
/** @type {import('@docusaurus/preset-classic').Options} */
|
|
23
|
-
({
|
|
24
|
-
docs: {
|
|
25
|
-
sidebarPath: require.resolve("./sidebars.js"),
|
|
26
|
-
sidebarCollapsed: false,
|
|
27
|
-
editUrl: 'https://github.com/fastly/expressly/edit/main/docs/',
|
|
28
|
-
},
|
|
29
|
-
theme: {
|
|
30
|
-
customCss: require.resolve("./src/css/custom.css"),
|
|
31
|
-
},
|
|
32
|
-
}),
|
|
33
|
-
],
|
|
34
|
-
],
|
|
35
|
-
|
|
36
|
-
themeConfig:
|
|
37
|
-
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
|
|
38
|
-
({
|
|
39
|
-
colorMode: {
|
|
40
|
-
respectPrefersColorScheme: true,
|
|
41
|
-
},
|
|
42
|
-
navbar: {
|
|
43
|
-
title: "expressly",
|
|
44
|
-
logo: {
|
|
45
|
-
alt: "expressly Logo",
|
|
46
|
-
src: 'img/logo.png',
|
|
47
|
-
},
|
|
48
|
-
items: [
|
|
49
|
-
{
|
|
50
|
-
type: "doc",
|
|
51
|
-
docId: "intro",
|
|
52
|
-
position: "left",
|
|
53
|
-
label: "Docs",
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
href: "https://developer.fastly.com/solutions/examples/javascript/",
|
|
57
|
-
label: "Examples",
|
|
58
|
-
position: "left",
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
href: "https://github.com/fastly/expressly",
|
|
62
|
-
label: "GitHub",
|
|
63
|
-
position: "right",
|
|
64
|
-
},
|
|
65
|
-
],
|
|
66
|
-
},
|
|
67
|
-
footer: {
|
|
68
|
-
style: "dark",
|
|
69
|
-
links: [
|
|
70
|
-
{
|
|
71
|
-
title: "expressly",
|
|
72
|
-
items: [
|
|
73
|
-
{
|
|
74
|
-
label: "Documentation",
|
|
75
|
-
to: "/docs/intro",
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
label: "Examples",
|
|
79
|
-
href: "https://developer.fastly.com/solutions/examples/javascript/",
|
|
80
|
-
},
|
|
81
|
-
],
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
title: "Compute@Edge",
|
|
85
|
-
items: [
|
|
86
|
-
{
|
|
87
|
-
label: "Learn about Compute@Edge",
|
|
88
|
-
href: "https://developer.fastly.com/learning/compute/",
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
label: "Create your first JavaScript app",
|
|
92
|
-
href: "https://developer.fastly.com/learning/compute/javascript/",
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
label: "Fastly Developer Hub",
|
|
96
|
-
href: "https://developer.fastly.com/",
|
|
97
|
-
},
|
|
98
|
-
],
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
title: "Fastly",
|
|
102
|
-
items: [
|
|
103
|
-
{
|
|
104
|
-
label: "Twitter",
|
|
105
|
-
href: "https://twitter.com/fastly",
|
|
106
|
-
},
|
|
107
|
-
],
|
|
108
|
-
},
|
|
109
|
-
],
|
|
110
|
-
copyright: `Copyright © ${new Date().getFullYear()} Fastly Inc. All rights reserved.`,
|
|
111
|
-
},
|
|
112
|
-
prism: {
|
|
113
|
-
theme: lightCodeTheme,
|
|
114
|
-
darkTheme: darkCodeTheme,
|
|
115
|
-
},
|
|
116
|
-
}),
|
|
117
|
-
};
|
|
118
|
-
|
|
119
|
-
module.exports = config;
|
package/docs/package.json
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "expressly-docs",
|
|
3
|
-
"version": "0.0.0",
|
|
4
|
-
"description": "Documentation for expressly - an Express-style router for Fastly's Compute@Edge",
|
|
5
|
-
"private": true,
|
|
6
|
-
"engines": {
|
|
7
|
-
"node": "^16.15.0"
|
|
8
|
-
},
|
|
9
|
-
"scripts": {
|
|
10
|
-
"docusaurus": "docusaurus",
|
|
11
|
-
"start": "docusaurus start",
|
|
12
|
-
"build": "docusaurus build",
|
|
13
|
-
"swizzle": "docusaurus swizzle",
|
|
14
|
-
"deploy": "docusaurus deploy",
|
|
15
|
-
"clear": "docusaurus clear",
|
|
16
|
-
"serve": "docusaurus serve",
|
|
17
|
-
"write-translations": "docusaurus write-translations",
|
|
18
|
-
"write-heading-ids": "docusaurus write-heading-ids",
|
|
19
|
-
"typecheck": "tsc"
|
|
20
|
-
},
|
|
21
|
-
"dependencies": {
|
|
22
|
-
"@docusaurus/core": "2.0.0-beta.21",
|
|
23
|
-
"@docusaurus/preset-classic": "2.0.0-beta.21",
|
|
24
|
-
"@mdx-js/react": "^1.6.22",
|
|
25
|
-
"clsx": "^1.1.1",
|
|
26
|
-
"prism-react-renderer": "^1.3.3",
|
|
27
|
-
"react": "^17.0.2",
|
|
28
|
-
"react-dom": "^17.0.2"
|
|
29
|
-
},
|
|
30
|
-
"devDependencies": {
|
|
31
|
-
"@docusaurus/module-type-aliases": "2.0.0-beta.21",
|
|
32
|
-
"@tsconfig/docusaurus": "^1.0.5",
|
|
33
|
-
"@types/react": "^17.0.2",
|
|
34
|
-
"typescript": "^4.7.3"
|
|
35
|
-
},
|
|
36
|
-
"browserslist": {
|
|
37
|
-
"production": [
|
|
38
|
-
">0.5%",
|
|
39
|
-
"not dead",
|
|
40
|
-
"not op_mini all"
|
|
41
|
-
],
|
|
42
|
-
"development": [
|
|
43
|
-
"last 1 chrome version",
|
|
44
|
-
"last 1 firefox version",
|
|
45
|
-
"last 1 safari version"
|
|
46
|
-
]
|
|
47
|
-
}
|
|
48
|
-
}
|
package/docs/sidebars.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Creating a sidebar enables you to:
|
|
3
|
-
- create an ordered group of docs
|
|
4
|
-
- render a sidebar for each doc of that group
|
|
5
|
-
- provide next/previous navigation
|
|
6
|
-
|
|
7
|
-
The sidebars can be generated from the filesystem, or explicitly defined here.
|
|
8
|
-
|
|
9
|
-
Create as many sidebars as you want.
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
// @ts-check
|
|
13
|
-
|
|
14
|
-
/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
|
|
15
|
-
const sidebars = {
|
|
16
|
-
// By default, Docusaurus generates a sidebar from the docs folder structure
|
|
17
|
-
main: [{ type: "autogenerated", dirName: "." }],
|
|
18
|
-
|
|
19
|
-
// But you can create a sidebar manually
|
|
20
|
-
/*
|
|
21
|
-
tutorialSidebar: [
|
|
22
|
-
{
|
|
23
|
-
type: 'category',
|
|
24
|
-
label: 'Tutorial',
|
|
25
|
-
items: ['hello'],
|
|
26
|
-
},
|
|
27
|
-
],
|
|
28
|
-
*/
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
module.exports = sidebars;
|