summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Matthew Phillips <matthew@skypack.dev> 2022-03-30 15:55:22 -0400
committerGravatar GitHub <noreply@github.com> 2022-03-30 15:55:22 -0400
commitc989f106f914126e82b2b2b995bd49f022b3a99b (patch)
treec33338971fcb863c7d97da3aed271fb7a556c303
parentd7ece97d207344644b813a91932f5c624e88a7f7 (diff)
downloadastro-c989f106f914126e82b2b2b995bd49f022b3a99b.tar.gz
astro-c989f106f914126e82b2b2b995bd49f022b3a99b.tar.zst
astro-c989f106f914126e82b2b2b995bd49f022b3a99b.zip
Allow components to return a Response (#2944)
* Allow components to return a Response * Changeset
-rw-r--r--.changeset/chatty-cows-attack.md5
-rw-r--r--packages/astro/src/runtime/server/index.ts42
-rw-r--r--packages/astro/test/astro-response.test.js32
-rw-r--r--packages/astro/test/fixtures/astro-response/src/components/not-found.astro6
-rw-r--r--packages/astro/test/fixtures/astro-response/src/pages/not-found-component.astro4
-rw-r--r--packages/astro/test/fixtures/astro-response/src/pages/not-found.astro6
6 files changed, 80 insertions, 15 deletions
diff --git a/.changeset/chatty-cows-attack.md b/.changeset/chatty-cows-attack.md
new file mode 100644
index 000000000..7fe9fb8c2
--- /dev/null
+++ b/.changeset/chatty-cows-attack.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Allow components to return a Response
diff --git a/packages/astro/src/runtime/server/index.ts b/packages/astro/src/runtime/server/index.ts
index 7f314f721..b9970d59d 100644
--- a/packages/astro/src/runtime/server/index.ts
+++ b/packages/astro/src/runtime/server/index.ts
@@ -412,7 +412,8 @@ async function replaceHeadInjection(result: SSRResult, html: string): Promise<st
export async function renderToString(result: SSRResult, componentFactory: AstroComponentFactory, props: any, children: any): Promise<string> {
const Component = await componentFactory(result, props, children);
if (!isAstroComponent(Component)) {
- throw new Error('Cannot return a Response from a nested component.');
+ const response: Response = Component;
+ throw response;
}
let template = await renderAstroComponent(Component);
@@ -425,20 +426,31 @@ export async function renderPage(
props: any,
children: any
): Promise<{ type: 'html'; html: string } | { type: 'response'; response: Response }> {
- const response = await componentFactory(result, props, children);
-
- if (isAstroComponent(response)) {
- let template = await renderAstroComponent(response);
- const html = await replaceHeadInjection(result, template);
- return {
- type: 'html',
- html,
- };
- } else {
- return {
- type: 'response',
- response,
- };
+ try {
+ const response = await componentFactory(result, props, children);
+
+ if (isAstroComponent(response)) {
+ let template = await renderAstroComponent(response);
+ const html = await replaceHeadInjection(result, template);
+ return {
+ type: 'html',
+ html,
+ };
+ } else {
+ return {
+ type: 'response',
+ response,
+ };
+ }
+ } catch(err) {
+ if(err instanceof Response) {
+ return {
+ type: 'response',
+ response: err
+ };
+ } else {
+ throw err;
+ }
}
}
diff --git a/packages/astro/test/astro-response.test.js b/packages/astro/test/astro-response.test.js
new file mode 100644
index 000000000..719d14d30
--- /dev/null
+++ b/packages/astro/test/astro-response.test.js
@@ -0,0 +1,32 @@
+import { expect } from 'chai';
+import { load as cheerioLoad } from 'cheerio';
+import { loadFixture } from './test-utils.js';
+
+// Asset bundling
+describe('Returning responses', () => {
+ let fixture;
+ /** @type {import('./test-utils').DevServer} */
+ let devServer;
+
+ before(async () => {
+ fixture = await loadFixture({
+ projectRoot: './fixtures/astro-response/',
+ });
+
+ devServer = await fixture.startDevServer();
+ });
+
+ after(async () => {
+ await devServer.stop();
+ });
+
+ it('Works from a page', async () => {
+ let response = await fixture.fetch('/not-found');
+ expect(response.status).to.equal(404);
+ });
+
+ it('Works from a component', async () => {
+ let response = await fixture.fetch('/not-found-component');
+ expect(response.status).to.equal(404);
+ });
+});
diff --git a/packages/astro/test/fixtures/astro-response/src/components/not-found.astro b/packages/astro/test/fixtures/astro-response/src/components/not-found.astro
new file mode 100644
index 000000000..dd339e72b
--- /dev/null
+++ b/packages/astro/test/fixtures/astro-response/src/components/not-found.astro
@@ -0,0 +1,6 @@
+---
+return new Response(null, {
+ status: 404,
+ statusText: `Not found`
+});
+---
diff --git a/packages/astro/test/fixtures/astro-response/src/pages/not-found-component.astro b/packages/astro/test/fixtures/astro-response/src/pages/not-found-component.astro
new file mode 100644
index 000000000..e1077e9c9
--- /dev/null
+++ b/packages/astro/test/fixtures/astro-response/src/pages/not-found-component.astro
@@ -0,0 +1,4 @@
+---
+import NotFound from '../components/not-found.astro';
+---
+<NotFound />
diff --git a/packages/astro/test/fixtures/astro-response/src/pages/not-found.astro b/packages/astro/test/fixtures/astro-response/src/pages/not-found.astro
new file mode 100644
index 000000000..dd339e72b
--- /dev/null
+++ b/packages/astro/test/fixtures/astro-response/src/pages/not-found.astro
@@ -0,0 +1,6 @@
+---
+return new Response(null, {
+ status: 404,
+ statusText: `Not found`
+});
+---