From 97724da93ed7b1db19632c0cdb4b3aab1ff84812 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Mon, 10 Jun 2024 05:58:44 -0400 Subject: [PATCH] Let middleware handle the original request URL (#11211) * Let middleware handle the original request URL * Add a changeset --- .changeset/six-files-carry.md | 5 +++++ packages/astro/src/core/app/index.ts | 5 ----- .../src/vite-plugin-astro-server/request.ts | 4 ++-- .../fixtures/ssr-request/src/middleware.ts | 14 ++++++++++++++ packages/astro/test/ssr-request.test.js | 19 +++++++------------ 5 files changed, 28 insertions(+), 19 deletions(-) create mode 100644 .changeset/six-files-carry.md create mode 100644 packages/astro/test/fixtures/ssr-request/src/middleware.ts diff --git a/.changeset/six-files-carry.md b/.changeset/six-files-carry.md new file mode 100644 index 0000000000..c8d5ebca4b --- /dev/null +++ b/.changeset/six-files-carry.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Let middleware handle the original request URL diff --git a/packages/astro/src/core/app/index.ts b/packages/astro/src/core/app/index.ts index 5b94135783..098762852e 100644 --- a/packages/astro/src/core/app/index.ts +++ b/packages/astro/src/core/app/index.ts @@ -14,7 +14,6 @@ import { AstroIntegrationLogger, Logger } from '../logger/core.js'; import { sequence } from '../middleware/index.js'; import { appendForwardSlash, - collapseDuplicateSlashes, joinPaths, prependForwardSlash, removeTrailingForwardSlash, @@ -298,10 +297,6 @@ export class App { if (clientAddress) { Reflect.set(request, clientAddressSymbol, clientAddress); } - // Handle requests with duplicate slashes gracefully by cloning with a cleaned-up request URL - if (request.url !== collapseDuplicateSlashes(request.url)) { - request = new Request(collapseDuplicateSlashes(request.url), request); - } if (!routeData) { routeData = this.match(request); this.#logger.debug('router', 'Astro matched the following route for ' + request.url); diff --git a/packages/astro/src/vite-plugin-astro-server/request.ts b/packages/astro/src/vite-plugin-astro-server/request.ts index a56f6e95c0..c8b3b4cb85 100644 --- a/packages/astro/src/vite-plugin-astro-server/request.ts +++ b/packages/astro/src/vite-plugin-astro-server/request.ts @@ -1,6 +1,6 @@ import type http from 'node:http'; import type { ManifestData } from '../@types/astro.js'; -import { collapseDuplicateSlashes, removeTrailingForwardSlash } from '../core/path.js'; +import { removeTrailingForwardSlash } from '../core/path.js'; import type { DevServerController } from './controller.js'; import { runWithErrorHandling } from './controller.js'; import { recordServerError } from './error.js'; @@ -27,7 +27,7 @@ export async function handleRequest({ const { config, loader } = pipeline; const origin = `${loader.isHttps() ? 'https' : 'http'}://${incomingRequest.headers.host}`; - const url = new URL(collapseDuplicateSlashes(origin + incomingRequest.url)); + const url = new URL(origin + incomingRequest.url); let pathname: string; if (config.trailingSlash === 'never' && !incomingRequest.url) { pathname = ''; diff --git a/packages/astro/test/fixtures/ssr-request/src/middleware.ts b/packages/astro/test/fixtures/ssr-request/src/middleware.ts new file mode 100644 index 0000000000..6e7a20d7a6 --- /dev/null +++ b/packages/astro/test/fixtures/ssr-request/src/middleware.ts @@ -0,0 +1,14 @@ +import { defineMiddleware } from 'astro:middleware'; + +export const onRequest = defineMiddleware(({ url }, next) => { + // Redirect when there are extra slashes + if(url.pathname === '/this//is/my/////directory') { + return new Response(null, { + status: 301, + headers: { + Location: '/' + } + }); + } + return next(); +}); diff --git a/packages/astro/test/ssr-request.test.js b/packages/astro/test/ssr-request.test.js index a78a10f25e..a520b350cc 100644 --- a/packages/astro/test/ssr-request.test.js +++ b/packages/astro/test/ssr-request.test.js @@ -43,18 +43,6 @@ describe('Using Astro.request in SSR', () => { assert.equal($('#origin').text(), 'http://example.com'); }); - it('Duplicate slashes are collapsed', async () => { - const app = await fixture.loadTestAdapterApp(); - const request = new Request('http://example.com/subpath////request/////'); - const response = await app.render(request); - assert.equal(response.status, 200); - const html = await response.text(); - const $ = cheerioLoad(html); - assert.equal($('#origin').text(), 'http://example.com'); - assert.equal($('#pathname').text(), '/subpath/request/'); - assert.equal($('#request-pathname').text(), '/subpath/request/'); - }); - it('public file is copied over', async () => { const json = await fixture.readFile('/client/cars.json'); assert.notEqual(json, undefined); @@ -107,4 +95,11 @@ describe('Using Astro.request in SSR', () => { const data = await response.json(); assert.equal(data instanceof Array, true); }); + + it('middleware gets the actual path sent in the request', async () => { + const app = await fixture.loadTestAdapterApp(); + const request = new Request('http://example.com/this//is/my/////directory'); + const response = await app.render(request); + assert.equal(response.status, 301); + }); });