Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix handling for 204 status code with a body #28479

Merged
merged 4 commits into from Aug 25, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
32 changes: 32 additions & 0 deletions errors/invalid-api-status-body.md
@@ -0,0 +1,32 @@
Invalid API Route Status/Body Response

#### Why This Error Occurred

In one of your API routes a 204 or 304 status code was used as well as sending a response body.

This is invalid as a 204 or 304 status code dictates no response body should be present.

#### Possible Ways to Fix It

Send an empty body when using a 204 or 304 status code or use a different status code while sending a response body.

Before

```js
export default function handler(req, res) {
res.status(204).send('invalid body')
}
```

After

```js
export default function handler(req, res) {
res.status(204).send()
}
```

### Useful Links

- [204 status code documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/204)
- [304 status code documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304)
4 changes: 4 additions & 0 deletions errors/manifest.json
Expand Up @@ -454,6 +454,10 @@
{
"title": "next-config-error",
"path": "/errors/next-config-error.md"
},
{
"title": "invalid-api-status-body",
"path": "/errors/invalid-api-status-body.md"
}
]
}
Expand Down
16 changes: 16 additions & 0 deletions packages/next/server/api-utils.ts
Expand Up @@ -258,6 +258,22 @@ export function sendData(
return
}

// strip irrelevant headers/body
if (res.statusCode === 204 || res.statusCode === 304) {
res.removeHeader('Content-Type')
res.removeHeader('Content-Length')
res.removeHeader('Transfer-Encoding')

if (process.env.NODE_ENV === 'development' && body) {
console.warn(
styfle marked this conversation as resolved.
Show resolved Hide resolved
`A body was attempted to be set with a 204 statusCode for ${req.url}, this is invalid and the body was ignored.\n` +
`See more info here https://nextjs.org/docs/messages/invalid-api-status-body`
)
}
res.end()
return
}

const contentType = res.getHeader('Content-Type')

if (body instanceof Stream) {
Expand Down
7 changes: 7 additions & 0 deletions test/integration/api-support/pages/api/status-204.js
@@ -0,0 +1,7 @@
export default function handler(req, res) {
if (req.query.invalid) {
// test the warning when content is added for a 204 response
return res.status(204).json({ hello: 'world' })
}
return res.status(204).send()
}
30 changes: 30 additions & 0 deletions test/integration/api-support/test/index.test.js
Expand Up @@ -26,6 +26,36 @@ let mode
let app

function runTests(dev = false) {
it('should handle 204 status correctly', async () => {
const res = await fetchViaHTTP(appPort, '/api/status-204', undefined, {
redirect: 'manual',
})
expect(res.status).toBe(204)
expect(res.headers.get('content-type')).toBe(null)
expect(res.headers.get('content-length')).toBe(null)
expect(res.headers.get('transfer-encoding')).toBe(null)

const stderrIdx = stderr.length
const res2 = await fetchViaHTTP(
appPort,
'/api/status-204',
{ invalid: '1' },
{
redirect: 'manual',
}
)
expect(res2.status).toBe(204)
expect(res2.headers.get('content-type')).toBe(null)
expect(res2.headers.get('content-length')).toBe(null)
expect(res2.headers.get('transfer-encoding')).toBe(null)

if (dev) {
expect(stderr.substr(stderrIdx)).toContain(
'A body was attempted to be set with a 204 statusCode'
)
}
})

it('should render page', async () => {
const html = await renderViaHTTP(appPort, '/')
expect(html).toMatch(/API - support/)
Expand Down