Allow components to return a Response (#2944)
* Allow components to return a Response * Changeset
This commit is contained in:
parent
d7ece97d20
commit
c989f106f9
6 changed files with 79 additions and 14 deletions
5
.changeset/chatty-cows-attack.md
Normal file
5
.changeset/chatty-cows-attack.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Allow components to return a Response
|
|
@ -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> {
|
export async function renderToString(result: SSRResult, componentFactory: AstroComponentFactory, props: any, children: any): Promise<string> {
|
||||||
const Component = await componentFactory(result, props, children);
|
const Component = await componentFactory(result, props, children);
|
||||||
if (!isAstroComponent(Component)) {
|
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);
|
let template = await renderAstroComponent(Component);
|
||||||
|
@ -425,20 +426,31 @@ export async function renderPage(
|
||||||
props: any,
|
props: any,
|
||||||
children: any
|
children: any
|
||||||
): Promise<{ type: 'html'; html: string } | { type: 'response'; response: Response }> {
|
): Promise<{ type: 'html'; html: string } | { type: 'response'; response: Response }> {
|
||||||
const response = await componentFactory(result, props, children);
|
try {
|
||||||
|
const response = await componentFactory(result, props, children);
|
||||||
|
|
||||||
if (isAstroComponent(response)) {
|
if (isAstroComponent(response)) {
|
||||||
let template = await renderAstroComponent(response);
|
let template = await renderAstroComponent(response);
|
||||||
const html = await replaceHeadInjection(result, template);
|
const html = await replaceHeadInjection(result, template);
|
||||||
return {
|
return {
|
||||||
type: 'html',
|
type: 'html',
|
||||||
html,
|
html,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
type: 'response',
|
type: 'response',
|
||||||
response,
|
response,
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
} catch(err) {
|
||||||
|
if(err instanceof Response) {
|
||||||
|
return {
|
||||||
|
type: 'response',
|
||||||
|
response: err
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
32
packages/astro/test/astro-response.test.js
Normal file
32
packages/astro/test/astro-response.test.js
Normal file
|
@ -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);
|
||||||
|
});
|
||||||
|
});
|
6
packages/astro/test/fixtures/astro-response/src/components/not-found.astro
vendored
Normal file
6
packages/astro/test/fixtures/astro-response/src/components/not-found.astro
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
return new Response(null, {
|
||||||
|
status: 404,
|
||||||
|
statusText: `Not found`
|
||||||
|
});
|
||||||
|
---
|
4
packages/astro/test/fixtures/astro-response/src/pages/not-found-component.astro
vendored
Normal file
4
packages/astro/test/fixtures/astro-response/src/pages/not-found-component.astro
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
import NotFound from '../components/not-found.astro';
|
||||||
|
---
|
||||||
|
<NotFound />
|
6
packages/astro/test/fixtures/astro-response/src/pages/not-found.astro
vendored
Normal file
6
packages/astro/test/fixtures/astro-response/src/pages/not-found.astro
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
return new Response(null, {
|
||||||
|
status: 404,
|
||||||
|
statusText: `Not found`
|
||||||
|
});
|
||||||
|
---
|
Loading…
Add table
Reference in a new issue