0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-03-10 23:01:26 -05:00

Merge branch 'main' into next

This commit is contained in:
Matthew Phillips 2023-08-17 08:54:28 -04:00
commit 7f978ec9d9
14 changed files with 243 additions and 34 deletions

View file

@ -39,6 +39,15 @@
- Updated dependencies [[`1eae2e3f7`](https://github.com/withastro/astro/commit/1eae2e3f7d693c9dfe91c8ccfbe606d32bf2fb81), [`76ddef19c`](https://github.com/withastro/astro/commit/76ddef19ccab6e5f7d3a5740cd41acf10e334b38), [`9b4f70a62`](https://github.com/withastro/astro/commit/9b4f70a629f55e461759ba46f68af7097a2e9215), [`3fdf509b2`](https://github.com/withastro/astro/commit/3fdf509b2731a9b2f972d89291e57cf78d62c769), [`2f951cd40`](https://github.com/withastro/astro/commit/2f951cd403dfcc2c3ca6aae618ae3e1409516e32), [`c022a4217`](https://github.com/withastro/astro/commit/c022a4217a805d223c1494e9eda4e48bbf810388), [`67becaa58`](https://github.com/withastro/astro/commit/67becaa580b8f787df58de66b7008b7098f1209c), [`bc37331d8`](https://github.com/withastro/astro/commit/bc37331d8154e3e95a8df9131e4e014e78a7a9e7), [`dfc2d93e3`](https://github.com/withastro/astro/commit/dfc2d93e3c645995379358fabbdfa9aab99f43d8), [`3dc1ca2fa`](https://github.com/withastro/astro/commit/3dc1ca2fac8d9965cc5085a5d09e72ed87b4281a), [`1be84dfee`](https://github.com/withastro/astro/commit/1be84dfee3ce8e6f5cc624f99aec4e980f6fde37), [`35f01df79`](https://github.com/withastro/astro/commit/35f01df797d23315f2bee2fc3fd795adb0559c58), [`3fdf509b2`](https://github.com/withastro/astro/commit/3fdf509b2731a9b2f972d89291e57cf78d62c769), [`78de801f2`](https://github.com/withastro/astro/commit/78de801f21fd4ca1653950027d953bf08614566b), [`59d6e569f`](https://github.com/withastro/astro/commit/59d6e569f63e175c97e82e94aa7974febfb76f7c), [`7723c4cc9`](https://github.com/withastro/astro/commit/7723c4cc93298c2e6530e55da7afda048f22cf81), [`fb5cd6b56`](https://github.com/withastro/astro/commit/fb5cd6b56dc27a71366ed5e1ab8bfe9b8f96bac5), [`631b9c410`](https://github.com/withastro/astro/commit/631b9c410d5d66fa384674027ba95d69ebb5063f)]:
- astro@3.0.0-beta.0
## 5.3.4
### Patch Changes
- [#8084](https://github.com/withastro/astro/pull/8084) [`560e45924`](https://github.com/withastro/astro/commit/560e45924622141206ff5b47d134cb343d6d2a71) Thanks [@hbgl](https://github.com/hbgl)! - Stream request body instead of buffering it in memory.
- Updated dependencies [[`c19987df0`](https://github.com/withastro/astro/commit/c19987df0be3520cf774476cea270c03edd08354), [`560e45924`](https://github.com/withastro/astro/commit/560e45924622141206ff5b47d134cb343d6d2a71), [`afc45af20`](https://github.com/withastro/astro/commit/afc45af2022f7c43fbb6c5c04983695f3819e47e), [`d1f7143f9`](https://github.com/withastro/astro/commit/d1f7143f9caf2ffa0e87cc55c0e05339d3501db3), [`3e46634fd`](https://github.com/withastro/astro/commit/3e46634fd540e5b967d2e5c9abd6235452cee2f2), [`a12027b6a`](https://github.com/withastro/astro/commit/a12027b6af411be39700919ca47e240a335e9887)]:
- astro@2.10.8
## 5.3.3
### Patch Changes

View file

@ -48,6 +48,7 @@
"chai": "^4.3.7",
"cheerio": "1.0.0-rc.12",
"mocha": "^9.2.2",
"node-mocks-http": "^1.12.2"
"node-mocks-http": "^1.13.0",
"undici": "^5.22.1"
}
}

View file

@ -1,6 +1,7 @@
import nodejs from '../dist/index.js';
import { loadFixture, createRequestAndResponse } from './test-utils.js';
import { expect } from 'chai';
import crypto from 'node:crypto';
describe('API routes', () => {
/** @type {import('./test-utils').Fixture} */
@ -22,9 +23,11 @@ describe('API routes', () => {
url: '/recipes',
});
handler(req, res);
req.once('async_iterator', () => {
req.send(JSON.stringify({ id: 2 }));
});
req.send(JSON.stringify({ id: 2 }));
handler(req, res);
let [buffer] = await done;
@ -43,11 +46,47 @@ describe('API routes', () => {
url: '/binary',
});
req.once('async_iterator', () => {
req.send(Buffer.from(new Uint8Array([1, 2, 3, 4, 5])));
});
handler(req, res);
req.send(Buffer.from(new Uint8Array([1, 2, 3, 4, 5])));
let [out] = await done;
let arr = Array.from(new Uint8Array(out.buffer));
expect(arr).to.deep.equal([5, 4, 3, 2, 1]);
});
it('Can post large binary data', async () => {
const { handler } = await import('./fixtures/api-route/dist/server/entry.mjs');
let { req, res, done } = createRequestAndResponse({
method: 'POST',
url: '/hash',
});
handler(req, res);
let expectedDigest = null;
req.once('async_iterator', () => {
// Send 256MB of garbage data in 256KB chunks. This should be fast (< 1sec).
let remainingBytes = 256 * 1024 * 1024;
const chunkSize = 256 * 1024;
const hash = crypto.createHash('sha256');
while (remainingBytes > 0) {
const size = Math.min(remainingBytes, chunkSize);
const chunk = Buffer.alloc(size, Math.floor(Math.random() * 256));
hash.update(chunk);
req.emit('data', chunk);
remainingBytes -= size;
}
req.emit('end');
expectedDigest = hash.digest();
});
let [out] = await done;
expect(new Uint8Array(out.buffer)).to.deep.equal(expectedDigest);
});
});

View file

@ -0,0 +1,16 @@
import crypto from 'node:crypto';
export async function post({ request }: { request: Request }) {
const hash = crypto.createHash('sha256');
const iterable = request.body as unknown as AsyncIterable<Uint8Array>;
for await (const chunk of iterable) {
hash.update(chunk);
}
return new Response(hash.digest(), {
headers: {
'Content-Type': 'application/octet-stream'
}
});
}

View file

@ -1,7 +1,8 @@
{
"name": "@test/nodejs-prerender-404",
"name": "@test/nodejs-prerender-404-500",
"version": "0.0.0",
"private": true,
"type": "module",
"dependencies": {
"astro": "workspace:*",
"@astrojs/node": "workspace:*"

View file

@ -0,0 +1,3 @@
body {
background-color: ivory;
}

View file

@ -0,0 +1,17 @@
// This module is only used by the prerendered 404.astro.
// It exhibits different behavior if it's called more than once,
// which is detected by a test and interpreted as a failure.
let usedOnce = false
let dynamicMessage = "Page was not prerendered"
export default function () {
if (usedOnce === false) {
usedOnce = true
return "Page does not exist"
}
dynamicMessage += "+"
return dynamicMessage
}

View file

@ -0,0 +1,17 @@
// This module is only used by the prerendered 500.astro.
// It exhibits different behavior if it's called more than once,
// which is detected by a test and interpreted as a failure.
let usedOnce = false
let dynamicMessage = "Page was not prerendered"
export default function () {
if (usedOnce === false) {
usedOnce = true
return "Something went wrong"
}
dynamicMessage += "+"
return dynamicMessage
}

View file

@ -0,0 +1,5 @@
---
import message from "../nondeterminism-404"
export const prerender = true;
---
{message()}

View file

@ -0,0 +1,6 @@
---
import "../external-stylesheet.css"
import message from "../nondeterminism-500"
export const prerender = true
---
<h1>{message()}</h1>

View file

@ -0,0 +1,4 @@
---
return new Response(null, { status: 500 })
---
<p>This html will not be served</p>

View file

@ -1,5 +0,0 @@
---
export const prerender = true;
---
Page does not exist

View file

@ -9,10 +9,11 @@ import * as cheerio from 'cheerio';
async function load() {
const mod = await import(
`./fixtures/prerender-404/dist/server/entry.mjs?dropcache=${Date.now()}`
`./fixtures/prerender-404-500/dist/server/entry.mjs?dropcache=${Date.now()}`
);
return mod;
}
describe('Prerender 404', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;
@ -24,8 +25,12 @@ describe('Prerender 404', () => {
process.env.PRERENDER = true;
fixture = await loadFixture({
// inconsequential config that differs between tests
// to bust cache and prevent modules and their state
// from being reused
site: 'https://test.dev/',
base: '/some-base',
root: './fixtures/prerender-404/',
root: './fixtures/prerender-404-500/',
output: 'server',
adapter: nodejs({ mode: 'standalone' }),
});
@ -51,12 +56,52 @@ describe('Prerender 404', () => {
});
it('Can handle prerendered 404', async () => {
const res = await fetch(`http://${server.host}:${server.port}/some-base/missing`);
const html = await res.text();
const url = `http://${server.host}:${server.port}/some-base/missing`;
const res1 = await fetch(url);
const res2 = await fetch(url);
const res3 = await fetch(url);
expect(res1.status).to.equal(404);
expect(res2.status).to.equal(404);
expect(res3.status).to.equal(404);
const html1 = await res1.text();
const html2 = await res2.text();
const html3 = await res3.text();
expect(html1).to.equal(html2);
expect(html2).to.equal(html3);
const $ = cheerio.load(html1);
expect($('body').text()).to.equal('Page does not exist');
});
it(' Can handle prerendered 500 called indirectly', async () => {
const url = `http://${server.host}:${server.port}/some-base/fivehundred`;
const response1 = await fetch(url);
const response2 = await fetch(url);
const response3 = await fetch(url);
expect(response1.status).to.equal(500);
const html1 = await response1.text();
const html2 = await response2.text();
const html3 = await response3.text();
expect(html1).to.contain('Something went wrong');
expect(html1).to.equal(html2);
expect(html2).to.equal(html3);
});
it('prerendered 500 page includes expected styles', async () => {
const response = await fetch(`http://${server.host}:${server.port}/some-base/fivehundred`);
const html = await response.text();
const $ = cheerio.load(html);
expect(res.status).to.equal(404);
expect($('body').text()).to.equal('Page does not exist');
// length will be 0 if the stylesheet does not get included
expect($('link[rel=stylesheet]')).to.have.a.lengthOf(1);
});
});
@ -66,12 +111,16 @@ describe('Prerender 404', () => {
process.env.PRERENDER = true;
fixture = await loadFixture({
root: './fixtures/prerender-404/',
// inconsequential config that differs between tests
// to bust cache and prevent modules and their state
// from being reused
site: 'https://test.info/',
root: './fixtures/prerender-404-500/',
output: 'server',
adapter: nodejs({ mode: 'standalone' }),
});
await fixture.build();
const { startServer } = await await load();
const { startServer } = await load();
let res = startServer();
server = res.server;
});
@ -92,11 +141,24 @@ describe('Prerender 404', () => {
});
it('Can handle prerendered 404', async () => {
const res = await fetch(`http://${server.host}:${server.port}/missing`);
const html = await res.text();
const $ = cheerio.load(html);
const url = `http://${server.host}:${server.port}/some-base/missing`;
const res1 = await fetch(url);
const res2 = await fetch(url);
const res3 = await fetch(url);
expect(res1.status).to.equal(404);
expect(res2.status).to.equal(404);
expect(res3.status).to.equal(404);
const html1 = await res1.text();
const html2 = await res2.text();
const html3 = await res3.text();
expect(html1).to.equal(html2);
expect(html2).to.equal(html3);
const $ = cheerio.load(html1);
expect(res.status).to.equal(404);
expect($('body').text()).to.equal('Page does not exist');
});
});
@ -112,13 +174,17 @@ describe('Hybrid 404', () => {
process.env.ASTRO_NODE_AUTOSTART = 'disabled';
process.env.PRERENDER = false;
fixture = await loadFixture({
// inconsequential config that differs between tests
// to bust cache and prevent modules and their state
// from being reused
site: 'https://test.com/',
base: '/some-base',
root: './fixtures/prerender-404/',
root: './fixtures/prerender-404-500/',
output: 'hybrid',
adapter: nodejs({ mode: 'standalone' }),
});
await fixture.build();
const { startServer } = await await load();
const { startServer } = await load();
let res = startServer();
server = res.server;
});
@ -139,11 +205,24 @@ describe('Hybrid 404', () => {
});
it('Can handle prerendered 404', async () => {
const res = await fetch(`http://${server.host}:${server.port}/some-base/missing`);
const html = await res.text();
const $ = cheerio.load(html);
const url = `http://${server.host}:${server.port}/some-base/missing`;
const res1 = await fetch(url);
const res2 = await fetch(url);
const res3 = await fetch(url);
expect(res1.status).to.equal(404);
expect(res2.status).to.equal(404);
expect(res3.status).to.equal(404);
const html1 = await res1.text();
const html2 = await res2.text();
const html3 = await res3.text();
expect(html1).to.equal(html2);
expect(html2).to.equal(html3);
const $ = cheerio.load(html1);
expect(res.status).to.equal(404);
expect($('body').text()).to.equal('Page does not exist');
});
});
@ -153,12 +232,16 @@ describe('Hybrid 404', () => {
process.env.ASTRO_NODE_AUTOSTART = 'disabled';
process.env.PRERENDER = false;
fixture = await loadFixture({
root: './fixtures/prerender-404/',
// inconsequential config that differs between tests
// to bust cache and prevent modules and their state
// from being reused
site: 'https://test.net/',
root: './fixtures/prerender-404-500/',
output: 'hybrid',
adapter: nodejs({ mode: 'standalone' }),
});
await fixture.build();
const { startServer } = await await load();
const { startServer } = await load();
let res = startServer();
server = res.server;
});
@ -179,11 +262,24 @@ describe('Hybrid 404', () => {
});
it('Can handle prerendered 404', async () => {
const res = await fetch(`http://${server.host}:${server.port}/missing`);
const html = await res.text();
const $ = cheerio.load(html);
const url = `http://${server.host}:${server.port}/missing`;
const res1 = await fetch(url);
const res2 = await fetch(url);
const res3 = await fetch(url);
expect(res1.status).to.equal(404);
expect(res2.status).to.equal(404);
expect(res3.status).to.equal(404);
const html1 = await res1.text();
const html2 = await res2.text();
const html3 = await res3.text();
expect(html1).to.equal(html2);
expect(html2).to.equal(html3);
const $ = cheerio.load(html1);
expect(res.status).to.equal(404);
expect($('body').text()).to.equal('Page does not exist');
});
});