Allow redirects in static mode
This commit is contained in:
parent
46e726960f
commit
ef3ea942cc
9 changed files with 129 additions and 9 deletions
|
@ -1724,6 +1724,7 @@ export interface RouteData {
|
|||
segments: RoutePart[][];
|
||||
type: RouteType;
|
||||
prerender: boolean;
|
||||
redirect?: string;
|
||||
}
|
||||
|
||||
export type SerializedRouteData = Omit<RouteData, 'generate' | 'pattern'> & {
|
||||
|
|
|
@ -522,9 +522,10 @@ async function generatePath(
|
|||
case 302: {
|
||||
const location = response.headers.get("location");
|
||||
if(!location) {
|
||||
redirectWithNoLocation();
|
||||
return void redirectWithNoLocation();
|
||||
}
|
||||
body = `<!doctype html><meta http-equiv="refresh" content="0;url=${location}" />`
|
||||
body = `<!doctype html><meta http-equiv="refresh" content="0;url=${location}" />`;
|
||||
pageData.route.redirect = location;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
export { netlifyEdgeFunctions } from './integration-edge-functions.js';
|
||||
export { netlifyFunctions as default, netlifyFunctions } from './integration-functions.js';
|
||||
export { netlifyStatic } from './integration-static.js';
|
||||
|
|
28
packages/integrations/netlify/src/integration-static.ts
Normal file
28
packages/integrations/netlify/src/integration-static.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
import type { AstroAdapter, AstroConfig, AstroIntegration, RouteData } from 'astro';
|
||||
import type { Args } from './netlify-functions.js';
|
||||
import { createRedirects } from './shared.js';
|
||||
|
||||
export function netlifyStatic(): AstroIntegration {
|
||||
let _config: any;
|
||||
return {
|
||||
name: '@astrojs/netlify',
|
||||
hooks: {
|
||||
'astro:config:done': ({ config }) => {
|
||||
_config = config;
|
||||
},
|
||||
// 'astro:config:setup': ({ config, updateConfig }) => {
|
||||
// const outDir = dist ?? new URL('./dist/', config.root);
|
||||
// updateConfig({
|
||||
// outDir,
|
||||
// build: {
|
||||
// client: outDir,
|
||||
// server: new URL('./.netlify/functions-internal/', config.root),
|
||||
// },
|
||||
// });
|
||||
// },
|
||||
'astro:build:done': async ({ dir, routes }) => {
|
||||
await createRedirects(_config, routes, dir, '', 'static');
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
|
@ -1,12 +1,12 @@
|
|||
import type { AstroConfig, RouteData } from 'astro';
|
||||
import fs from 'fs';
|
||||
|
||||
type RedirectDefinition = {
|
||||
export type RedirectDefinition = {
|
||||
dynamic: boolean;
|
||||
input: string;
|
||||
target: string;
|
||||
weight: 0 | 1;
|
||||
status: 200 | 404;
|
||||
status: 200 | 404 | 301;
|
||||
};
|
||||
|
||||
export async function createRedirects(
|
||||
|
@ -14,7 +14,7 @@ export async function createRedirects(
|
|||
routes: RouteData[],
|
||||
dir: URL,
|
||||
entryFile: string,
|
||||
type: 'functions' | 'edge-functions' | 'builders'
|
||||
type: 'functions' | 'edge-functions' | 'builders' | 'static'
|
||||
) {
|
||||
const _redirectsURL = new URL('./_redirects', dir);
|
||||
const kind = type ?? 'functions';
|
||||
|
@ -23,7 +23,19 @@ export async function createRedirects(
|
|||
|
||||
for (const route of routes) {
|
||||
if (route.pathname) {
|
||||
if (route.distURL) {
|
||||
if( kind === 'static') {
|
||||
if(route.redirect) {
|
||||
definitions.push({
|
||||
dynamic: false,
|
||||
input: route.pathname,
|
||||
target: route.redirect,
|
||||
status: 301,
|
||||
weight: 1
|
||||
});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (route.distURL) {
|
||||
definitions.push({
|
||||
dynamic: false,
|
||||
input: route.pathname,
|
||||
|
@ -68,7 +80,19 @@ export async function createRedirects(
|
|||
})
|
||||
.join('/');
|
||||
|
||||
if (route.distURL) {
|
||||
if(kind === 'static') {
|
||||
if(route.redirect) {
|
||||
definitions.push({
|
||||
dynamic: true,
|
||||
input: pattern,
|
||||
target: route.redirect,
|
||||
status: 301,
|
||||
weight: 1
|
||||
});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (route.distURL) {
|
||||
const target =
|
||||
`${pattern}` + (config.build.format === 'directory' ? '/index.html' : '.html');
|
||||
definitions.push({
|
||||
|
@ -99,8 +123,8 @@ export async function createRedirects(
|
|||
}
|
||||
|
||||
function prettify(definitions: RedirectDefinition[]) {
|
||||
let minInputLength = 0,
|
||||
minTargetLength = 0;
|
||||
let minInputLength = 4,
|
||||
minTargetLength = 4;
|
||||
definitions.sort((a, b) => {
|
||||
// Find the longest input, so we can format things nicely
|
||||
if (a.input.length > minInputLength) {
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<html>
|
||||
<head><title>Testing</title></head>
|
||||
<body>
|
||||
<h1>Testing</h1>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
return Astro.redirect('/');
|
||||
---
|
27
packages/integrations/netlify/test/static/redirects.test.js
Normal file
27
packages/integrations/netlify/test/static/redirects.test.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
import { expect } from 'chai';
|
||||
import { load as cheerioLoad } from 'cheerio';
|
||||
import { loadFixture, testIntegration } from './test-utils.js';
|
||||
import { netlifyStatic } from '../../dist/index.js';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
describe('SSG - Redirects', () => {
|
||||
/** @type {import('../../../astro/test/test-utils').Fixture} */
|
||||
let fixture;
|
||||
|
||||
before(async () => {
|
||||
fixture = await loadFixture({
|
||||
root: new URL('./fixtures/redirects/', import.meta.url).toString(),
|
||||
output: 'static',
|
||||
adapter: netlifyStatic(),
|
||||
site: `http://example.com`,
|
||||
integrations: [testIntegration()],
|
||||
});
|
||||
await fixture.build();
|
||||
});
|
||||
|
||||
it('Creates a redirects file', async () => {
|
||||
let redirects = await fixture.readFile('/_redirects');
|
||||
let parts = redirects.split(/\s+/);
|
||||
expect(parts).to.deep.equal(['/nope', '/', '301']);
|
||||
});
|
||||
});
|
29
packages/integrations/netlify/test/static/test-utils.js
Normal file
29
packages/integrations/netlify/test/static/test-utils.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
// @ts-check
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
export * from '../../../../astro/test/test-utils.js';
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns {import('../../../../astro/dist/types/@types/astro').AstroIntegration}
|
||||
*/
|
||||
export function testIntegration() {
|
||||
return {
|
||||
name: '@astrojs/netlify/test-integration',
|
||||
hooks: {
|
||||
'astro:config:setup': ({ updateConfig }) => {
|
||||
updateConfig({
|
||||
vite: {
|
||||
resolve: {
|
||||
alias: {
|
||||
'@astrojs/netlify/netlify-functions.js': fileURLToPath(
|
||||
new URL('../../dist/netlify-functions.js', import.meta.url)
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue