docs: document configuring request body parsing (#11463)

* docs: document configuring request body parsing

* chore: run yarn prep automatically

* chore: run yarn prep automatically

* chore: run yarn prep automatically

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Shahed Nasser
2025-02-14 15:58:34 +02:00
committed by GitHub
parent ceb99d073a
commit 9f39cd19f8
7 changed files with 13047 additions and 12663 deletions

View File

@@ -603,7 +603,7 @@ medusaIntegrationTestRunner({
expect.objectContaining({
id: expect.any(String),
url: expect.any(String),
})
}),
])
)
})

View File

@@ -105,7 +105,13 @@ Learn more in [this documentation](../validation/page.mdx#how-to-validate-reques
## Request Body Parameters
The Medusa application parses the body of any request having its `Content-Type` header set to `application/json`. The request body parameters are set in the `MedusaRequest`'s `body` property.
The Medusa application parses the body of any request having a JSON, URL-encoded, or text request content types. The request body parameters are set in the `MedusaRequest`'s `body` property.
<Note title="Tip">
Learn more about configuring body parsing in [this guide](../parse-body/page.mdx).
</Note>
For example:

View File

@@ -0,0 +1,190 @@
export const metadata = {
title: `${pageNumber} Configure Request Body Parser`,
}
# {metadata.title}
In this chapter, you'll learn how to configure the request body parser for your API routes.
## Default Body Parser Configuration
The Medusa application configures the body parser by default to parse JSON, URL-encoded, and text request content types. You can parse other data types by adding the relevant [Express middleware](https://expressjs.com/en/guide/using-middleware.html) or preserve the raw body data by configuring the body parser, which is useful for webhook requests.
This chapter shares some examples of configuring the body parser for different data types or use cases.
---
## Preserve Raw Body Data for Webhooks
If your API route receives webhook requests, you might want to preserve the raw body data. To do this, you can configure the body parser to parse the raw body data and store it in the `req.rawBody` property.
To do that, create the file `src/api/middlewares.ts` with the following content:
export const preserveHighlights = [
["7", "preserveRawBody", "Enable preserving the raw body data."],
]
```ts title="src/api/middlewares.ts" highlights={preserveHighlights}
import { defineMiddlewares } from "@medusajs/framework/http"
export default defineMiddlewares({
routes: [
{
method: ["POST"],
bodyParser: { preserveRawBody: true },
matcher: "/custom",
},
],
})
```
The middleware route object passed to `routes` accepts a `bodyParser` property whose value is an object of configuration for the default body parser. By enabling the `preserveRawBody` property, the raw body data is preserved and stored in the `req.rawBody` property.
<Note title="Tip">
Learn more about [middlewares](../middlewares/page.mdx).
</Note>
You can then access the raw body data in your API route handler:
```ts title="src/api/custom/route.ts"
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
export async function POST(
req: MedusaRequest,
res: MedusaResponse
) {
console.log(req.rawBody)
// TODO use raw body
}
```
---
## Configure Request Body Size Limit
By default, the body parser limits the request body size to `100kb`. If a request body exceeds that size, the Medusa application throws an error.
You can configure the body parser to accept larger request bodies by setting the `sizeLimit` property of the `bodyParser` object in a middleware route object. For example:
export const sizeLimitHighlights = [
["7", "sizeLimit", "Set the request body size limit."],
]
```ts title="src/api/middlewares.ts" highlights={sizeLimitHighlights}
import { defineMiddlewares } from "@medusajs/framework/http"
export default defineMiddlewares({
routes: [
{
method: ["POST"],
bodyParser: { sizeLimit: "2mb" },
matcher: "/custom",
},
],
})
```
The `sizeLimit` property accepts one of the following types of values:
- A string representing the size limit in bytes (For example, `100kb`, `2mb`, `5gb`). It is passed to the [bytes](https://www.npmjs.com/package/bytes) library to parse the size.
- A number representing the size limit in bytes. For example, `1024` for 1kb.
---
## Configure File Uploads
To accept file uploads in your API routes, you can configure the [Express Multer middleware](https://expressjs.com/en/resources/middleware/multer.html) on your route.
The `multer` package is available through the `@medusajs/medusa` package, so you don't need to install it. However, for better typing support, install the `@types/multer` package as a development dependency:
```bash npm2yarn
npm install --save-dev @types/multer
```
Then, to configure file upload for your route, create the file `src/api/middlewares.ts` with the following content:
export const uploadHighlights = [
["4", "upload", "Configure the upload middleware."],
["13", "upload", "Add the upload middleware to the route."],
]
```ts title="src/api/middlewares.ts" highlights={uploadHighlights}
import { defineMiddlewares } from "@medusajs/framework/http"
import multer from "multer"
const upload = multer({ storage: multer.memoryStorage() })
export default defineMiddlewares({
routes: [
{
method: ["POST"],
matcher: "/custom",
middlewares: [
// @ts-ignore
upload.array("files"),
],
},
],
})
```
In the example above, you configure the `multer` middleware to store the uploaded files in memory. Then, you apply the `upload.array("files")` middleware to the route to accept file uploads. By using the `array` method, you accept multiple file uploads with the same `files` field name.
You can then access the uploaded files in your API route handler:
```ts title="src/api/custom/route.ts"
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
export async function POST(
req: MedusaRequest,
res: MedusaResponse
) {
const files = req.files as Express.Multer.File[]
// TODO handle files
}
```
The uploaded files are stored in the `req.files` property as an array of Multer file objects that have properties like `filename` and `mimetype`.
### Uploading Files using File Module Provider
The recommended way to upload the files to storage using the configured [File Module Provider](!resources!/architectural-modules/file) is to use the [uploadFilesWorkflow](!resources!/references/medusa-workflows/uploadFilesWorkflow):
```ts title="src/api/custom/route.ts"
import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http"
import { MedusaError } from "@medusajs/framework/utils"
import { uploadFilesWorkflow } from "@medusajs/medusa/core-flows"
export async function POST(
req: MedusaRequest,
res: MedusaResponse
) {
const files = req.files as Express.Multer.File[]
if (!files?.length) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
"No files were uploaded"
)
}
const { result } = await uploadFilesWorkflow(req.scope).run({
input: {
files: files?.map((f) => ({
filename: f.originalname,
mimeType: f.mimetype,
content: f.buffer.toString("binary"),
access: "public",
})),
},
})
res.status(200).json({ files: result })
}
```
Check out the [uploadFilesWorkflow reference](!resources!/references/medusa-workflows/uploadFilesWorkflow) for details on the expected input and output of the workflow.

View File

@@ -48,7 +48,7 @@ export const generatedEditDates = {
"app/learn/fundamentals/modules/module-links/page.mdx": "2024-09-30T08:43:53.126Z",
"app/learn/fundamentals/data-models/searchable-property/page.mdx": "2024-10-21T13:30:21.369Z",
"app/learn/fundamentals/scheduled-jobs/execution-number/page.mdx": "2024-10-21T13:30:21.371Z",
"app/learn/fundamentals/api-routes/parameters/page.mdx": "2024-11-19T16:37:47.251Z",
"app/learn/fundamentals/api-routes/parameters/page.mdx": "2025-02-14T08:34:03.184Z",
"app/learn/fundamentals/api-routes/http-methods/page.mdx": "2024-10-21T13:30:21.367Z",
"app/learn/fundamentals/admin/tips/page.mdx": "2025-02-05T09:07:52.584Z",
"app/learn/fundamentals/api-routes/cors/page.mdx": "2024-12-09T13:04:04.357Z",
@@ -116,5 +116,6 @@ export const generatedEditDates = {
"app/learn/customization/reuse-customizations/page.mdx": "2025-01-22T10:01:57.665Z",
"app/learn/update/page.mdx": "2025-01-27T08:45:19.030Z",
"app/learn/fundamentals/module-links/query-context/page.mdx": "2025-02-12T16:59:20.963Z",
"app/learn/fundamentals/admin/environment-variables/page.mdx": "2025-02-06T13:29:46.800Z"
"app/learn/fundamentals/admin/environment-variables/page.mdx": "2025-02-06T13:29:46.800Z",
"app/learn/fundamentals/api-routes/parse-body/page.mdx": "2025-02-14T08:32:25.596Z"
}

View File

@@ -533,6 +533,15 @@ export const generatedSidebar = [
"children": [],
"chapterTitle": "3.5.4. Middlewares"
},
{
"loaded": true,
"isPathHref": true,
"type": "link",
"path": "/learn/fundamentals/api-routes/parse-body",
"title": "Body Parsing",
"children": [],
"chapterTitle": "3.5.5. Body Parsing"
},
{
"loaded": true,
"isPathHref": true,
@@ -540,7 +549,7 @@ export const generatedSidebar = [
"path": "/learn/fundamentals/api-routes/validation",
"title": "Validation",
"children": [],
"chapterTitle": "3.5.5. Validation"
"chapterTitle": "3.5.6. Validation"
},
{
"loaded": true,
@@ -549,7 +558,7 @@ export const generatedSidebar = [
"path": "/learn/fundamentals/api-routes/protected-routes",
"title": "Protected Routes",
"children": [],
"chapterTitle": "3.5.6. Protected Routes"
"chapterTitle": "3.5.7. Protected Routes"
},
{
"loaded": true,
@@ -558,7 +567,7 @@ export const generatedSidebar = [
"path": "/learn/fundamentals/api-routes/errors",
"title": "Errors",
"children": [],
"chapterTitle": "3.5.7. Errors"
"chapterTitle": "3.5.8. Errors"
},
{
"loaded": true,
@@ -567,7 +576,7 @@ export const generatedSidebar = [
"path": "/learn/fundamentals/api-routes/cors",
"title": "Handling CORS",
"children": [],
"chapterTitle": "3.5.8. Handling CORS"
"chapterTitle": "3.5.9. Handling CORS"
},
{
"loaded": true,
@@ -576,7 +585,7 @@ export const generatedSidebar = [
"path": "/learn/fundamentals/api-routes/additional-data",
"title": "Additional Data",
"children": [],
"chapterTitle": "3.5.9. Additional Data"
"chapterTitle": "3.5.10. Additional Data"
}
],
"chapterTitle": "3.5. API Routes"

File diff suppressed because it is too large Load Diff

View File

@@ -308,6 +308,11 @@ export const sidebar = sidebarAttachHrefCommonOptions([
path: "/learn/fundamentals/api-routes/middlewares",
title: "Middlewares",
},
{
type: "link",
path: "/learn/fundamentals/api-routes/parse-body",
title: "Body Parsing",
},
{
type: "link",
path: "/learn/fundamentals/api-routes/validation",