mirror of
https://github.com/withastro/astro.git
synced 2025-01-27 22:19:04 -05:00
Replace send
with sirv
(#2713)
* remove send * Create thick-ravens-chew.md * I feel like I'm going to screw something up * working finally! * rewrite req.url * Add tiny bit of doc * Update .gitignore Co-authored-by: Evan Boehs <evan@boehs.org>
This commit is contained in:
parent
fbf2431f51
commit
556e51eecc
4 changed files with 27 additions and 67 deletions
5
.changeset/thick-ravens-chew.md
Normal file
5
.changeset/thick-ravens-chew.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
"astro": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Replace `send` dependency with `sirv`
|
0
comp.txt
0
comp.txt
|
@ -95,7 +95,7 @@
|
||||||
"resolve": "^1.20.0",
|
"resolve": "^1.20.0",
|
||||||
"rollup": "^2.64.0",
|
"rollup": "^2.64.0",
|
||||||
"semver": "^7.3.5",
|
"semver": "^7.3.5",
|
||||||
"send": "^0.17.1",
|
"sirv": "^2.0.2",
|
||||||
"serialize-javascript": "^6.0.0",
|
"serialize-javascript": "^6.0.0",
|
||||||
"shiki": "^0.10.0",
|
"shiki": "^0.10.0",
|
||||||
"shorthash": "^0.0.2",
|
"shorthash": "^0.0.2",
|
||||||
|
@ -125,7 +125,6 @@
|
||||||
"@types/parse5": "^6.0.3",
|
"@types/parse5": "^6.0.3",
|
||||||
"@types/resolve": "^1.20.1",
|
"@types/resolve": "^1.20.1",
|
||||||
"@types/rimraf": "^3.0.2",
|
"@types/rimraf": "^3.0.2",
|
||||||
"@types/send": "^0.17.1",
|
|
||||||
"@types/yargs-parser": "^20.2.1",
|
"@types/yargs-parser": "^20.2.1",
|
||||||
"astro-scripts": "workspace:*",
|
"astro-scripts": "workspace:*",
|
||||||
"chai": "^4.3.4",
|
"chai": "^4.3.4",
|
||||||
|
|
|
@ -1,17 +1,14 @@
|
||||||
import type { AstroConfig } from '../../@types/astro';
|
import type { AstroConfig } from '../../@types/astro';
|
||||||
import type { LogOptions } from '../logger';
|
import type { LogOptions } from '../logger';
|
||||||
import type { Stats } from 'fs';
|
|
||||||
import type { AddressInfo } from 'net';
|
import type { AddressInfo } from 'net';
|
||||||
|
|
||||||
import http from 'http';
|
import http from 'http';
|
||||||
|
import sirv from 'sirv';
|
||||||
import { performance } from 'perf_hooks';
|
import { performance } from 'perf_hooks';
|
||||||
import send from 'send';
|
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
import fs from 'fs';
|
|
||||||
import * as msg from '../messages.js';
|
import * as msg from '../messages.js';
|
||||||
import { error, info } from '../logger.js';
|
import { error, info } from '../logger.js';
|
||||||
import { subpathNotUsedTemplate, notFoundTemplate, default as template } from '../../template/4xx.js';
|
import { subpathNotUsedTemplate, notFoundTemplate } from '../../template/4xx.js';
|
||||||
import { appendForwardSlash, trimSlashes } from '../path.js';
|
|
||||||
import { getLocalAddress } from '../dev/util.js';
|
import { getLocalAddress } from '../dev/util.js';
|
||||||
|
|
||||||
interface PreviewOptions {
|
interface PreviewOptions {
|
||||||
|
@ -28,22 +25,8 @@ export interface PreviewServer {
|
||||||
/** The primary dev action */
|
/** The primary dev action */
|
||||||
export default async function preview(config: AstroConfig, { logging }: PreviewOptions): Promise<PreviewServer> {
|
export default async function preview(config: AstroConfig, { logging }: PreviewOptions): Promise<PreviewServer> {
|
||||||
const startServerTime = performance.now();
|
const startServerTime = performance.now();
|
||||||
const pageUrlFormat = config.buildOptions.pageUrlFormat;
|
|
||||||
const trailingSlash = config.devOptions.trailingSlash;
|
|
||||||
const forceTrailingSlash = trailingSlash === 'always';
|
|
||||||
const blockTrailingSlash = trailingSlash === 'never';
|
|
||||||
|
|
||||||
/** Default file served from a directory. */
|
|
||||||
const defaultFile = 'index.html';
|
|
||||||
|
|
||||||
const defaultOrigin = 'http://localhost';
|
const defaultOrigin = 'http://localhost';
|
||||||
|
const trailingSlash = config.devOptions.trailingSlash
|
||||||
const sendOptions = {
|
|
||||||
extensions: pageUrlFormat === 'file' ? ['html'] : false,
|
|
||||||
index: false,
|
|
||||||
root: fileURLToPath(config.dist),
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Base request URL. */
|
/** Base request URL. */
|
||||||
let baseURL = new URL(config.buildOptions.site || '/', defaultOrigin);
|
let baseURL = new URL(config.buildOptions.site || '/', defaultOrigin);
|
||||||
|
|
||||||
|
@ -64,55 +47,28 @@ export default async function preview(config: AstroConfig, { logging }: PreviewO
|
||||||
const isRoot = pathname === '/';
|
const isRoot = pathname === '/';
|
||||||
const hasTrailingSlash = isRoot || pathname.endsWith('/');
|
const hasTrailingSlash = isRoot || pathname.endsWith('/');
|
||||||
|
|
||||||
let tryTrailingSlash = true;
|
function err(message: string) {
|
||||||
let tryHtmlExtension = true;
|
|
||||||
|
|
||||||
let url: URL;
|
|
||||||
|
|
||||||
const onErr = (message: string) => {
|
|
||||||
res.statusCode = 404;
|
res.statusCode = 404;
|
||||||
res.end(notFoundTemplate(pathname, message));
|
res.end(notFoundTemplate(pathname, message));
|
||||||
};
|
};
|
||||||
|
|
||||||
const onStat = (err: NodeJS.ErrnoException | null, stat: Stats) => {
|
switch(true) {
|
||||||
switch (true) {
|
case hasTrailingSlash && trailingSlash == 'never' && !isRoot:
|
||||||
// retry nonexistent paths without an html extension
|
err('Prohibited trailing slash');
|
||||||
case err && tryHtmlExtension && hasTrailingSlash && !blockTrailingSlash:
|
break;
|
||||||
case err && tryHtmlExtension && !hasTrailingSlash && !forceTrailingSlash && !pathname.endsWith('.html'):
|
case !hasTrailingSlash && trailingSlash == 'always' && !isRoot:
|
||||||
tryHtmlExtension = false;
|
err('Required trailing slash');
|
||||||
return fs.stat((url = new URL(url.pathname + '.html', url)), onStat);
|
break;
|
||||||
|
default: {
|
||||||
// 404 on nonexistent paths (that are yet handled)
|
// HACK: rewrite req.url so that sirv finds the file
|
||||||
case err !== null:
|
req.url = '/' + req.url?.replace(baseURL.pathname,'')
|
||||||
return onErr('Path not found');
|
sirv(fileURLToPath(config.dist), {
|
||||||
|
maxAge: 0,
|
||||||
// 404 on directories when a trailing slash is present but blocked
|
onNoMatch: () => {
|
||||||
case stat.isDirectory() && hasTrailingSlash && blockTrailingSlash && !isRoot:
|
err('Path not found')
|
||||||
return onErr('Prohibited trailing slash');
|
}
|
||||||
|
})(req,res)
|
||||||
// 404 on directories when a trailing slash is missing but forced
|
}}
|
||||||
case stat.isDirectory() && !hasTrailingSlash && forceTrailingSlash && !isRoot:
|
|
||||||
return onErr('Required trailing slash');
|
|
||||||
|
|
||||||
// retry on directories when a default file is missing but allowed (that are yet handled)
|
|
||||||
case stat.isDirectory() && tryTrailingSlash:
|
|
||||||
tryTrailingSlash = false;
|
|
||||||
return fs.stat((url = new URL(url.pathname + (url.pathname.endsWith('/') ? defaultFile : '/' + defaultFile), url)), onStat);
|
|
||||||
|
|
||||||
// 404 on existent directories (that are yet handled)
|
|
||||||
case stat.isDirectory():
|
|
||||||
return onErr('Path not found');
|
|
||||||
|
|
||||||
// handle existent paths
|
|
||||||
default:
|
|
||||||
send(req, fileURLToPath(url), {
|
|
||||||
extensions: false,
|
|
||||||
index: false,
|
|
||||||
}).pipe(res);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
fs.stat((url = new URL(trimSlashes(pathname), config.dist)), onStat);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let { hostname, port } = config.devOptions;
|
let { hostname, port } = config.devOptions;
|
||||||
|
|
Loading…
Add table
Reference in a new issue