Skip to content

Commit

Permalink
Enable allowMiddlewareResponseBody by default (#44224)
Browse files Browse the repository at this point in the history
Follow-up to #44195


## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md)

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] [e2e](https://github.com/vercel/next.js/blob/canary/contributing/core/testing.md#writing-tests-for-nextjs) tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have a helpful link attached, see [`contributing.md`](https://github.com/vercel/next.js/blob/canary/contributing.md)

## Documentation / Examples

- [ ] Make sure the linting passes by running `pnpm build && pnpm lint`
- [ ] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
  • Loading branch information
timneutkens committed Dec 21, 2022
1 parent 52fb820 commit 9ee4c0c
Show file tree
Hide file tree
Showing 17 changed files with 15 additions and 141 deletions.
13 changes: 1 addition & 12 deletions docs/advanced-features/middleware.md
Expand Up @@ -221,18 +221,7 @@ export function middleware(request: NextRequest) {
## Producing a Response

You can respond to middleware directly by returning a `NextResponse` (responding from middleware is available since Next.js v13.0.0).

To enable middleware responses, update `next.config.js`:

```js
// next.config.js
module.exports = {
experimental: {
allowMiddlewareResponseBody: true,
},
}
```
You can respond to middleware directly by returning a `NextResponse` (responding from middleware is available since Next.js v13.1.0).

Once enabled, you can provide a response from middleware using the `Response` or `NextResponse` API:

Expand Down
8 changes: 0 additions & 8 deletions packages/next/build/webpack-config.ts
Expand Up @@ -301,9 +301,6 @@ export function getDefineEnv({
'process.env.__NEXT_I18N_SUPPORT': JSON.stringify(!!config.i18n),
'process.env.__NEXT_I18N_DOMAINS': JSON.stringify(config.i18n?.domains),
'process.env.__NEXT_ANALYTICS_ID': JSON.stringify(config.analyticsId),
'process.env.__NEXT_ALLOW_MIDDLEWARE_RESPONSE_BODY': JSON.stringify(
config.allowMiddlewareResponseBody
),
'process.env.__NEXT_NO_MIDDLEWARE_URL_NORMALIZE': JSON.stringify(
config.skipMiddlewareUrlNormalize
),
Expand Down Expand Up @@ -2062,7 +2059,6 @@ export default async function getBaseWebpackConfig(
dev,
sriEnabled: !dev && !!config.experimental.sri?.algorithm,
hasFontLoaders: !!config.experimental.fontLoaders,
allowMiddlewareResponseBody: !!config.allowMiddlewareResponseBody,
}),
isClient &&
new BuildManifestPlugin({
Expand Down Expand Up @@ -2154,10 +2150,6 @@ export default async function getBaseWebpackConfig(
['swcEmotion', !!config.compiler?.emotion],
['turbotrace', !!config.experimental.turbotrace],
['transpilePackages', !!config.transpilePackages],
[
'allowMiddlewareResponseBody',
!!config.allowMiddlewareResponseBody,
],
[
'skipMiddlewareUrlNormalize',
!!config.skipMiddlewareUrlNormalize,
Expand Down
6 changes: 3 additions & 3 deletions packages/next/build/webpack/loaders/next-middleware-loader.ts
Expand Up @@ -40,7 +40,7 @@ export default function middlewareLoader(this: any) {
buildInfo.rootDir = rootDir

return `
import { adapter, blockUnallowedResponse, enhanceGlobals } from 'next/dist/esm/server/web/adapter'
import { adapter, enhanceGlobals } from 'next/dist/esm/server/web/adapter'
enhanceGlobals()
Expand All @@ -52,11 +52,11 @@ export default function middlewareLoader(this: any) {
}
export default function (opts) {
return blockUnallowedResponse(adapter({
return adapter({
...opts,
page: ${JSON.stringify(page)},
handler,
}))
})
}
`
}
52 changes: 0 additions & 52 deletions packages/next/build/webpack/plugins/middleware-plugin.ts
Expand Up @@ -232,21 +232,6 @@ function isInMiddlewareLayer(parser: webpack.javascript.JavascriptParser) {
return parser.state.module?.layer === 'middleware'
}

function isInMiddlewareFile(parser: webpack.javascript.JavascriptParser) {
return (
parser.state.current?.layer === 'middleware' &&
/middleware\.\w+$/.test(parser.state.current?.rawRequest)
)
}

function isNullLiteral(expr: any) {
return expr.value === null
}

function isUndefinedIdentifier(expr: any) {
return expr.name === 'undefined'
}

function isProcessEnvMemberExpression(memberExpression: any): boolean {
return (
memberExpression.object?.type === 'Identifier' &&
Expand Down Expand Up @@ -345,14 +330,12 @@ function getCodeAnalyzer(params: {
dev: boolean
compiler: webpack.Compiler
compilation: webpack.Compilation
allowMiddlewareResponseBody: boolean
}) {
return (parser: webpack.javascript.JavascriptParser) => {
const {
dev,
compiler: { webpack: wp },
compilation,
allowMiddlewareResponseBody,
} = params
const { hooks } = parser

Expand Down Expand Up @@ -488,32 +471,6 @@ function getCodeAnalyzer(params: {
}
}

/**
* A handler for calls to `new Response()` so we can fail if user is setting the response's body.
*/
const handleNewResponseExpression = (node: any) => {
const firstParameter = node?.arguments?.[0]
if (
isInMiddlewareFile(parser) &&
firstParameter &&
!isNullLiteral(firstParameter) &&
!isUndefinedIdentifier(firstParameter)
) {
const error = buildWebpackError({
message: `Middleware is returning a response body (line: ${node.loc.start.line}), which is not supported.
Learn more: https://nextjs.org/docs/messages/returning-response-body-in-middleware`,
compilation,
parser,
...node,
})
if (dev) {
compilation.warnings.push(error)
} else {
compilation.errors.push(error)
}
}
}

/**
* Handler to store original source location of static and dynamic imports into module's buildInfo.
*/
Expand Down Expand Up @@ -568,10 +525,6 @@ Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime`,
.tap(NAME, handleWrapWasmInstantiateExpression)
}

if (!allowMiddlewareResponseBody) {
hooks.new.for('Response').tap(NAME, handleNewResponseExpression)
hooks.new.for('NextResponse').tap(NAME, handleNewResponseExpression)
}
hooks.callMemberChain.for('process').tap(NAME, handleCallMemberChain)
hooks.expressionMemberChain.for('process').tap(NAME, handleCallMemberChain)
hooks.importCall.tap(NAME, handleImport)
Expand Down Expand Up @@ -835,23 +788,19 @@ export default class MiddlewarePlugin {
private readonly dev: boolean
private readonly sriEnabled: boolean
private readonly hasFontLoaders: boolean
private readonly allowMiddlewareResponseBody: boolean

constructor({
dev,
sriEnabled,
hasFontLoaders,
allowMiddlewareResponseBody,
}: {
dev: boolean
sriEnabled: boolean
hasFontLoaders: boolean
allowMiddlewareResponseBody: boolean
}) {
this.dev = dev
this.sriEnabled = sriEnabled
this.hasFontLoaders = hasFontLoaders
this.allowMiddlewareResponseBody = allowMiddlewareResponseBody
}

public apply(compiler: webpack.Compiler) {
Expand All @@ -864,7 +813,6 @@ export default class MiddlewarePlugin {
dev: this.dev,
compiler,
compilation,
allowMiddlewareResponseBody: this.allowMiddlewareResponseBody,
})
hooks.parser.for('javascript/auto').tap(NAME, codeAnalyzer)
hooks.parser.for('javascript/dynamic').tap(NAME, codeAnalyzer)
Expand Down
2 changes: 0 additions & 2 deletions packages/next/build/webpack/plugins/telemetry-plugin.ts
Expand Up @@ -38,7 +38,6 @@ export type Feature =
| `swc/target/${SWC_TARGET_TRIPLE}`
| 'turbotrace'
| 'transpilePackages'
| 'allowMiddlewareResponseBody'
| 'skipMiddlewareUrlNormalize'
| 'skipTrailingSlashRedirect'

Expand Down Expand Up @@ -101,7 +100,6 @@ const BUILD_FEATURES: Array<Feature> = [
'swc/target/aarch64-pc-windows-msvc',
'turbotrace',
'transpilePackages',
'allowMiddlewareResponseBody',
'skipMiddlewareUrlNormalize',
'skipTrailingSlashRedirect',
]
Expand Down
3 changes: 0 additions & 3 deletions packages/next/server/config-schema.ts
Expand Up @@ -7,9 +7,6 @@ const configSchema = {
type: 'object',
additionalProperties: false,
properties: {
allowMiddlewareResponseBody: {
type: 'boolean',
},
amp: {
additionalProperties: false,
properties: {
Expand Down
2 changes: 0 additions & 2 deletions packages/next/server/config-shared.ts
Expand Up @@ -504,8 +504,6 @@ export interface NextConfig extends Record<string, any> {
// A list of packages that should always be transpiled and bundled in the server
transpilePackages?: string[]

allowMiddlewareResponseBody?: boolean

skipMiddlewareUrlNormalize?: boolean

skipTrailingSlashRedirect?: boolean
Expand Down
12 changes: 0 additions & 12 deletions packages/next/server/config.ts
Expand Up @@ -615,18 +615,6 @@ function assignDefaults(dir: string, userConfig: { [key: string]: any }) {
result.transpilePackages = (result.experimental as any).transpilePackages
}

if (
result.experimental &&
'allowMiddlewareResponseBody' in (result.experimental as any)
) {
Log.warn(
`\`allowMiddlewareResponseBody\` has been moved out of \`experimental\`. Please update your ${configFileName} file accordingly.`
)
result.allowMiddlewareResponseBody = (
result.experimental as any
).allowMiddlewareResponseBody
}

if (
result.experimental &&
'skipMiddlewareUrlNormalize' in (result.experimental as any)
Expand Down
26 changes: 0 additions & 26 deletions packages/next/server/web/adapter.ts
Expand Up @@ -198,32 +198,6 @@ export async function adapter(params: {
}
}

export function blockUnallowedResponse(
promise: Promise<FetchEventResult>
): Promise<FetchEventResult> {
if (process.env.__NEXT_ALLOW_MIDDLEWARE_RESPONSE_BODY) {
return promise
}

return promise.then((result) => {
if (result.response?.body) {
console.error(
new Error(
`A middleware can not alter response's body. Learn more: https://nextjs.org/docs/messages/returning-response-body-in-middleware`
)
)
return {
...result,
response: new Response('Internal Server Error', {
status: 500,
statusText: 'Internal Server Error',
}),
}
}
return result
})
}

function getUnsupportedModuleErrorMessage(module: string) {
// warning: if you change these messages, you must adjust how react-dev-overlay's middleware detects modules not found
return `The edge runtime does not support Node.js '${module}' module.
Expand Down
1 change: 0 additions & 1 deletion packages/next/telemetry/events/build.ts
Expand Up @@ -167,7 +167,6 @@ export type EventBuildFeatureUsage = {
| 'build-lint'
| 'vercelImageGeneration'
| 'transpilePackages'
| 'allowMiddlewareResponseBody'
| 'skipMiddlewareUrlNormalize'
| 'skipTrailingSlashRedirect'
invocationCount: number
Expand Down
4 changes: 2 additions & 2 deletions test/development/middleware-warnings/index.test.ts
Expand Up @@ -61,9 +61,9 @@ describe('middlewares', () => {
return new Response(await fetch('https://example.vercel.sh'));
}`,
},
])('warns when $title', async ({ code }) => {
])('does not warn when $title', async ({ code }) => {
;({ cleanup } = await sandbox(next, new Map([[middlewarePath, code]])))
expect(next.cliOutput).toMatch(middlewareWarning)
expect(next.cliOutput).not.toMatch(middlewareWarning)
})

it.each([
Expand Down
1 change: 0 additions & 1 deletion test/e2e/app-dir/app-middleware/next.config.js
@@ -1,5 +1,4 @@
module.exports = {
allowMiddlewareResponseBody: true,
experimental: {
appDir: true,
},
Expand Down
14 changes: 6 additions & 8 deletions test/e2e/middleware-responses/test/index.test.ts
Expand Up @@ -29,25 +29,23 @@ describe('Middleware Responses', () => {
])
})

it(`${label}should fail when returning a stream`, async () => {
it(`${label}should not fail when returning a stream`, async () => {
const res = await fetchViaHTTP(next.url, `${locale}/stream-a-response`)
expect(res.status).toBe(500)
expect(res.status).toBe(200)

if (!(global as any).isNextDeploy) {
expect(await res.text()).toEqual('Internal Server Error')
expect(next.cliOutput).toContain(
expect(next.cliOutput).not.toContain(
`A middleware can not alter response's body. Learn more: https://nextjs.org/docs/messages/returning-response-body-in-middleware`
)
}
})

it(`${label}should fail when returning a text body`, async () => {
it(`${label}should not fail when returning a text body`, async () => {
const res = await fetchViaHTTP(next.url, `${locale}/send-response`)
expect(res.status).toBe(500)
expect(res.status).toBe(200)

if (!(global as any).isNextDeploy) {
expect(await res.text()).toEqual('Internal Server Error')
expect(next.cliOutput).toContain(
expect(next.cliOutput).not.toContain(
`A middleware can not alter response's body. Learn more: https://nextjs.org/docs/messages/returning-response-body-in-middleware`
)
}
Expand Down
1 change: 0 additions & 1 deletion test/e2e/skip-trailing-slash-redirect/app/next.config.js
@@ -1,6 +1,5 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
allowMiddlewareResponseBody: true,
skipMiddlewareUrlNormalize: true,
skipTrailingSlashRedirect: true,
async redirects() {
Expand Down
6 changes: 3 additions & 3 deletions test/integration/middleware-build-errors/test/index.test.js
Expand Up @@ -53,13 +53,13 @@ describe('Middleware validation during build', () => {
])('given a middleware $title', ({ code }) => {
beforeAll(() => writeFile(middlewareFile, code))

it('throws an error', async () => {
it('does not throw an error', async () => {
const { stderr, code } = await nextBuild(appDir, [], {
stderr: true,
stdout: true,
})
expect(stderr).toMatch(middlewareError)
expect(code).toBe(1)
expect(stderr).not.toMatch(middlewareError)
expect(code).toBe(0)
})
})

Expand Down
1 change: 0 additions & 1 deletion test/integration/telemetry/next.config.middleware-options
@@ -1,5 +1,4 @@
module.exports = {
allowMiddlewareResponseBody: true,
skipMiddlewareUrlNormalize: true,
skipTrailingSlashRedirect: true,
}
4 changes: 0 additions & 4 deletions test/integration/telemetry/test/index.test.js
Expand Up @@ -1137,10 +1137,6 @@ describe('Telemetry CLI', () => {
stderr,
'NEXT_BUILD_FEATURE_USAGE'
)
expect(featureUsageEvents).toContainEqual({
featureName: 'allowMiddlewareResponseBody',
invocationCount: 1,
})
expect(featureUsageEvents).toContainEqual({
featureName: 'skipMiddlewareUrlNormalize',
invocationCount: 1,
Expand Down

0 comments on commit 9ee4c0c

Please sign in to comment.