Skip to content

Commit

Permalink
Remove deprecation for relative URL usage in middlewares (#34461)
Browse files Browse the repository at this point in the history
* Remove deprecation for relative URL usage in middlewares

* fix tests

Co-authored-by: JJ Kasper <[email protected]>
  • Loading branch information
Schniz and ijjk authored Feb 17, 2022
1 parent d4d79b2 commit f0f322c
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 19 deletions.
4 changes: 2 additions & 2 deletions errors/middleware-relative-urls.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

#### Why This Error Occurred

You are using a Middleware function that uses `Response.redirect(url)`, `NextResponse.redirect(url)` or `NextResponse.rewrite(url)` where `url` is a relative or an invalid URL. Currently this will work, but building a request with `new Request(url)` or running `fetch(url)` when `url` is a relative URL will **not** work. For this reason and to bring consistency to Next.js Middleware, this behavior will be deprecated soon in favor of always using absolute URLs.
You are using a Middleware function that uses `Response.redirect(url)`, `NextResponse.redirect(url)` or `NextResponse.rewrite(url)` where `url` is a relative or an invalid URL. Prior to Next.js 12.1, we allowed passing relative URLs. However, constructing a request with `new Request(url)` or running `fetch(url)` when `url` is a relative URL **does not** work. For this reason and to bring consistency to Next.js Middleware, this behavior has been deprecated and now removed.

#### Possible Ways to Fix It

To fix this warning you must always pass absolute URL for redirecting and rewriting. There are several ways to get the absolute URL but the recommended way is to clone `NextURL` and mutate it:
To fix this error you must always pass absolute URL for redirecting and rewriting. There are several ways to get the absolute URL but the recommended way is to clone `NextURL` and mutate it:

```typescript
import type { NextRequest } from 'next/server'
Expand Down
12 changes: 5 additions & 7 deletions packages/next/server/web/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,18 +149,16 @@ export function splitCookiesString(cookiesString: string) {
}

/**
* We will be soon deprecating the usage of relative URLs in Middleware introducing
* URL validation. This helper puts the future code in place and prints a warning
* for cases where it will break. Meanwhile we preserve the previous behavior.
* Validate the correctness of a user-provided URL.
*/
export function validateURL(url: string | URL): string {
try {
return String(new URL(String(url)))
} catch (error: any) {
console.log(
`warn -`,
'using relative URLs for Middleware will be deprecated soon - https://nextjs.org/docs/messages/middleware-relative-urls'
throw new Error(
`URLs is malformed. Please use only absolute URLs - https://nextjs.org/docs/messages/middleware-relative-urls`,
// @ts-expect-error This will work for people who enable the error causes polyfill
{ cause: error }
)
return String(url)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export async function middleware(request) {
) {
const isExternal = url.searchParams.get('override') === 'external'
return NextResponse.rewrite(
isExternal ? 'https://vercel.com' : '/rewrites/a'
isExternal ? 'https://vercel.com' : new URL('/rewrites/a', request.url)
)
}

Expand Down
39 changes: 30 additions & 9 deletions test/integration/middleware/core/test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const context = {}
context.appDir = join(__dirname, '../')

const middlewareWarning = 'using beta Middleware (not covered by semver)'
const urlsWarning = 'using relative URLs for Middleware will be deprecated soon'
const urlsError = 'Please use only absolute URLs'

describe('Middleware base tests', () => {
describe('dev mode', () => {
Expand Down Expand Up @@ -110,7 +110,7 @@ describe('Middleware base tests', () => {
})
})

function urlTests(log, locale = '') {
function urlTests(_log, locale = '') {
it('rewrites by default to a target location', async () => {
const res = await fetchViaHTTP(context.appPort, `${locale}/urls`)
const html = await res.text()
Expand Down Expand Up @@ -146,18 +146,39 @@ function urlTests(log, locale = '') {
})

it('warns when using Response.redirect with a relative URL', async () => {
await fetchViaHTTP(context.appPort, `${locale}/urls/relative-redirect`)
expect(log.output).toContain(urlsWarning)
const response = await fetchViaHTTP(
context.appPort,
`${locale}/urls/relative-redirect`
)
expect(await response.json()).toEqual({
error: {
message: expect.stringContaining(urlsError),
},
})
})

it('warns when using NextResponse.redirect with a relative URL', async () => {
await fetchViaHTTP(context.appPort, `${locale}/urls/relative-next-redirect`)
expect(log.output).toContain(urlsWarning)
const response = await fetchViaHTTP(
context.appPort,
`${locale}/urls/relative-next-redirect`
)
expect(await response.json()).toEqual({
error: {
message: expect.stringContaining(urlsError),
},
})
})

it('warns when using NextResponse.rewrite with a relative URL', async () => {
await fetchViaHTTP(context.appPort, `${locale}/urls/relative-next-rewrite`)
expect(log.output).toContain(urlsWarning)
it('throws when using NextResponse.rewrite with a relative URL', async () => {
const response = await fetchViaHTTP(
context.appPort,
`${locale}/urls/relative-next-rewrite`
)
expect(await response.json()).toEqual({
error: {
message: expect.stringContaining(urlsError),
},
})
})
}

Expand Down

0 comments on commit f0f322c

Please sign in to comment.