Fix redirects in dev mode (#7342)
* Fix redirects in dev mode * Adding a changeset
This commit is contained in:
parent
3d9a392a09
commit
bbcf69e7b8
4 changed files with 109 additions and 54 deletions
5
.changeset/swift-flies-press.md
Normal file
5
.changeset/swift-flies-press.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Fix for experimental redirects in dev mode
|
|
@ -161,7 +161,7 @@ function isRedirect(statusCode: number) {
|
|||
}
|
||||
|
||||
export function throwIfRedirectNotAllowed(response: Response, config: AstroConfig) {
|
||||
if (!isServerLikeOutput(config) && isRedirect(response.status)) {
|
||||
if (!isServerLikeOutput(config) && isRedirect(response.status) && !config.experimental.redirects) {
|
||||
throw new AstroError(AstroErrorData.StaticRedirectNotAvailable);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import type { AstroSettings, RouteData } from '../@types/astro';
|
||||
import { preload, type DevelopmentEnvironment } from '../core/render/dev/index.js';
|
||||
import { preload, type DevelopmentEnvironment, type ComponentPreload } from '../core/render/dev/index.js';
|
||||
import { getPrerenderStatus } from './metadata.js';
|
||||
import { routeIsRedirect, RedirectComponentInstance } from '../core/redirects/index.js';
|
||||
|
||||
type GetSortedPreloadedMatchesParams = {
|
||||
env: DevelopmentEnvironment;
|
||||
|
@ -26,14 +27,31 @@ type PreloadAndSetPrerenderStatusParams = {
|
|||
matches: RouteData[];
|
||||
settings: AstroSettings;
|
||||
};
|
||||
|
||||
type PreloadAndSetPrerenderStatusResult = {
|
||||
filePath: URL;
|
||||
route: RouteData;
|
||||
preloadedComponent: ComponentPreload;
|
||||
};
|
||||
|
||||
async function preloadAndSetPrerenderStatus({
|
||||
env,
|
||||
matches,
|
||||
settings,
|
||||
}: PreloadAndSetPrerenderStatusParams) {
|
||||
}: PreloadAndSetPrerenderStatusParams): Promise<PreloadAndSetPrerenderStatusResult[]> {
|
||||
const preloaded = await Promise.all(
|
||||
matches.map(async (route) => {
|
||||
const filePath = new URL(`./${route.component}`, settings.config.root);
|
||||
|
||||
if(routeIsRedirect(route)) {
|
||||
const preloadedComponent: ComponentPreload = [[], RedirectComponentInstance];
|
||||
return {
|
||||
preloadedComponent,
|
||||
route,
|
||||
filePath
|
||||
};
|
||||
}
|
||||
|
||||
const preloadedComponent = await preload({ env, filePath });
|
||||
|
||||
// gets the prerender metadata set by the `astro:scanner` vite plugin
|
||||
|
@ -46,7 +64,7 @@ async function preloadAndSetPrerenderStatus({
|
|||
route.prerender = prerenderStatus;
|
||||
}
|
||||
|
||||
return { preloadedComponent, route, filePath } as const;
|
||||
return { preloadedComponent, route, filePath };
|
||||
})
|
||||
);
|
||||
return preloaded;
|
||||
|
|
|
@ -65,61 +65,93 @@ describe('Astro.redirect', () => {
|
|||
});
|
||||
|
||||
describe('output: "static"', () => {
|
||||
before(async () => {
|
||||
process.env.STATIC_MODE = true;
|
||||
fixture = await loadFixture({
|
||||
root: './fixtures/ssr-redirect/',
|
||||
output: 'static',
|
||||
experimental: {
|
||||
redirects: true,
|
||||
},
|
||||
redirects: {
|
||||
'/one': '/',
|
||||
'/two': '/',
|
||||
'/blog/[...slug]': '/articles/[...slug]',
|
||||
'/three': {
|
||||
status: 302,
|
||||
destination: '/',
|
||||
describe('build', () => {
|
||||
before(async () => {
|
||||
process.env.STATIC_MODE = true;
|
||||
fixture = await loadFixture({
|
||||
root: './fixtures/ssr-redirect/',
|
||||
output: 'static',
|
||||
experimental: {
|
||||
redirects: true,
|
||||
},
|
||||
},
|
||||
redirects: {
|
||||
'/one': '/',
|
||||
'/two': '/',
|
||||
'/blog/[...slug]': '/articles/[...slug]',
|
||||
'/three': {
|
||||
status: 302,
|
||||
destination: '/',
|
||||
},
|
||||
},
|
||||
});
|
||||
await fixture.build();
|
||||
});
|
||||
|
||||
it('Includes the meta refresh tag in Astro.redirect pages', async () => {
|
||||
const html = await fixture.readFile('/secret/index.html');
|
||||
expect(html).to.include('http-equiv="refresh');
|
||||
expect(html).to.include('url=/login');
|
||||
});
|
||||
|
||||
it('Includes the meta refresh tag in `redirect` config pages', async () => {
|
||||
let html = await fixture.readFile('/one/index.html');
|
||||
expect(html).to.include('http-equiv="refresh');
|
||||
expect(html).to.include('url=/');
|
||||
|
||||
html = await fixture.readFile('/two/index.html');
|
||||
expect(html).to.include('http-equiv="refresh');
|
||||
expect(html).to.include('url=/');
|
||||
|
||||
html = await fixture.readFile('/three/index.html');
|
||||
expect(html).to.include('http-equiv="refresh');
|
||||
expect(html).to.include('url=/');
|
||||
});
|
||||
|
||||
it('Generates page for dynamic routes', async () => {
|
||||
let html = await fixture.readFile('/blog/one/index.html');
|
||||
expect(html).to.include('http-equiv="refresh');
|
||||
expect(html).to.include('url=/articles/one');
|
||||
|
||||
html = await fixture.readFile('/blog/two/index.html');
|
||||
expect(html).to.include('http-equiv="refresh');
|
||||
expect(html).to.include('url=/articles/two');
|
||||
});
|
||||
|
||||
it('Generates redirect pages for redirects created by middleware', async () => {
|
||||
let html = await fixture.readFile('/middleware-redirect/index.html');
|
||||
expect(html).to.include('http-equiv="refresh');
|
||||
expect(html).to.include('url=/');
|
||||
});
|
||||
await fixture.build();
|
||||
});
|
||||
|
||||
it('Includes the meta refresh tag in Astro.redirect pages', async () => {
|
||||
const html = await fixture.readFile('/secret/index.html');
|
||||
expect(html).to.include('http-equiv="refresh');
|
||||
expect(html).to.include('url=/login');
|
||||
});
|
||||
describe('dev', () => {
|
||||
/** @type {import('./test-utils.js').DevServer} */
|
||||
let devServer;
|
||||
before(async () => {
|
||||
process.env.STATIC_MODE = true;
|
||||
fixture = await loadFixture({
|
||||
root: './fixtures/ssr-redirect/',
|
||||
output: 'static',
|
||||
experimental: {
|
||||
redirects: true,
|
||||
},
|
||||
redirects: {
|
||||
'/one': '/',
|
||||
},
|
||||
});
|
||||
devServer = await fixture.startDevServer();
|
||||
});
|
||||
|
||||
it('Includes the meta refresh tag in `redirect` config pages', async () => {
|
||||
let html = await fixture.readFile('/one/index.html');
|
||||
expect(html).to.include('http-equiv="refresh');
|
||||
expect(html).to.include('url=/');
|
||||
|
||||
html = await fixture.readFile('/two/index.html');
|
||||
expect(html).to.include('http-equiv="refresh');
|
||||
expect(html).to.include('url=/');
|
||||
|
||||
html = await fixture.readFile('/three/index.html');
|
||||
expect(html).to.include('http-equiv="refresh');
|
||||
expect(html).to.include('url=/');
|
||||
});
|
||||
|
||||
it('Generates page for dynamic routes', async () => {
|
||||
let html = await fixture.readFile('/blog/one/index.html');
|
||||
expect(html).to.include('http-equiv="refresh');
|
||||
expect(html).to.include('url=/articles/one');
|
||||
|
||||
html = await fixture.readFile('/blog/two/index.html');
|
||||
expect(html).to.include('http-equiv="refresh');
|
||||
expect(html).to.include('url=/articles/two');
|
||||
});
|
||||
|
||||
it('Generates redirect pages for redirects created by middleware', async () => {
|
||||
let html = await fixture.readFile('/middleware-redirect/index.html');
|
||||
expect(html).to.include('http-equiv="refresh');
|
||||
expect(html).to.include('url=/');
|
||||
after(async () => {
|
||||
await devServer.stop();
|
||||
});
|
||||
|
||||
it('Returns 301', async () => {
|
||||
let res = await fixture.fetch('/one', {
|
||||
redirect: 'manual'
|
||||
});
|
||||
expect(res.status).to.equal(301);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in a new issue