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[][];
|
segments: RoutePart[][];
|
||||||
type: RouteType;
|
type: RouteType;
|
||||||
prerender: boolean;
|
prerender: boolean;
|
||||||
|
redirect?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type SerializedRouteData = Omit<RouteData, 'generate' | 'pattern'> & {
|
export type SerializedRouteData = Omit<RouteData, 'generate' | 'pattern'> & {
|
||||||
|
|
|
@ -522,9 +522,10 @@ async function generatePath(
|
||||||
case 302: {
|
case 302: {
|
||||||
const location = response.headers.get("location");
|
const location = response.headers.get("location");
|
||||||
if(!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;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
export { netlifyEdgeFunctions } from './integration-edge-functions.js';
|
export { netlifyEdgeFunctions } from './integration-edge-functions.js';
|
||||||
export { netlifyFunctions as default, netlifyFunctions } from './integration-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 type { AstroConfig, RouteData } from 'astro';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
|
||||||
type RedirectDefinition = {
|
export type RedirectDefinition = {
|
||||||
dynamic: boolean;
|
dynamic: boolean;
|
||||||
input: string;
|
input: string;
|
||||||
target: string;
|
target: string;
|
||||||
weight: 0 | 1;
|
weight: 0 | 1;
|
||||||
status: 200 | 404;
|
status: 200 | 404 | 301;
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function createRedirects(
|
export async function createRedirects(
|
||||||
|
@ -14,7 +14,7 @@ export async function createRedirects(
|
||||||
routes: RouteData[],
|
routes: RouteData[],
|
||||||
dir: URL,
|
dir: URL,
|
||||||
entryFile: string,
|
entryFile: string,
|
||||||
type: 'functions' | 'edge-functions' | 'builders'
|
type: 'functions' | 'edge-functions' | 'builders' | 'static'
|
||||||
) {
|
) {
|
||||||
const _redirectsURL = new URL('./_redirects', dir);
|
const _redirectsURL = new URL('./_redirects', dir);
|
||||||
const kind = type ?? 'functions';
|
const kind = type ?? 'functions';
|
||||||
|
@ -23,7 +23,19 @@ export async function createRedirects(
|
||||||
|
|
||||||
for (const route of routes) {
|
for (const route of routes) {
|
||||||
if (route.pathname) {
|
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({
|
definitions.push({
|
||||||
dynamic: false,
|
dynamic: false,
|
||||||
input: route.pathname,
|
input: route.pathname,
|
||||||
|
@ -68,7 +80,19 @@ export async function createRedirects(
|
||||||
})
|
})
|
||||||
.join('/');
|
.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 =
|
const target =
|
||||||
`${pattern}` + (config.build.format === 'directory' ? '/index.html' : '.html');
|
`${pattern}` + (config.build.format === 'directory' ? '/index.html' : '.html');
|
||||||
definitions.push({
|
definitions.push({
|
||||||
|
@ -99,8 +123,8 @@ export async function createRedirects(
|
||||||
}
|
}
|
||||||
|
|
||||||
function prettify(definitions: RedirectDefinition[]) {
|
function prettify(definitions: RedirectDefinition[]) {
|
||||||
let minInputLength = 0,
|
let minInputLength = 4,
|
||||||
minTargetLength = 0;
|
minTargetLength = 4;
|
||||||
definitions.sort((a, b) => {
|
definitions.sort((a, b) => {
|
||||||
// Find the longest input, so we can format things nicely
|
// Find the longest input, so we can format things nicely
|
||||||
if (a.input.length > minInputLength) {
|
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…
Add table
Reference in a new issue