0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-02-17 22:44:24 -05:00

fix(dev): remove params for prerendered pages (#10199)

* fix(dev): remove params for prerendered pages

* add test

* add changset

* deduplicate param removal

* format

* adjust tests
This commit is contained in:
Arsh 2024-02-23 20:56:34 +05:30 committed by GitHub
parent 3de7b2c7ec
commit 6aa660ae7a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 78 additions and 13 deletions

View file

@ -0,0 +1,5 @@
---
"astro": patch
---
Fixes an issue where prerendered pages had access to query params in dev mode.

View file

@ -1,5 +1,7 @@
import type { APIContext } from 'astro'; import type { APIContext } from 'astro';
export const prerender = false;
export const POST = async ({ request, redirect }: APIContext) => { export const POST = async ({ request, redirect }: APIContext) => {
const formData = await request.formData(); const formData = await request.formData();
const name = formData.get('name'); const name = formData.get('name');

View file

@ -3,6 +3,7 @@ import Layout from '../components/Layout.astro';
const method = Astro.url.searchParams.get('method') ?? 'POST'; const method = Astro.url.searchParams.get('method') ?? 'POST';
const enctype = Astro.url.searchParams.get('enctype'); const enctype = Astro.url.searchParams.get('enctype');
const postShowThrow = Astro.url.searchParams.has('throw') ?? false; const postShowThrow = Astro.url.searchParams.has('throw') ?? false;
export const prerender = false;
--- ---
<Layout> <Layout>

View file

@ -1,6 +1,8 @@
--- ---
import Layout from '../components/Layout.astro'; import Layout from '../components/Layout.astro';
const name = Astro.url.searchParams.get('name'); const name = Astro.url.searchParams.get('name');
export const prerender = false;
--- ---
<Layout> <Layout>
<div>Submitted contact: <span id="contact-name">{name}</span></div> <div>Submitted contact: <span id="contact-name">{name}</span></div>

View file

@ -6,6 +6,8 @@ if(Astro.request.method === 'POST') {
const name = formData.get('name'); const name = formData.get('name');
return Astro.redirect(`/form-response?name=${name}`); return Astro.redirect(`/form-response?name=${name}`);
} }
export const prerender = false;
--- ---
<Layout> <Layout>
<h2>Contact Form</h2> <h2>Contact Form</h2>

View file

@ -13,6 +13,7 @@ export interface CreateRequestOptions {
logger: Logger; logger: Logger;
ssr: boolean; ssr: boolean;
locals?: object | undefined; locals?: object | undefined;
removeParams?: boolean;
} }
const clientAddressSymbol = Symbol.for('astro.clientAddress'); const clientAddressSymbol = Symbol.for('astro.clientAddress');
@ -27,13 +28,21 @@ export function createRequest({
logger, logger,
ssr, ssr,
locals, locals,
removeParams = false,
}: CreateRequestOptions): Request { }: CreateRequestOptions): Request {
let headersObj = let headersObj =
headers instanceof Headers headers instanceof Headers
? headers ? headers
: new Headers(Object.entries(headers as Record<string, any>)); : new Headers(Object.entries(headers as Record<string, any>));
const request = new Request(url.toString(), { if (typeof url === 'string') url = new URL(url);
// HACK! astro:assets uses query params for the injected route in `dev`
if (removeParams && url.pathname !== '/_image') {
url.search = '';
}
const request = new Request(url, {
method: method, method: method,
headers: headersObj, headers: headersObj,
body, body,

View file

@ -40,17 +40,6 @@ export async function handleRequest({
// Add config.base back to url before passing it to SSR // Add config.base back to url before passing it to SSR
url.pathname = removeTrailingForwardSlash(config.base) + url.pathname; url.pathname = removeTrailingForwardSlash(config.base) + url.pathname;
// HACK! astro:assets uses query params for the injected route in `dev`
if (!buildingToSSR && pathname !== '/_image') {
// Prevent user from depending on search params when not doing SSR.
// NOTE: Create an array copy here because deleting-while-iterating
// creates bugs where not all search params are removed.
const allSearchParams = Array.from(url.searchParams);
for (const [key] of allSearchParams) {
url.searchParams.delete(key);
}
}
let body: ArrayBuffer | undefined = undefined; let body: ArrayBuffer | undefined = undefined;
if (!(incomingRequest.method === 'GET' || incomingRequest.method === 'HEAD')) { if (!(incomingRequest.method === 'GET' || incomingRequest.method === 'HEAD')) {
let bytes: Uint8Array[] = []; let bytes: Uint8Array[] = [];

View file

@ -229,6 +229,7 @@ export async function handleRoute({
logger, logger,
ssr: buildingToSSR, ssr: buildingToSSR,
clientAddress: buildingToSSR ? incomingRequest.socket.remoteAddress : undefined, clientAddress: buildingToSSR ? incomingRequest.socket.remoteAddress : undefined,
removeParams: buildingToSSR === false || route.prerender
}); });
// Set user specified headers to response object. // Set user specified headers to response object.

View file

@ -1,11 +1,14 @@
import * as assert from 'node:assert/strict'; import * as assert from 'node:assert/strict';
import { describe, it } from 'node:test'; import { after, before, describe, it } from 'node:test';
import { fileURLToPath } from 'node:url';
import { createContainer } from '../../../dist/core/dev/container.js';
import { createLoader } from '../../../dist/core/module-loader/index.js'; import { createLoader } from '../../../dist/core/module-loader/index.js';
import { createRouteManifest } from '../../../dist/core/routing/index.js'; import { createRouteManifest } from '../../../dist/core/routing/index.js';
import { createComponent, render } from '../../../dist/runtime/server/index.js'; import { createComponent, render } from '../../../dist/runtime/server/index.js';
import { createController, handleRequest } from '../../../dist/vite-plugin-astro-server/index.js'; import { createController, handleRequest } from '../../../dist/vite-plugin-astro-server/index.js';
import { DevPipeline } from '../../../dist/vite-plugin-astro-server/pipeline.js'; import { DevPipeline } from '../../../dist/vite-plugin-astro-server/pipeline.js';
import { createDevelopmentManifest } from '../../../dist/vite-plugin-astro-server/plugin.js'; import { createDevelopmentManifest } from '../../../dist/vite-plugin-astro-server/plugin.js';
import testAdapter from '../../test-adapter.js';
import { import {
createAstroModule, createAstroModule,
createBasicSettings, createBasicSettings,
@ -73,4 +76,55 @@ describe('vite-plugin-astro-server', () => {
assert.equal(html.includes('<div id="test">'), true); assert.equal(html.includes('<div id="test">'), true);
}); });
}); });
describe('url', () => {
let container;
let settings;
before(async () => {
const root = new URL('../../fixtures/api-routes/', import.meta.url);
const fileSystem = {
'/src/pages/url.astro': `{Astro.request.url}`,
'/src/pages/prerendered.astro': `---
export const prerender = true;
---
{Astro.request.url}`,
};
const fs = createFs(fileSystem, root);
settings = await createBasicSettings({
root: fileURLToPath(root),
output: 'server',
adapter: testAdapter(),
});
container = await createContainer({
fs,
settings,
logger: defaultLogger,
});
});
after(async () => {
await container.close();
});
it('params are included', async () => {
const { req, res, text } = createRequestAndResponse({
method: 'GET',
url: '/url?xyz=123',
});
container.handle(req, res);
const html = await text();
assert.deepEqual(html, '<!DOCTYPE html>http://undefined/url?xyz=123');
});
it('params are excluded on prerendered routes', async () => {
const { req, res, text } = createRequestAndResponse({
method: 'GET',
url: '/prerendered?xyz=123',
});
container.handle(req, res);
const html = await text();
assert.deepEqual(html, '<!DOCTYPE html>http://undefined/prerendered');
});
});
}); });