vercel / next.js

The React Framework
https://nextjs.org
MIT License
126.74k stars 26.95k forks source link

Error Invalid character in header content ["Location"] with trailingSlash enabled #31677

Closed studio404pl closed 1 year ago

studio404pl commented 2 years ago

What version of Next.js are you using?

11.1.2

What version of Node.js are you using?

12.18.1

What browser are you using?

Brave

What operating system are you using?

macOS

How are you deploying your application?

next start

Describe the Bug

When the trailingSlash is enabled, the redirection doesn't work properly in some of the cases.

Example URL:

http://localhost:3000/some-url/%E2%80%9Chttps://domain.com/analytics?pxid=111&%E2%80%9D

Returned error:

error - TypeError [ERR_INVALID_CHAR]: Invalid character in header content ["Location"]
    at ServerResponse.setHeader (_http_outgoing.js:521:3)
    at Object.fn (/Library/WebServer/Documents/nextjs/node_modules/next/dist/server/next-server.js:554:25)
    at Router.execute (/Library/WebServer/Documents/nextjs/node_modules/next/dist/server/router.js:205:48)
    at DevServer.run (/Library/WebServer/Documents/nextjs/node_modules/next/dist/server/next-server.js:841:47)
    at DevServer.run (/Library/WebServer/Documents/nextjs/node_modules/next/dist/server/dev/next-dev-server.js:355:32)
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async DevServer.handleRequest (/Library/WebServer/Documents/nextjs/node_modules/next/dist/server/next-server.js:292:20) {
  code: 'ERR_INVALID_CHAR'
}

Expected Behavior

All of the URLS tried to be accessed are properly redirected without any errors thrown.

To Reproduce

  1. npm install next@11.1.2 react react-dom
  2. create a sample index page
  3. create a next.config.js file:
    module.exports = {
    trailingSlash: true,
    };
  4. npm run dev
  5. Visit the below URL in the browser:
    http://localhost:3000/some-url/%E2%80%9Chttps://domain.com/analytics?pxid=111&%E2%80%9D
  6. See the error
balazsorban44 commented 2 years ago

The URL is actually invalid, you have an extra & right after pxid=111. This works fine for me:

http://localhost:3000/some-url/%E2%80%9Chttps://domain.com/analytics?pxid=111%E2%80%9D

But it might be OK to add an empty key=value in URLs, so maybe we should handle that case correctly.

tills13 commented 2 years ago

Is it invalid?

The query is ?pxid=111&%E2%80%9D' which is parsed into { 'pxid' => '111', '”' => '' }

Per https://url.spec.whatwg.org/#concept-urlencoded-parser (and is the behaviour of URL)

> const u = new URL('http://localhost:3000/some-url/%E2%80%9Chttps://domain.com/analytics?pxid=111&%E2%80%9D')
> u.search
'?pxid=111&%E2%80%9D'
> u.searchParams
URLSearchParams { 'pxid' => '111', '”' => '' }

At the very least, NextJS shouldn't encounter an error in this situation.

balazsorban44 commented 2 years ago

After thinking some more about it @tills13, you are probably right, but I think this is actually not what the user wants. I needed to have another look, but

The URL

http://localhost:3000/some-url/%E2%80%9Chttps://domain.com/analytics?pxid=111&%E2%80%9D

looks like this when decoded:

http://localhost:3000/some-url/“https:/domain.com/analytics?pxid=111&”

They probably don't expect the search params to be parsed in this case, it's not part of the "outer" URL, but rather the one between and .

I believe encoding the "inner" URL resolves the user's problem

http://localhost:3000/some-url/%E2%80%9Chttps%3A%2F%2Fdomain.com%2Fanalytics%3Fpxid%3D111%26%E2%80%9D

This will redirect correctly.

@studio404pl is this what you want?:

new URL(`http://localhost:3000/some-url/%E2%80%9C${encodeURIComponent("https://domain.com/analytics?pxid=111&")}%E2%80%9D`)
tills13 commented 2 years ago

(I work with the original poster)

To be clear, this is something we encountered through APM, not something our app generates itself. We use ExpressJS and our own trailing slash middleware but the url in question didn't match any of our routes and so was handled by the default NextJS request handler.

Honestly we see so much garbage come through our system ... who knows what people are doing on their machines to produce something like this. Seeing the garbage result in a 500 was new, though. Typically we'll see a 30X and then a 404.

studio404pl commented 2 years ago

@balazsorban44 as @tills13 already said, it should be handled gently by NextJS if we can expect any kind of input here. The problem is not about fixing the input data, just to process them properly even if they are malformed.

github-actions[bot] commented 1 year ago

Please verify that your issue can be recreated with next@canary.

Why was this issue marked with the please verify canary label?

We noticed the provided reproduction was using an older version of Next.js, instead of canary.

The canary version of Next.js ships daily and includes all features and fixes that have not been released to the stable version yet. You can think of canary as a public beta. Some issues may already be fixed in the canary version, so please verify that your issue reproduces by running npm install next@canary and test it in your project, using your reproduction steps.

If the issue does not reproduce with the canary version, then it has already been fixed and this issue can be closed.

How can I quickly verify if my issue has been fixed in canary?

The safest way is to install next@canary in your project and test it, but you can also search through closed Next.js issues for duplicates or check the Next.js releases.

My issue has been open for a long time, why do I need to verify canary now?

Next.js does not backport bug fixes to older versions of Next.js. Instead, we are trying to introduce only a minimal amount of breaking changes between major releases.

What happens if I don't verify against the canary version of Next.js?

An issue with the please verify canary that receives no meaningful activity (e.g. new comments that acknowledge verification against canary) will be automatically closed and locked after 30 days.

If your issue has not been resolved in that time and it has been closed/locked, please open a new issue, with the required reproduction, using next@canary.

I did not open this issue, but it is relevant to me, what can I do to help?

Anyone experiencing the same issue is welcome to provide a minimal reproduction following the above steps. Furthermore, you can upvote the issue using the :+1: reaction on the topmost comment (please do not comment "I have the same issue" without repro steps). Then, we can sort issues by votes to prioritize.

I think my reproduction is good enough, why aren't you looking into it quicker?

We look into every Next.js issue and constantly monitor open issues for new comments.

However, sometimes we might miss one or two due to the popularity/high traffic of the repository. We apologize, and kindly ask you to refrain from tagging core maintainers, as that will usually not result in increased priority.

Upvoting issues to show your interest will help us prioritize and address them as quickly as possible. That said, every issue is important to us, and if an issue gets closed by accident, we encourage you to open a new one linking to the old issue and we will look into it.

Useful Resources

balazsorban44 commented 1 year ago

This issue has been automatically closed because it wasn't verified against next@canary. If you think it was closed by accident, please leave a comment. If you are running into a similar issue, please open a new issue with a reproduction. Thank you.

github-actions[bot] commented 1 year ago

This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.