Skip to content

Commit 70a9f0b

Browse files
authored
Fix server island script breaking when charset is added to content-type (#12810)
1 parent 98f9e83 commit 70a9f0b

File tree

5 files changed

+28
-1
lines changed

5 files changed

+28
-1
lines changed

.changeset/six-pumpkins-act.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'astro': patch
3+
---
4+
5+
Fixes server islands failing to check content-type header under certain circumstances
6+
7+
Sometimes a reverse proxy or similar service might modify the content-type header to include the charset or other parameters in the media type of the response. This previously wasn't handled by the client-side server island script and thus removed the script without actually placing the requested content in the DOM. This fix makes it so the script checks if the header starts with the proper content type instead of exactly matching `text/html`, so the following will still be considered a valid header: `text/html; charset=utf-8`
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
Astro.response.headers.set('content-type', 'text/html;charset=utf-8');
3+
---
4+
5+
<h2 id="charset-in-content-type">I'm an island with a different content-type response header</h2>

packages/astro/e2e/fixtures/server-islands/src/pages/index.astro

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import Island from '../components/Island.astro';
33
import Self from '../components/Self.astro';
44
import HTMLError from '../components/HTMLError.astro';
55
import { generateLongText } from '../lorem';
6+
import MediaTypeInHeader from '../components/MediaTypeInHeader.astro';
67
78
const content = generateLongText(5);
89
@@ -22,6 +23,8 @@ export const prerender = false;
2223

2324
<Self server:defer />
2425

26+
<MediaTypeInHeader server:defer />
27+
2528
<div id="big">
2629
<Island server:defer secret="test" content={content} />
2730
</div>

packages/astro/e2e/server-islands.test.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,15 @@ test.describe('Server islands', () => {
4444
await expect(el).toHaveText('test');
4545
});
4646

47+
test("content-type header with media type still allows the island to be displayed", async ({
48+
page,
49+
astro,
50+
}) => {
51+
await page.goto(astro.resolveUrl('/base/'));
52+
let el = page.locator('#charset-in-content-type');
53+
await expect(el).toHaveCount(1);
54+
});
55+
4756
test('Self imported module can server defer', async ({ page, astro }) => {
4857
await page.goto(astro.resolveUrl('/base/'));
4958
let el = page.locator('.now');

packages/astro/src/runtime/server/render/server-islands.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,10 @@ let response = await fetch('${serverIslandUrl}', {
120120
`
121121
}
122122
if (script) {
123-
if(response.status === 200 && response.headers.get('content-type') === 'text/html') {
123+
if(
124+
response.status === 200
125+
&& response.headers.has('content-type')
126+
&& response.headers.get('content-type').split(";")[0].trim() === 'text/html') {
124127
let html = await response.text();
125128
126129
// Swap!

0 commit comments

Comments
 (0)