Remove experimental flag for redirects config (#7686)
* Remove experimental flag for redirects config * Remove experimental from tests * Remove experimental CLI flag * Add changeset * Removing redirect test that is no longer relevant * Remove experimental label" * Update .changeset/dry-beers-grow.md Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca> * Update .changeset/dry-beers-grow.md Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca> * Remove old function --------- Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
This commit is contained in:
parent
659b2b034c
commit
ec745d689a
14 changed files with 20 additions and 98 deletions
15
.changeset/dry-beers-grow.md
Normal file
15
.changeset/dry-beers-grow.md
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
---
|
||||||
|
'astro': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Redirects configuration
|
||||||
|
|
||||||
|
This change moves the `redirects` configuration out of experimental. If you were previously using experimental redirects, remove the following experimental flag:
|
||||||
|
|
||||||
|
```js
|
||||||
|
experimental: {
|
||||||
|
redirects: true,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you have been waiting for stabilization before using redirects, now you can do so. Check out [the docs on redirects](https://docs.astro.build/en/core-concepts/routing/#redirects) to learn how to use this built-in feature.
|
|
@ -108,7 +108,6 @@ export interface CLIFlags {
|
||||||
drafts?: boolean;
|
drafts?: boolean;
|
||||||
open?: boolean;
|
open?: boolean;
|
||||||
experimentalAssets?: boolean;
|
experimentalAssets?: boolean;
|
||||||
experimentalRedirects?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -455,10 +454,10 @@ export interface AstroUserConfig {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @docs
|
* @docs
|
||||||
* @name redirects (Experimental)
|
* @name redirects
|
||||||
* @type {Record<string, RedirectConfig>}
|
* @type {Record<string, RedirectConfig>}
|
||||||
* @default `{}`
|
* @default `{}`
|
||||||
* @version 2.6.0
|
* @version 2.9.0
|
||||||
* @description Specify a mapping of redirects where the key is the route to match
|
* @description Specify a mapping of redirects where the key is the route to match
|
||||||
* and the value is the path to redirect to.
|
* and the value is the path to redirect to.
|
||||||
*
|
*
|
||||||
|
@ -1228,27 +1227,6 @@ export interface AstroUserConfig {
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
assets?: boolean;
|
assets?: boolean;
|
||||||
|
|
||||||
/**
|
|
||||||
* @docs
|
|
||||||
* @name experimental.redirects
|
|
||||||
* @type {boolean}
|
|
||||||
* @default `false`
|
|
||||||
* @version 2.6.0
|
|
||||||
* @description
|
|
||||||
* Enable experimental support for redirect configuration. With this enabled
|
|
||||||
* you can set redirects via the top-level `redirects` property. To enable
|
|
||||||
* this feature, set `experimental.redirects` to `true`.
|
|
||||||
*
|
|
||||||
* ```js
|
|
||||||
* {
|
|
||||||
* experimental: {
|
|
||||||
* redirects: true,
|
|
||||||
* },
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
redirects?: boolean;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Legacy options to be removed
|
// Legacy options to be removed
|
||||||
|
|
|
@ -37,13 +37,12 @@ import {
|
||||||
import { runHookBuildGenerated } from '../../integrations/index.js';
|
import { runHookBuildGenerated } from '../../integrations/index.js';
|
||||||
import { isServerLikeOutput } from '../../prerender/utils.js';
|
import { isServerLikeOutput } from '../../prerender/utils.js';
|
||||||
import { BEFORE_HYDRATION_SCRIPT_ID, PAGE_SCRIPT_ID } from '../../vite-plugin-scripts/index.js';
|
import { BEFORE_HYDRATION_SCRIPT_ID, PAGE_SCRIPT_ID } from '../../vite-plugin-scripts/index.js';
|
||||||
import { callEndpoint, throwIfRedirectNotAllowed } from '../endpoint/index.js';
|
import { callEndpoint } from '../endpoint/index.js';
|
||||||
import { AstroError, AstroErrorData } from '../errors/index.js';
|
import { AstroError, AstroErrorData } from '../errors/index.js';
|
||||||
import { debug, info } from '../logger/core.js';
|
import { debug, info } from '../logger/core.js';
|
||||||
import {
|
import {
|
||||||
getRedirectLocationOrThrow,
|
getRedirectLocationOrThrow,
|
||||||
RedirectSinglePageBuiltModule,
|
RedirectSinglePageBuiltModule,
|
||||||
routeIsRedirect,
|
|
||||||
} from '../redirects/index.js';
|
} from '../redirects/index.js';
|
||||||
import { createEnvironment, createRenderContext, tryRenderPage } from '../render/index.js';
|
import { createEnvironment, createRenderContext, tryRenderPage } from '../render/index.js';
|
||||||
import { callGetStaticPaths } from '../render/route-cache.js';
|
import { callGetStaticPaths } from '../render/route-cache.js';
|
||||||
|
@ -228,10 +227,6 @@ async function generatePage(
|
||||||
builtPaths: Set<string>,
|
builtPaths: Set<string>,
|
||||||
manifest: SSRManifest
|
manifest: SSRManifest
|
||||||
) {
|
) {
|
||||||
if (routeIsRedirect(pageData.route) && !opts.settings.config.experimental.redirects) {
|
|
||||||
throw new Error(`To use redirects first set experimental.redirects to \`true\``);
|
|
||||||
}
|
|
||||||
|
|
||||||
let timeStart = performance.now();
|
let timeStart = performance.now();
|
||||||
|
|
||||||
const pageInfo = getPageDataByComponent(internals, pageData.route.component);
|
const pageInfo = getPageDataByComponent(internals, pageData.route.component);
|
||||||
|
@ -561,7 +556,6 @@ async function generatePath(
|
||||||
);
|
);
|
||||||
|
|
||||||
if (result.type === 'response') {
|
if (result.type === 'response') {
|
||||||
throwIfRedirectNotAllowed(result.response, opts.settings.config);
|
|
||||||
// If there's no body, do nothing
|
// If there's no body, do nothing
|
||||||
if (!result.response.body) return;
|
if (!result.response.body) return;
|
||||||
const ab = await result.response.arrayBuffer();
|
const ab = await result.response.arrayBuffer();
|
||||||
|
|
|
@ -100,8 +100,6 @@ export function resolveFlags(flags: Partial<Flags>): CLIFlags {
|
||||||
drafts: typeof flags.drafts === 'boolean' ? flags.drafts : undefined,
|
drafts: typeof flags.drafts === 'boolean' ? flags.drafts : undefined,
|
||||||
experimentalAssets:
|
experimentalAssets:
|
||||||
typeof flags.experimentalAssets === 'boolean' ? flags.experimentalAssets : undefined,
|
typeof flags.experimentalAssets === 'boolean' ? flags.experimentalAssets : undefined,
|
||||||
experimentalRedirects:
|
|
||||||
typeof flags.experimentalRedirects === 'boolean' ? flags.experimentalRedirects : undefined,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,6 @@ const ASTRO_CONFIG_DEFAULTS = {
|
||||||
redirects: {},
|
redirects: {},
|
||||||
experimental: {
|
experimental: {
|
||||||
assets: false,
|
assets: false,
|
||||||
redirects: false,
|
|
||||||
},
|
},
|
||||||
} satisfies AstroUserConfig & { server: { open: boolean } };
|
} satisfies AstroUserConfig & { server: { open: boolean } };
|
||||||
|
|
||||||
|
@ -233,7 +232,6 @@ export const AstroConfigSchema = z.object({
|
||||||
experimental: z
|
experimental: z
|
||||||
.object({
|
.object({
|
||||||
assets: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.assets),
|
assets: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.assets),
|
||||||
redirects: z.boolean().optional().default(ASTRO_CONFIG_DEFAULTS.experimental.redirects),
|
|
||||||
})
|
})
|
||||||
.passthrough()
|
.passthrough()
|
||||||
.refine(
|
.refine(
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import type {
|
import type {
|
||||||
APIContext,
|
APIContext,
|
||||||
AstroConfig,
|
|
||||||
EndpointHandler,
|
EndpointHandler,
|
||||||
EndpointOutput,
|
EndpointOutput,
|
||||||
MiddlewareEndpointHandler,
|
MiddlewareEndpointHandler,
|
||||||
|
@ -9,7 +8,6 @@ import type {
|
||||||
} from '../../@types/astro';
|
} from '../../@types/astro';
|
||||||
import type { Environment, RenderContext } from '../render/index';
|
import type { Environment, RenderContext } from '../render/index';
|
||||||
|
|
||||||
import { isServerLikeOutput } from '../../prerender/utils.js';
|
|
||||||
import { renderEndpoint } from '../../runtime/server/index.js';
|
import { renderEndpoint } from '../../runtime/server/index.js';
|
||||||
import { ASTRO_VERSION } from '../constants.js';
|
import { ASTRO_VERSION } from '../constants.js';
|
||||||
import { AstroCookies, attachToResponse } from '../cookies/index.js';
|
import { AstroCookies, attachToResponse } from '../cookies/index.js';
|
||||||
|
@ -161,17 +159,3 @@ export async function callEndpoint<MiddlewareResult = Response | EndpointOutput>
|
||||||
cookies: context.cookies,
|
cookies: context.cookies,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function isRedirect(statusCode: number) {
|
|
||||||
return statusCode >= 300 && statusCode < 400;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function throwIfRedirectNotAllowed(response: Response, config: AstroConfig) {
|
|
||||||
if (
|
|
||||||
!isServerLikeOutput(config) &&
|
|
||||||
isRedirect(response.status) &&
|
|
||||||
!config.experimental.redirects
|
|
||||||
) {
|
|
||||||
throw new AstroError(AstroErrorData.StaticRedirectNotAvailable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ import type http from 'node:http';
|
||||||
import type { ComponentInstance, ManifestData, RouteData, SSRManifest } from '../@types/astro';
|
import type { ComponentInstance, ManifestData, RouteData, SSRManifest } from '../@types/astro';
|
||||||
import { attachToResponse } from '../core/cookies/index.js';
|
import { attachToResponse } from '../core/cookies/index.js';
|
||||||
import { call as callEndpoint } from '../core/endpoint/dev/index.js';
|
import { call as callEndpoint } from '../core/endpoint/dev/index.js';
|
||||||
import { throwIfRedirectNotAllowed } from '../core/endpoint/index.js';
|
|
||||||
import { AstroErrorData, isAstroError } from '../core/errors/index.js';
|
import { AstroErrorData, isAstroError } from '../core/errors/index.js';
|
||||||
import { warn } from '../core/logger/core.js';
|
import { warn } from '../core/logger/core.js';
|
||||||
import { loadMiddleware } from '../core/middleware/loadMiddleware.js';
|
import { loadMiddleware } from '../core/middleware/loadMiddleware.js';
|
||||||
|
@ -146,16 +145,6 @@ export async function handleRoute({
|
||||||
return handle404Response(origin, incomingRequest, incomingResponse);
|
return handle404Response(origin, incomingRequest, incomingResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matchedRoute.route.type === 'redirect' && !settings.config.experimental.redirects) {
|
|
||||||
writeWebResponse(
|
|
||||||
incomingResponse,
|
|
||||||
new Response(`To enable redirect set experimental.redirects to \`true\`.`, {
|
|
||||||
status: 400,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { config } = settings;
|
const { config } = settings;
|
||||||
const filePath: URL | undefined = matchedRoute.filePath;
|
const filePath: URL | undefined = matchedRoute.filePath;
|
||||||
const { route, preloadedComponent } = matchedRoute;
|
const { route, preloadedComponent } = matchedRoute;
|
||||||
|
@ -210,7 +199,6 @@ export async function handleRoute({
|
||||||
manifest,
|
manifest,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
throwIfRedirectNotAllowed(result.response, config);
|
|
||||||
await writeWebResponse(incomingResponse, result.response);
|
await writeWebResponse(incomingResponse, result.response);
|
||||||
} else {
|
} else {
|
||||||
let contentType = 'text/plain';
|
let contentType = 'text/plain';
|
||||||
|
@ -249,14 +237,13 @@ export async function handleRoute({
|
||||||
manifest,
|
manifest,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
throwIfRedirectNotAllowed(result, config);
|
|
||||||
|
|
||||||
let response = result;
|
let response = result;
|
||||||
// Response.status is read-only, so a clone is required to override
|
// Response.status is read-only, so a clone is required to override
|
||||||
if (status && response.status !== status) {
|
if (status && response.status !== status) {
|
||||||
response = new Response(result.body, { ...result, status });
|
response = new Response(result.body, { ...result, status });
|
||||||
}
|
}
|
||||||
return await writeSSRResult(request, response, incomingResponse);
|
await writeSSRResult(request, response, incomingResponse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,11 +43,6 @@ describe('Development Routing', () => {
|
||||||
const response = await fixture.fetch('/2');
|
const response = await fixture.fetch('/2');
|
||||||
expect(response.status).to.equal(404);
|
expect(response.status).to.equal(404);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('500 when redirecting in SSG mode', async () => {
|
|
||||||
const response = await fixture.fetch('/redirect');
|
|
||||||
expect(response.status).to.equal(500);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('No subpath used', () => {
|
describe('No subpath used', () => {
|
||||||
|
|
|
@ -15,9 +15,6 @@ describe('Astro.redirect', () => {
|
||||||
redirects: {
|
redirects: {
|
||||||
'/api/redirect': '/test',
|
'/api/redirect': '/test',
|
||||||
},
|
},
|
||||||
experimental: {
|
|
||||||
redirects: true,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
await fixture.build();
|
await fixture.build();
|
||||||
});
|
});
|
||||||
|
@ -71,9 +68,6 @@ describe('Astro.redirect', () => {
|
||||||
fixture = await loadFixture({
|
fixture = await loadFixture({
|
||||||
root: './fixtures/ssr-redirect/',
|
root: './fixtures/ssr-redirect/',
|
||||||
output: 'static',
|
output: 'static',
|
||||||
experimental: {
|
|
||||||
redirects: true,
|
|
||||||
},
|
|
||||||
redirects: {
|
redirects: {
|
||||||
'/': '/test',
|
'/': '/test',
|
||||||
'/one': '/test',
|
'/one': '/test',
|
||||||
|
@ -159,9 +153,6 @@ describe('Astro.redirect', () => {
|
||||||
fixture = await loadFixture({
|
fixture = await loadFixture({
|
||||||
root: './fixtures/ssr-redirect/',
|
root: './fixtures/ssr-redirect/',
|
||||||
output: 'static',
|
output: 'static',
|
||||||
experimental: {
|
|
||||||
redirects: true,
|
|
||||||
},
|
|
||||||
redirects: {
|
redirects: {
|
||||||
'/one': '/',
|
'/one': '/',
|
||||||
},
|
},
|
||||||
|
@ -194,9 +185,6 @@ describe('Astro.redirect', () => {
|
||||||
build: {
|
build: {
|
||||||
redirects: false,
|
redirects: false,
|
||||||
},
|
},
|
||||||
experimental: {
|
|
||||||
redirects: true,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
await fixture.build();
|
await fixture.build();
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,9 +14,6 @@ describe('mode: "directory"', () => {
|
||||||
redirects: {
|
redirects: {
|
||||||
'/old': '/',
|
'/old': '/',
|
||||||
},
|
},
|
||||||
experimental: {
|
|
||||||
redirects: true,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
await fixture.build();
|
await fixture.build();
|
||||||
});
|
});
|
||||||
|
|
|
@ -142,7 +142,7 @@ export default defineConfig({
|
||||||
|
|
||||||
### Static sites
|
### Static sites
|
||||||
|
|
||||||
For static sites you usually don't need an adapter. However, if you use `redirects` configuration (experimental) in your Astro config, the Netlify adapter can be used to translate this to the proper `_redirects` format.
|
For static sites you usually don't need an adapter. However, if you use `redirects` configuration in your Astro config, the Netlify adapter can be used to translate this to the proper `_redirects` format.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { defineConfig } from 'astro/config';
|
import { defineConfig } from 'astro/config';
|
||||||
|
@ -154,9 +154,6 @@ export default defineConfig({
|
||||||
redirects: {
|
redirects: {
|
||||||
'/blog/old-post': '/blog/new-post',
|
'/blog/old-post': '/blog/new-post',
|
||||||
},
|
},
|
||||||
experimental: {
|
|
||||||
redirects: true,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,6 @@ describe('SSG - Redirects', () => {
|
||||||
redirects: {
|
redirects: {
|
||||||
'/other': '/',
|
'/other': '/',
|
||||||
},
|
},
|
||||||
experimental: {
|
|
||||||
redirects: true,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
await fixture.build();
|
await fixture.build();
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,9 +11,6 @@ describe('SSG - Redirects', () => {
|
||||||
root: new URL('./fixtures/redirects/', import.meta.url).toString(),
|
root: new URL('./fixtures/redirects/', import.meta.url).toString(),
|
||||||
output: 'static',
|
output: 'static',
|
||||||
adapter: netlifyStatic(),
|
adapter: netlifyStatic(),
|
||||||
experimental: {
|
|
||||||
redirects: true,
|
|
||||||
},
|
|
||||||
site: `http://example.com`,
|
site: `http://example.com`,
|
||||||
integrations: [testIntegration()],
|
integrations: [testIntegration()],
|
||||||
redirects: {
|
redirects: {
|
||||||
|
|
|
@ -18,9 +18,6 @@ describe('Redirects', () => {
|
||||||
'/blog/[...slug]': '/team/articles/[...slug]',
|
'/blog/[...slug]': '/team/articles/[...slug]',
|
||||||
},
|
},
|
||||||
trailingSlash: 'always',
|
trailingSlash: 'always',
|
||||||
experimental: {
|
|
||||||
redirects: true,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
await fixture.build();
|
await fixture.build();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Reference in a new issue