Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/content/docs/adapters/express.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ description: Use oRPC inside an Express.js project
[Express.js](https://expressjs.com/) is a popular Node.js framework for building web applications. For additional context, refer to the [HTTP Adapter](/docs/adapters/http) guide.

::: warning
oRPC uses its own request parser. To avoid conflicts, register any body-parsing middleware **after** your oRPC middleware or only on routes that don't use oRPC.
Express's [body-parser](https://expressjs.com/en/resources/middleware/body-parser.html) handles common request body types, and oRPC will use the parsed body if available. However, it doesn't support features like [Bracket Notation](/docs/openapi/bracket-notation), and in case you upload a file with `application/json`, it may be parsed as plain JSON instead of a `File`. To avoid these issues, register any body-parsing middleware **after** your oRPC middleware or only on routes that don't use oRPC.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This paragraph is a bit long and dense. For better readability, consider breaking down the information into a list of limitations.

Suggested change
Express's [body-parser](https://expressjs.com/en/resources/middleware/body-parser.html) handles common request body types, and oRPC will use the parsed body if available. However, it doesn't support features like [Bracket Notation](/docs/openapi/bracket-notation), and in case you upload a file with `application/json`, it may be parsed as plain JSON instead of a `File`. To avoid these issues, register any body-parsing middleware **after** your oRPC middleware or only on routes that don't use oRPC.
Express's [body-parser](https://expressjs.com/en/resources/middleware/body-parser.html) handles common request body types, and oRPC will use the parsed body if available. However, this approach has some limitations:
- It doesn't support features like [Bracket Notation](/docs/openapi/bracket-notation).
- A file uploaded with `application/json` may be parsed as a plain JSON object instead of a `File`.
To avoid these issues, register any body-parsing middleware **after** your oRPC middleware or only on routes that don't use oRPC.

:::

## Basic
Expand Down
3 changes: 1 addition & 2 deletions apps/content/docs/adapters/next.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ export default async (req, res) => {
```

::: warning

Next.js default [body parser](https://nextjs.org/docs/pages/building-your-application/routing/api-routes#custom-config) blocks oRPC raw‑request handling. Ensure `bodyParser` is disabled in your API route:
Next.js [body parser](https://nextjs.org/docs/pages/building-your-application/routing/api-routes#custom-config) may handle common request body types, and oRPC will use the parsed body if available. However, it doesn't support features like [Bracket Notation](/docs/openapi/bracket-notation), and in case you upload a file with `application/json`, it may be parsed as plain JSON instead of a `File`. To avoid these issues, disable the body parser:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This paragraph is a bit long and dense. For better readability, consider breaking down the information into a list of limitations.

Suggested change
Next.js [body parser](https://nextjs.org/docs/pages/building-your-application/routing/api-routes#custom-config) may handle common request body types, and oRPC will use the parsed body if available. However, it doesn't support features like [Bracket Notation](/docs/openapi/bracket-notation), and in case you upload a file with `application/json`, it may be parsed as plain JSON instead of a `File`. To avoid these issues, disable the body parser:
Next.js [body parser](https://nextjs.org/docs/pages/building-your-application/routing/api-routes#custom-config) may handle common request body types, and oRPC will use the parsed body if available. However, this approach has some limitations:
- It doesn't support features like [Bracket Notation](/docs/openapi/bracket-notation).
- A file uploaded with `application/json` may be parsed as a plain JSON object instead of a `File`.
To avoid these issues, disable the body parser:


```ts
export const config = {
Expand Down
4 changes: 3 additions & 1 deletion packages/nest/src/implement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,9 @@ export class ImplementInterceptor implements NestInterceptor {
const standardRequest = toStandardLazyRequest(nodeReq, nodeRes)
const fallbackStandardBody = standardRequest.body.bind(standardRequest)
// Prefer NestJS parsed body (in nodejs body only allow parse once)
standardRequest.body = () => Promise.resolve(req.body ?? fallbackStandardBody())
standardRequest.body = () => Promise.resolve(
req.body === undefined ? fallbackStandardBody() : req.body,
)

const standardResponse: StandardResponse = await (async () => {
let isDecoding = false
Expand Down
13 changes: 13 additions & 0 deletions packages/standard-server-node/src/body.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,19 @@ describe('toStandardBody', () => {
expect(getFilenameFromContentDispositionSpy).toHaveBeenCalledTimes(1)
expect(getFilenameFromContentDispositionSpy).toHaveBeenCalledWith('attachment')
})

it('prefer parsed body', async () => {
let standardBody: StandardBody = {} as any

await request(async (req: IncomingMessage, res: ServerResponse) => {
// @ts-expect-error fake body is parsed
req.body = { value: 123 }
standardBody = await toStandardBody(req)
res.end()
}).post('/').send()

expect(standardBody).toEqual({ value: 123 })
})
})

describe('toNodeHttpBody', () => {
Expand Down
4 changes: 4 additions & 0 deletions packages/standard-server-node/src/body.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import { toEventIterator, toEventStream } from './event-iterator'
export interface ToStandardBodyOptions extends ToEventIteratorOptions {}

export function toStandardBody(req: NodeHttpRequest, options: ToStandardBodyOptions = {}): Promise<StandardBody> {
if (req.body !== undefined) {
return Promise.resolve(req.body)
}

return runWithSpan({ name: 'parse_standard_body', signal: options.signal }, async () => {
const contentDisposition = req.headers['content-disposition']
const contentType = req.headers['content-type']
Expand Down
5 changes: 5 additions & 0 deletions packages/standard-server-node/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ export type NodeHttpRequest = (IncomingMessage | Http2ServerRequest) & {
* This is useful for `express.js` middleware.
*/
originalUrl?: string

/**
* Prefer parsed body if it is available.
*/
body?: unknown
}

export type NodeHttpResponse = ServerResponse | Http2ServerResponse
Loading