-
Notifications
You must be signed in to change notification settings - Fork 375
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: support for redirects with 200 status. Fix crashing dev server w… #7034
base: main
Are you sure you want to change the base?
Conversation
@@ -202,7 +206,7 @@ const handleAddonUrl = function ({ addonUrl, req, res }) { | |||
|
|||
// @ts-expect-error TS(7006) FIXME: Parameter 'match' implicitly has an 'any' type. | |||
const isRedirect = function (match) { | |||
return match.status && match.status >= 300 && match.status <= 400 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this is a mistake, 400 should not be included
return url?.startsWith('/.netlify/') ?? false | ||
} | ||
|
||
function isInternal(url?: string): boolean { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've separated these 2 methods
All places of usage is using isInternalFunctions
, and only 1 place which affects URL override use this method
!isInternal(req.url) && | ||
!isInternal(destURL) && | ||
!isInternalFunctions(req.url) && | ||
!isInternalFunctions(destURL) && | ||
(ct.endsWith('/x-www-form-urlencoded') || ct === 'multipart/form-data') | ||
) { | ||
return proxy.web(req, res, { target: options.functionsServer }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
on line 433-437
https://github.com/netlify/cli/pull/7034/files#diff-7c2533ca30d8693b3cecb3406646bc13b86b3969b43a0aa0659bb52c7676caa9R437
(GH not allow to leave a comment there, bummer)
instead of checking if it's just a static file, or internalUrl which is now isInternalFunctions
-> it uses isInternal
which just checks if url starts with /
meaning it's internal url.
And then basically it lands into the if-else check and does the status/url override
proxy.on('error', (err, req, res) => { | ||
console.error('Got error from proxy', err); | ||
|
||
if (res instanceof http.ServerResponse) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had this issue here and there, wanted to fix it as well
src/utils/proxy.ts
Outdated
'Content-Type': 'text/plain', | ||
}) | ||
proxy.on('error', (err, req, res) => { | ||
console.error('Got error from proxy', err); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think more logging is better than less
options: req.proxyOptions, | ||
siteInfo, | ||
env, | ||
if (isRedirect({ status: proxyRes.statusCode }) && proxyRes.headers.location) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here is another change.
User has a redirect to the page, which also has internal redirect.
For instance, gatsby sites likes to do a redirection from /page
to /page/
(slash in the end).
So we basically want to follow it:
- user hits /test/page
- it matches redirect /test/* -> /:splat
- cli proxies contents of the
/:splat
, which includesLocation
header. But status is 200 instead of 3xx (and original is 302 for instance, meaning localhost:8000 returns { 302, Location }, but location:8888 returns { 200, Location }
Users see now this page:

This is browser built-in contents. Location header is there. Browser will never do
the redirect since, if you want it to happen, either status should be 3xx, or another header Refresh
should be there.
So, instead, here we are changing the flow for the netlify dev (which is typically runs SSGs in develop mode, not in the production mode) to this:
| Target app wants redirect on this route? Follow it
This change can be left intact and for instance, I can enable it only for some of the contexts (e.g. for dev server context). WDYT?
res.write('Root page') | ||
res.end() | ||
} else if (pathname === '/test/exists') { | ||
res.writeHead(302, undefined, { location: '/test/exists/' }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
examples of the site which makes redirect, so then in netlify toml we want to land on this page, which then wants to jump to the next
52d39e4
to
f334be1
Compare
@@ -2,6 +2,6 @@ | |||
command = "npm run serve" | |||
framework = "#custom" | |||
functions = "functions/" | |||
port = 7000 | |||
port = 7001 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
7000 by default on OS X taken by airplay, failed my tests
b9b41f6
to
59c1680
Compare
…hen have socket error. Follow redirects from proxyRes
59c1680
to
90cbb20
Compare
req.url = destStaticFile ? destStaticFile + dest.search : destURL | ||
const { status } = match | ||
statusValue = status | ||
if (match.force || status !== 200) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
override status code only if forcing or status is not 200, when 200 is just shadowing the page by the url, so it's status should be propagated (e.g. 404 because it's not there or idk 201 because server decided to return 201 by that url)
…hen have socket error. Follow redirects from proxyRes
🎉 Thanks for submitting a pull request! 🎉
Summary
Fixes WRFL-2263
One of the customers who are using Gatsby uses a 200 redirect
It works on prod but doesn't in
netlify dev
Root cause for that we are not overriding the url if the file is not static, and in case of dev server running on gatsby (or next as well) - it is never static.
See the updated
redirects.test.ts
-> specifically thesite-with-redirect > should do local redirect
It creates a simple redirect for
/local/*
to/:splat
with status 200, user navigates for/local/test/exists
:before the change: 404 page not found
after the change: keeping url of /local/test/exists but content of
/test/exists
(as per docs)For us to review and ship your PR efficiently, please perform the following steps:
passes our tests.
A picture of a cute animal (not mandatory, but encouraged)