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> {
|
||||
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);
|
||||
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,
|
||||
};
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
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…
Reference in a new issue