Skip to content

Commit

Permalink
Fix several issues in the middleware documentation (#3518)
Browse files Browse the repository at this point in the history
Summary of fixes:

- Fixed a few cases where the `title` for code blocks was incorrectly spelled `tilte` instead
- Fixed `MiddlewareResponseHandler` being incorrectly referred to as `MiddlewareRequestHandler` instead
- Fixed a line comment that should've been a block comment and was cutting off the end of the line
- Replaced `html.replace` with `html.replaceAll` in the "redacting sensitive information" example
- Added a missing `title`
- Removed a draft version of the example for chaining middleware
- Fixed inconsistent indentation and formatting
- Added missing semicolons
- Removed extraneous spaces
- A few grammar fixes

Co-authored-by: Yan Thomas <[email protected]>
  • Loading branch information
wackbyte and yanthomasdev authored Jun 30, 2023
1 parent adbfdc9 commit 22c58ac
Showing 1 changed file with 49 additions and 63 deletions.
112 changes: 49 additions & 63 deletions src/content/docs/en/guides/middleware.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Middleware
description: Learn how to use middleware in Astro.
i18nReady: true
---
import PackageManagerTabs from '~/components/tabs/PackageManagerTabs.astro'
import PackageManagerTabs from '~/components/tabs/PackageManagerTabs.astro';

**Middleware** allows you to intercept requests and responses and inject behaviors dynamically every time a page or endpoint is about to be rendered.

Expand All @@ -20,51 +20,47 @@ Middleware is available in both SSG and SSR Astro projects.
```js title="src/middleware.js"
export function onRequest ({ locals, request }, next) {
// intercept response data from a request
// optionally, transform the response by modifying `locals`
locals.title = "New title"
// optionally, transform the response by modifying `locals`
locals.title = "New title";

// return a Response or the result of calling `next()`
return next()
// return a Response or the result of calling `next()`
return next();
};
```

3. Inside any `.astro` file, access response data using `Astro.locals`
3. Inside any `.astro` file, access response data using `Astro.locals`.

```astro title="src/components/Component.astro"
---
const data = Astro.locals;
---
<h1>{data.title}</h1>
<p>This {data.property} is from middleware.</p>
```

### Middleware types

You can import and use the utility function `defineMiddleware()` to take advantage of type safety:


```ts tilte="src/middleware.ts"
```ts title="src/middleware.ts"
import { defineMiddleware } from "astro/middleware";

// `context` and `next` are automatically typed
export const onRequest = defineMiddleware((context, next) => {

})
});
```

Instead, if you're using JsDoc to take advantage of type safety, you can use `MiddlewareRequestHandler`:

```js tilte="src/middleware.js"
Instead, if you're using JSDoc to take advantage of type safety, you can use `MiddlewareResponseHandler`:

```js title="src/middleware.js"
/**
* @type import("astro").MiddlewareResponseHandler
* @type {import("astro").MiddlewareResponseHandler}
*/
// `context` and `next` are automatically typed
export const onRequest = (context, next) => {

}

};
```

To type the information inside `Astro.locals`, which gives you autocompletion inside `.astro` files and middleware code, declare a global namespace in the `env.d.ts` file:
Expand All @@ -76,33 +72,33 @@ declare namespace App {
user: {
name: string
},
welcomeTitle: () => String,
welcomeTitle: () => string,
orders: Map<string, object>
}
}
```

Then, inside middleware file, we can take advantage of autocompletion and type safety.

You can store any type of data inside `Astro.locals`: strings, numbers, and even complex data types such as functions, and maps.
Then, inside the middleware file, we can take advantage of autocompletion and type safety.

You can store any type of data inside `Astro.locals`: strings, numbers, and even complex data types such as functions and maps.

```js title="src/middleware.js"
export function onRequest ({ locals, request }, next) {
```js title="src/middleware.js"
export function onRequest ({ locals, request }, next) {
// intercept response data from a request
// optionally, transform the response by modifying `locals`
locals.user.name = "John Wick"
locals.user.name = "John Wick";
locals.welcomeTitle = () => {
return "Welcome back " + locals.user.name
}
return "Welcome back " + locals.user.name;
};

// return a Response or the result of calling `next()`
return next()
};
// return a Response or the result of calling `next()`
return next();
};
```

Then you can use this information inside any `.astro` file.

```astro title="src/pages/Orders.astro"
```astro title="src/pages/orders.astro"
---
const title = Astro.locals.welcomeTitle();
const orders = Array.from(Astro.locals.orders.entries());
Expand All @@ -111,64 +107,54 @@ const orders = Array.from(Astro.locals.orders.entries());
<p>This {data.property} is from middleware.</p>
<ul>
{orders.map(order => {
return <li>{// do something with each order}</li>
return <li>{/* do something with each order */}</li>;
})}
</ul>
```


### Example: redacting sensitive information

The example below uses middleware to replace "PRIVATE INFO" with the word "REDACTED" to allow you to render modified HTML on your page:

```js
```js title="src/middleware.js"
export const onRequest = async (context, next) => {
const response = await next();
const html = await response.text();
const redactedHtml = html.replace("PRIVATE INFO", "REDACTED");

return new Response(redactedHtml, {
status: 200,
headers: response.headers
});
}
const response = await next();
const html = await response.text();
const redactedHtml = html.replaceAll("PRIVATE INFO", "REDACTED");
return new Response(redactedHtml, {
status: 200,
headers: response.headers
});
};
```

### Chaining middleware

Multiple middlewares can be joined, in a specified order, using [`sequence()`](#sequence):
Multiple middlewares can be joined in a specified order using [`sequence()`](#sequence):

```js title="src/middleware.js"
import {sequence} from "astro/middleware";

function validation() {}
function auth() {}

export const onRequest = sequence(validation, auth);
```

```js
import {sequence} from "astro/middleware";
import { sequence } from "astro/middleware";

async function validation(_, next) {
console.log("validation request");
const response = await next();
console.log("validation response");
return response;
}
async function auth(_, next) {
console.log("auth request");
const response = await next();
console.log("auth response");
return response;

async function auth(_, next) {
console.log("auth request");
const response = await next();
console.log("auth response");
return response;
}
async function greeting(_, next) {
console.log("greeting request");
const response = await next();
console.log("greeting response");
return response;

async function greeting(_, next) {
console.log("greeting request");
const response = await next();
console.log("greeting response");
return response;
}

export const onRequest = sequence(validation, auth, greeting);
Expand All @@ -185,7 +171,7 @@ auth response
validation response
```

## API reference
## API Reference

### `onRequest()`

Expand Down

0 comments on commit 22c58ac

Please sign in to comment.