docs: changes for next release (#11708)
* docs: changes for next release * small fixes * fix lint error * small fix
This commit is contained in:
@@ -18,11 +18,20 @@ As Medusa's server is based on Express, you can use any [Express middleware](htt
|
||||
|
||||
</Note>
|
||||
|
||||
### Middleware Types
|
||||
|
||||
There are two types of middlewares:
|
||||
|
||||
1. Global Middleware: A middleware that applies to all routes matching a specified pattern.
|
||||
2. Route Middleware: A middleware that applies to routes matching a specified pattern and HTTP method(s).
|
||||
|
||||
These middlewares generally have the same definition and usage, but they differ in the routes they apply to. You'll learn how to create both types in the following sections.
|
||||
|
||||
---
|
||||
|
||||
## How to Create a Middleware?
|
||||
## How to Create a Global Middleware?
|
||||
|
||||
Middlewares are defined in the special file `src/api/middlewares.ts`. Use the `defineMiddlewares` function from the Medusa Framework to define the middlewares, and export its value.
|
||||
Middlewares of all types are defined in the special file `src/api/middlewares.ts`. Use the `defineMiddlewares` function from the Medusa Framework to define the middlewares, and export its value.
|
||||
|
||||
For example:
|
||||
|
||||
@@ -57,13 +66,11 @@ export default defineMiddlewares({
|
||||
The `defineMiddlewares` function accepts a middleware configurations object that has the property `routes`. `routes`'s value is an array of middleware route objects, each having the following properties:
|
||||
|
||||
- `matcher`: a string or regular expression indicating the API route path to apply the middleware on. The regular expression must be compatible with [path-to-regexp](https://github.com/pillarjs/path-to-regexp).
|
||||
- `middlewares`: An array of middleware functions.
|
||||
- `middlewares`: An array of global and route middleware functions.
|
||||
|
||||
In the example above, you define a middleware that logs the message `Received a request!` whenever a request is sent to an API route path starting with `/custom`.
|
||||
In the example above, you define a global middleware that logs the message `Received a request!` whenever a request is sent to an API route path starting with `/custom`.
|
||||
|
||||
---
|
||||
|
||||
## Test the Middleware
|
||||
### Test the Global Middleware
|
||||
|
||||
To test the middleware:
|
||||
|
||||
@@ -82,6 +89,64 @@ Received a request!
|
||||
|
||||
---
|
||||
|
||||
## How to Create a Route Middleware?
|
||||
|
||||
In the previous section, you learned how to create a global middleware. You define the route middleware in the same way in `src/api/middlewares.ts`, but you specify an additional property `method` in the middleware route object. Its value is one or more HTTP methods to apply the middleware to.
|
||||
|
||||
For example:
|
||||
|
||||
export const highlights = [["12", "method", "Apply the middleware only on `POST` requests"]]
|
||||
|
||||
```ts title="src/api/middlewares.ts" highlights={highlights} collapsibleLines="1-7" expandButtonLabel="Show Imports"
|
||||
import {
|
||||
MedusaNextFunction,
|
||||
MedusaRequest,
|
||||
MedusaResponse,
|
||||
defineMiddlewares,
|
||||
} from "@medusajs/framework/http"
|
||||
|
||||
export default defineMiddlewares({
|
||||
routes: [
|
||||
{
|
||||
matcher: "/custom*",
|
||||
method: ["POST", "PUT"],
|
||||
middlewares: [
|
||||
(
|
||||
req: MedusaRequest,
|
||||
res: MedusaResponse,
|
||||
next: MedusaNextFunction
|
||||
) => {
|
||||
console.log("Received a request!")
|
||||
|
||||
next()
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
This example applies the middleware only when a `POST` or `PUT` request is sent to an API route path starting with `/custom`, changing the middleware from a global middleware to a route middleware.
|
||||
|
||||
### Test the Route Middleware
|
||||
|
||||
To test the middleware:
|
||||
|
||||
1. Start the application:
|
||||
|
||||
```bash npm2yarn
|
||||
npm run dev
|
||||
```
|
||||
|
||||
2. Send a `POST` request to any API route starting with `/custom`.
|
||||
3. See the following message in the terminal:
|
||||
|
||||
```bash
|
||||
Received a request!
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## When to Use Middlewares
|
||||
|
||||
<Note type="success" title="Use middlewares when">
|
||||
@@ -141,48 +206,13 @@ This applies a middleware to the routes defined in the file `src/api/custom/[id]
|
||||
|
||||
---
|
||||
|
||||
## Restrict HTTP Methods
|
||||
|
||||
Restrict which HTTP methods the middleware is applied to using the `method` property of the middleware route object.
|
||||
|
||||
For example:
|
||||
|
||||
export const highlights = [["12", "method", "Apply the middleware only on `POST` requests"]]
|
||||
|
||||
```ts title="src/api/middlewares.ts" highlights={highlights} collapsibleLines="1-7" expandButtonLabel="Show Imports"
|
||||
import {
|
||||
MedusaNextFunction,
|
||||
MedusaRequest,
|
||||
MedusaResponse,
|
||||
defineMiddlewares,
|
||||
} from "@medusajs/framework/http"
|
||||
|
||||
export default defineMiddlewares({
|
||||
routes: [
|
||||
{
|
||||
matcher: "/custom*",
|
||||
method: ["POST", "PUT"],
|
||||
middlewares: [
|
||||
// ...
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
`method`'s value is one or more HTTP methods to apply the middleware to.
|
||||
|
||||
This example applies the middleware only when a `POST` or `PUT` request is sent to an API route path starting with `/custom`.
|
||||
|
||||
---
|
||||
|
||||
## Request URLs with Trailing Backslashes
|
||||
|
||||
A middleware whose `matcher` pattern doesn't end with a backslash won't be applied for requests to URLs with a trailing backslash.
|
||||
|
||||
For example, consider you have the following middleware:
|
||||
|
||||
```ts collapsibleLines="1-7" expandMoreLabel="Show Imports"
|
||||
```ts title="src/api/middlewares.ts" collapsibleLines="1-7" expandMoreLabel="Show Imports"
|
||||
import {
|
||||
MedusaNextFunction,
|
||||
MedusaRequest,
|
||||
@@ -218,8 +248,123 @@ In general, avoid adding trailing backslashes when sending requests to API route
|
||||
|
||||
---
|
||||
|
||||
## Middlewares Precedence in Registration
|
||||
## Middlewares and Route Ordering
|
||||
|
||||
The Medusa application registers your middlewares first, then registers middlewares defined in Medusa's core.
|
||||
<Note>
|
||||
|
||||
So, if you add a middleware for a route defined in the core, it might get overridden by the core middleware. For example, if you add a middleware to change authentication of admin routes, the authentication middleware defined in the core will still run, leading to your middleware not being effective.
|
||||
The ordering explained in this section was added in [Medusa v2.6](https://github.com/medusajs/medusa/releases/tag/v2.6)
|
||||
|
||||
</Note>
|
||||
|
||||
The Medusa application registers middlewares and API route handlers in the following order:
|
||||
|
||||
1. Global middlewares in the following order:
|
||||
1. Global middleware defined in the Medusa's core.
|
||||
2. Global middleware defined in the plugins (in the order the plugins are registered in).
|
||||
3. Global middleware you define in the application.
|
||||
2. Route middlewares in the following order:
|
||||
1. Route middleware defined in the Medusa's core.
|
||||
2. Route middleware defined in the plugins (in the order the plugins are registered in).
|
||||
3. Route middleware you define in the application.
|
||||
3. API routes in the following order:
|
||||
1. API routes defined in the Medusa's core.
|
||||
2. API routes defined in the plugins (in the order the plugins are registered in).
|
||||
3. API routes you define in the application.
|
||||
|
||||
### Middlewares Sorting
|
||||
|
||||
On top of the previous ordering, Medusa sorts global and route middlewares based on their matcher pattern in the following order:
|
||||
|
||||
1. Wildcard matchers. For example, `/custom*`.
|
||||
2. Regex matchers. For example, `/custom/(products|collections)`.
|
||||
3. Static matchers without parameters. For example, `/custom`.
|
||||
4. Static matchers with parameters. For example, `/custom/:id`.
|
||||
|
||||
For example, if you have the following middlewares:
|
||||
|
||||
```ts title="src/api/middlewares.ts"
|
||||
export default defineMiddlewares({
|
||||
routes: [
|
||||
{
|
||||
matcher: "/custom/:id",
|
||||
middlewares: [/* ... */],
|
||||
},
|
||||
{
|
||||
matcher: "/custom",
|
||||
middlewares: [/* ... */],
|
||||
},
|
||||
{
|
||||
matcher: "/custom*",
|
||||
method: ["GET"],
|
||||
middlewares: [/* ... */],
|
||||
},
|
||||
{
|
||||
matcher: "/custom/:id",
|
||||
method: ["GET"],
|
||||
middlewares: [/* ... */],
|
||||
},
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
The global middlewares are sorted into the following order before they're registered:
|
||||
|
||||
1. Global middleware `/custom`.
|
||||
2. Global middleware `/custom/:id`.
|
||||
|
||||
And the route middlewares are sorted into the following order before they're registered:
|
||||
|
||||
1. Route middleware `/custom*`.
|
||||
2. Route middleware `/custom/:id`.
|
||||
|
||||
Then, the middlwares are registered in the order mentioned earlier, with global middlewares first, then the route middlewares.
|
||||
|
||||
### Middlewares and Route Execution Order
|
||||
|
||||
When a request is sent to an API route, the global middlewares are executed first, then the route middlewares, and finally the route handler.
|
||||
|
||||
For example, consider you have the following middlewares:
|
||||
|
||||
```ts title="src/api/middlewares.ts"
|
||||
export default defineMiddlewares({
|
||||
routes: [
|
||||
{
|
||||
matcher: "/custom",
|
||||
middlewares: [
|
||||
(req, res, next) => {
|
||||
console.log("Global middleware")
|
||||
next()
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
matcher: "/custom",
|
||||
method: ["GET"],
|
||||
middlewares: [
|
||||
(req, res, next) => {
|
||||
console.log("Route middleware")
|
||||
next()
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
```
|
||||
|
||||
When you send a request to `/custom` route, the following messages are logged in the terminal:
|
||||
|
||||
```bash
|
||||
Global middleware
|
||||
Route middleware
|
||||
Hello from custom! # message logged from API route handler
|
||||
```
|
||||
|
||||
The global middleware runs first, then the route middleware, and finally the route handler, assuming that it logs the message `Hello from custom!`.
|
||||
|
||||
---
|
||||
|
||||
## Overriding Middlewares
|
||||
|
||||
A middleware can not override an existing middleware. Instead, middlewares are added to the end of the middleware stack.
|
||||
|
||||
For example, if you define a custom validation middleware, such as `validateAndTransformBody`, on an existing route, then both the original and the custom validation middleware will run.
|
||||
|
||||
@@ -53,7 +53,7 @@ export const generatedEditDates = {
|
||||
"app/learn/fundamentals/admin/tips/page.mdx": "2025-02-24T09:52:06.901Z",
|
||||
"app/learn/fundamentals/api-routes/cors/page.mdx": "2024-12-09T13:04:04.357Z",
|
||||
"app/learn/fundamentals/admin/ui-routes/page.mdx": "2025-02-24T09:35:11.752Z",
|
||||
"app/learn/fundamentals/api-routes/middlewares/page.mdx": "2025-02-12T17:05:20.708Z",
|
||||
"app/learn/fundamentals/api-routes/middlewares/page.mdx": "2025-03-04T10:16:15.029Z",
|
||||
"app/learn/fundamentals/modules/isolation/page.mdx": "2024-12-09T11:02:38.087Z",
|
||||
"app/learn/fundamentals/data-models/configure-properties/page.mdx": "2024-10-21T13:30:21.368Z",
|
||||
"app/learn/fundamentals/data-models/index/page.mdx": "2024-10-21T13:30:21.368Z",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -339,8 +339,9 @@ If the authentication is successful, the request returns a `201` response code.
|
||||
The Medusa application defines an API route at `/auth/{actor_type}/{auth_provider}/update` that accepts a token and, if valid, updates the user's password.
|
||||
|
||||
```bash
|
||||
curl -X POST http://localhost:9000/auth/{actor_type}/{providers}/update?token=123
|
||||
curl -X POST http://localhost:9000/auth/{actor_type}/{providers}/update
|
||||
-H 'Content-Type: application/json' \
|
||||
-H 'Authorization: Bearer {token}' \
|
||||
--data-raw '{
|
||||
"email": "Whitney_Schultz@gmail.com",
|
||||
"password": "supersecret"
|
||||
@@ -360,9 +361,15 @@ Its path parameters are:
|
||||
- `{actor_type}`: the actor type of the user you're authenticating. For example, `customer`.
|
||||
- `{provider}`: the auth provider to handle the authentication. For example, `emailpass`.
|
||||
|
||||
#### Query Parameters
|
||||
#### Pass Token in Authorization Header
|
||||
|
||||
The route accepts a `token` query parameter, which is the token generated using the [Generate Reset Password Token route](#generate-reset-password-token-route).
|
||||
<Note>
|
||||
|
||||
Before [Medusa v2.6](https://github.com/medusajs/medusa/releases/tag/v2.6), you passed the token as a query parameter. Now, you must pass it in the `Authorization` header.
|
||||
|
||||
</Note>
|
||||
|
||||
In the request's authorization header, you must pass the token generated using the [Generate Reset Password Token route](#generate-reset-password-token-route). You pass it as a bearer token.
|
||||
|
||||
### Request Body Parameters
|
||||
|
||||
|
||||
@@ -167,8 +167,8 @@ export const resetPasswordFetchHighlights = [
|
||||
["3", "email", "Receive the email from a query parameter."],
|
||||
["9", "password", "Assuming the password is retrieved from an input field."],
|
||||
["14", "fetch", "Send a request to update the customer's password."],
|
||||
["14", "token", "Pass the token as a query parameter."],
|
||||
["20", "body", "Pass the email and password in the request body."]
|
||||
["19", "token", "Pass the token in the Authorization header."],
|
||||
["21", "body", "Pass the email and password in the request body."]
|
||||
]
|
||||
|
||||
```ts highlights={resetPasswordFetchHighlights}
|
||||
@@ -185,11 +185,12 @@ export const resetPasswordFetchHighlights = [
|
||||
return
|
||||
}
|
||||
|
||||
fetch(`http://localhost:9000/auth/customer/emailpass/update?token=${token}`, {
|
||||
fetch(`http://localhost:9000/auth/customer/emailpass/update`, {
|
||||
credentials: "include",
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": `Bearer ${token}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email,
|
||||
@@ -210,8 +211,8 @@ export const resetPasswordHighlights = [
|
||||
["18", "token", "Receive the token from a query parameter."],
|
||||
["21", "email", "Receive the email from a query parameter."],
|
||||
["35", "fetch", "Send a request to update the customer's password."],
|
||||
["35", "token", "Pass the token as a query parameter."],
|
||||
["41", "body", "Pass the email and password in the request body."]
|
||||
["40", "token", "Pass the token in the Authorization header."],
|
||||
["42", "body", "Pass the email and password in the request body."]
|
||||
]
|
||||
|
||||
```tsx highlights={resetPasswordHighlights}
|
||||
@@ -249,11 +250,12 @@ export const resetPasswordHighlights = [
|
||||
}
|
||||
setLoading(true)
|
||||
|
||||
fetch(`http://localhost:9000/auth/customer/emailpass/update?token=${token}`, {
|
||||
fetch(`http://localhost:9000/auth/customer/emailpass/update`, {
|
||||
credentials: "include",
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": `Bearer ${token}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
email,
|
||||
@@ -289,4 +291,10 @@ export const resetPasswordHighlights = [
|
||||
|
||||
In this example, you receive the `token` and `email` from the page's query parameters.
|
||||
|
||||
Then, when the form that has the password field is submitted, you send a request to the `http://localhost:9000/auth/customer/emailpass/update` API route. You pass it the token as a query parameter, and the email and password in the request body.
|
||||
Then, when the form that has the password field is submitted, you send a request to the `http://localhost:9000/auth/customer/emailpass/update` API route. You pass it the token as in the Authorization header as a bearer token, and the email and password in the request body.
|
||||
|
||||
<Note>
|
||||
|
||||
Before [Medusa v2.6](https://github.com/medusajs/medusa/releases/tag/v2.6), you passed the token as a query parameter. Now, you must pass it in the `Authorization` header.
|
||||
|
||||
</Note>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export const generatedEditDates = {
|
||||
"app/commerce-modules/auth/auth-providers/emailpass/page.mdx": "2025-01-13T11:31:35.361Z",
|
||||
"app/commerce-modules/auth/auth-providers/page.mdx": "2024-10-08T07:27:21.859Z",
|
||||
"app/commerce-modules/auth/authentication-route/page.mdx": "2025-01-13T11:31:17.572Z",
|
||||
"app/commerce-modules/auth/authentication-route/page.mdx": "2025-03-04T09:13:45.919Z",
|
||||
"app/commerce-modules/auth/examples/page.mdx": "2024-10-15T15:02:13.794Z",
|
||||
"app/commerce-modules/auth/module-options/page.mdx": "2025-01-07T12:47:35.073Z",
|
||||
"app/commerce-modules/auth/page.mdx": "2025-01-09T13:41:05.476Z",
|
||||
@@ -2108,7 +2108,7 @@ export const generatedEditDates = {
|
||||
"app/admin-components/layouts/two-column/page.mdx": "2024-10-07T11:16:10.092Z",
|
||||
"app/admin-components/components/forms/page.mdx": "2024-10-09T12:48:04.229Z",
|
||||
"app/commerce-modules/auth/reset-password/page.mdx": "2025-02-26T11:18:00.391Z",
|
||||
"app/storefront-development/customers/reset-password/page.mdx": "2024-12-19T16:32:00.724Z",
|
||||
"app/storefront-development/customers/reset-password/page.mdx": "2025-03-04T09:15:25.662Z",
|
||||
"app/commerce-modules/api-key/links-to-other-modules/page.mdx": "2025-01-06T11:19:22.450Z",
|
||||
"app/commerce-modules/cart/extend/page.mdx": "2024-12-25T12:48:59.149Z",
|
||||
"app/commerce-modules/cart/links-to-other-modules/page.mdx": "2025-01-06T11:19:35.593Z",
|
||||
|
||||
Reference in New Issue
Block a user