-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
feat(node): handle redirects dynamically in static mode #14441
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
Merged
Merged
Changes from 3 commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
--- | ||
'@astrojs/node': minor | ||
'astro': patch | ||
--- | ||
|
||
Updates redirect handling to be consistent across `static` and `server` output, aligning with the behavior of other adapters. | ||
|
||
Previously, the Node.js adapter used default HTML files with meta refresh tags when in `static` output. This often resulted in an extra flash of the page on redirect, while also not applying the proper status code for redirections. It's also likely less friendly to search engines. | ||
|
||
This update ensures that configured redirects are always handled as HTTP redirects regardless of output mode, and the default HTML files for the redirects are no longer generated in `static` output. It makes the Node.js adapter more consistent with the other official adapters. | ||
|
||
No change to your project is required to take advantage of this new adapter functionality. It is not expected to cause any breaking changes. However, in an unlikely event that you previously rely on the generated redirecting HTML files for some reason, you may need to handle the redirects differently now. Otherwise you should just notice smoother redirects, with more accurate HTTP status codes, and may potentially see some SEO gains. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
packages/integrations/node/test/fixtures/redirects/astro.config.mjs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { defineConfig } from 'astro/config'; | ||
import nodejs from '@astrojs/node'; | ||
|
||
export default defineConfig({ | ||
adapter: nodejs({ mode: 'standalone' }), | ||
redirects: { | ||
'/old-page': '/new-page', | ||
'/old-page-301': { | ||
status: 301, | ||
destination: '/new-page-301', | ||
}, | ||
'/old-page-302': { | ||
status: 302, | ||
destination: '/new-page-302', | ||
}, | ||
'/dynamic/[slug]': '/pages/[slug]', | ||
'/spread/[...path]': '/content/[...path]', | ||
'/external': 'https://example.com', | ||
}, | ||
}); |
9 changes: 9 additions & 0 deletions
9
packages/integrations/node/test/fixtures/redirects/package.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"name": "@test/redirects", | ||
"version": "0.0.0", | ||
"private": true, | ||
"dependencies": { | ||
"astro": "workspace:*", | ||
"@astrojs/node": "workspace:*" | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
packages/integrations/node/test/fixtures/redirects/src/pages/content/[...path].astro
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--- | ||
// Spread route for testing spread redirects | ||
|
||
export function getStaticPaths() { | ||
return [ | ||
{ params: { path: 'some/nested/path' } }, | ||
]; | ||
} | ||
--- |
3 changes: 3 additions & 0 deletions
3
packages/integrations/node/test/fixtures/redirects/src/pages/new-page-301.astro
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
--- | ||
// This is the destination page for 301 redirects | ||
--- |
3 changes: 3 additions & 0 deletions
3
packages/integrations/node/test/fixtures/redirects/src/pages/new-page-302.astro
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
--- | ||
// This is the destination page for 302 redirects | ||
--- |
3 changes: 3 additions & 0 deletions
3
packages/integrations/node/test/fixtures/redirects/src/pages/new-page.astro
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
--- | ||
// This is the destination page for redirects | ||
--- |
9 changes: 9 additions & 0 deletions
9
packages/integrations/node/test/fixtures/redirects/src/pages/pages/[slug].astro
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
--- | ||
// Dynamic page for testing dynamic redirects | ||
|
||
export function getStaticPaths() { | ||
return [ | ||
{ params: { slug: 'test-slug' } }, | ||
]; | ||
} | ||
--- |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import assert from 'node:assert/strict'; | ||
import { after, before, describe, it } from 'node:test'; | ||
import nodejs from '../dist/index.js'; | ||
import { loadFixture, waitServerListen } from './test-utils.js'; | ||
|
||
describe('Redirects', () => { | ||
/** @type {import('./test-utils').Fixture} */ | ||
let fixture; | ||
let server; | ||
|
||
before(async () => { | ||
fixture = await loadFixture({ | ||
root: './fixtures/redirects/', | ||
adapter: nodejs({ mode: 'standalone' }), | ||
}); | ||
await fixture.build(); | ||
const { startServer } = await fixture.loadAdapterEntryModule(); | ||
const res = startServer(); | ||
server = res.server; | ||
await waitServerListen(server.server); | ||
}); | ||
|
||
after(async () => { | ||
await server.stop(); | ||
await fixture.clean(); | ||
}); | ||
|
||
function fetchEndpoint(url, options = {}) { | ||
return fetch( | ||
`http://${server.host}:${server.port}/${url}`, | ||
{ ...options, redirect: 'manual' }, | ||
); | ||
} | ||
|
||
it('should redirect with default 301 status for simple redirects', async () => { | ||
const response = await fetchEndpoint('old-page'); | ||
assert.equal(response.status, 301); | ||
assert.equal(response.headers.get('location'), '/new-page'); | ||
}); | ||
|
||
it('should redirect with custom 301 status', async () => { | ||
const response = await fetchEndpoint('old-page-301'); | ||
assert.equal(response.status, 301); | ||
assert.equal(response.headers.get('location'), '/new-page-301'); | ||
}); | ||
|
||
it('should redirect with custom 302 status', async () => { | ||
const response = await fetchEndpoint('old-page-302'); | ||
assert.equal(response.status, 302); | ||
assert.equal(response.headers.get('location'), '/new-page-302'); | ||
}); | ||
|
||
it('should handle dynamic redirects with parameters', async () => { | ||
const response = await fetchEndpoint('dynamic/test-slug'); | ||
assert.equal(response.status, 301); | ||
assert.equal(response.headers.get('location'), '/pages/test-slug'); | ||
}); | ||
|
||
it('should handle spread redirects with parameters', async () => { | ||
const response = await fetchEndpoint('spread/some/nested/path'); | ||
assert.equal(response.status, 301); | ||
assert.equal(response.headers.get('location'), '/content/some/nested/path'); | ||
}); | ||
|
||
it('should redirect to external URL', async () => { | ||
const response = await fetchEndpoint('external'); | ||
assert.equal(response.status, 301); | ||
assert.equal(response.headers.get('location'), 'https://example.com/'); | ||
}); | ||
}); |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.