Skip to content

Commit

Permalink
Refactor into separate middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
ascorbic committed Jan 16, 2025
1 parent f8e74c1 commit 20da681
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 29 deletions.
9 changes: 9 additions & 0 deletions packages/astro/src/template/4xx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,12 @@ export function trailingSlashMismatchTemplate(pathname: string, trailingSlash: '
<p>Come to our <a href="https://astro.build/chat">Discord</a> if you need help.</p>`,
});
}

export function notFoundTemplate(pathname: string, message = 'Not found') {
return template({
pathname,
statusCode: 404,
title: message,
tabTitle: `404: ${message}`,
});
}
33 changes: 4 additions & 29 deletions packages/astro/src/vite-plugin-astro-server/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,11 @@ import type { AstroSettings } from '../types/astro.js';

import * as fs from 'node:fs';
import path from 'node:path';
import {
appendForwardSlash,
collapseDuplicateTrailingSlashes,
hasFileExtension,
} from '@astrojs/internal-helpers/path';
import { bold } from 'kleur/colors';
import type { Logger } from '../core/logger/core.js';
import notFoundTemplate, {
subpathNotUsedTemplate,
trailingSlashMismatchTemplate,
} from '../template/4xx.js';
import { writeHtmlResponse, writeRedirectResponse } from './response.js';
import { notFoundTemplate, subpathNotUsedTemplate } from '../template/4xx.js';
import { writeHtmlResponse } from './response.js';
import { appendForwardSlash } from '@astrojs/internal-helpers/path';

export function baseMiddleware(
settings: AstroSettings,
Expand All @@ -25,14 +18,9 @@ export function baseMiddleware(
const devRootURL = new URL(config.base, 'http://localhost');
const devRoot = site ? site.pathname : devRootURL.pathname;
const devRootReplacement = devRoot.endsWith('/') ? '/' : '';
const { trailingSlash } = settings.config;

return function devBaseMiddleware(req, res, next) {
const url = req.url!;
const destination = collapseDuplicateTrailingSlashes(url, true);
if (url && destination !== url) {
return writeRedirectResponse(res, 301, destination);
}
let pathname: string;
try {
pathname = decodeURI(new URL(url, 'http://localhost').pathname);
Expand All @@ -41,14 +29,6 @@ export function baseMiddleware(
return next(e);
}

if (
(trailingSlash === 'never' && pathname.endsWith('/')) ||
(trailingSlash === 'always' && !pathname.endsWith('/') && !hasFileExtension(pathname))
) {
const html = trailingSlashMismatchTemplate(pathname, trailingSlash);
return writeHtmlResponse(res, 404, html);
}

if (pathname.startsWith(devRoot)) {
req.url = url.replace(devRoot, devRootReplacement);
return next();
Expand All @@ -60,12 +40,7 @@ export function baseMiddleware(
}

if (req.headers.accept?.includes('text/html')) {
const html = notFoundTemplate({
statusCode: 404,
title: 'Not found',
tabTitle: '404: Not Found',
pathname,
});
const html = notFoundTemplate(pathname, 'Not Found');
return writeHtmlResponse(res, 404, html);
}

Expand Down
5 changes: 5 additions & 0 deletions packages/astro/src/vite-plugin-astro-server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { recordServerError } from './error.js';
import { DevPipeline } from './pipeline.js';
import { handleRequest } from './request.js';
import { setRouteError } from './server-state.js';
import { trailingSlashMiddleware } from './trailing-slash.js';

export interface AstroPluginOptions {
settings: AstroSettings;
Expand Down Expand Up @@ -119,6 +120,10 @@ export default function createVitePluginAstroServer({
route: '',
handle: baseMiddleware(settings, logger),
});
viteServer.middlewares.stack.unshift({
route: '',
handle: trailingSlashMiddleware(settings),
});
// Note that this function has a name so other middleware can find it.
viteServer.middlewares.use(async function astroDevHandler(request, response) {
if (request.url === undefined || !request.method) {
Expand Down
34 changes: 34 additions & 0 deletions packages/astro/src/vite-plugin-astro-server/trailing-slash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import type * as vite from 'vite';
import type { AstroSettings } from '../types/astro.js';

import { collapseDuplicateTrailingSlashes, hasFileExtension } from '@astrojs/internal-helpers/path';
import { trailingSlashMismatchTemplate } from '../template/4xx.js';
import { writeHtmlResponse, writeRedirectResponse } from './response.js';

export function trailingSlashMiddleware(settings: AstroSettings): vite.Connect.NextHandleFunction {
const { trailingSlash } = settings.config;

return function devTrailingSlash(req, res, next) {
const url = req.url!;
const destination = collapseDuplicateTrailingSlashes(url, true);
if (url && destination !== url) {
console.log({url, destination});

Check warning on line 15 in packages/astro/src/vite-plugin-astro-server/trailing-slash.ts

View workflow job for this annotation

GitHub Actions / Lint

lint/suspicious/noConsoleLog

Don't use console.log
return writeRedirectResponse(res, 301, destination);
}
let pathname: string;
try {
pathname = decodeURI(new URL(url, 'http://localhost').pathname);
} catch (e) {
/* malformed uri */
return next(e);
}
if (
(trailingSlash === 'never' && pathname.endsWith('/') && pathname !== '/') ||
(trailingSlash === 'always' && !pathname.endsWith('/') && !hasFileExtension(pathname))
) {
const html = trailingSlashMismatchTemplate(pathname, trailingSlash);
return writeHtmlResponse(res, 404, html);
}
return next();
};
}

0 comments on commit 20da681

Please sign in to comment.