Repository: sveltejs/kit (js)

Issue:
internal `fetch` request is not initialized correctly
### Describe the bug

When we call `fetch` to an internal endpoint the request is not initialized the same way it would be in the browser or using `undici`:

https://github.com/sveltejs/kit/blob/0d4596340389233031588a77e478f9fb34a26d4e/packages/kit/src/runtime/server/fetch.js#L131

Here's the spec: https://fetch.spec.whatwg.org/#fetching

In particular, I noticed that we're not setting the `Accept` header, but it looks like there's other stuff we're not doing either like setting `Accept-Language`.

### Reproduction

Call a `+server.js` from a `load` function in a `+page.js`

See https://github.com/sveltejs/sites/pull/398

### Logs

_No response_

### System Info

```Shell
`master`
```


### Severity

serious, but I can work around it

### Additional Information

_No response_

Pull request description:
always set accept/accept-language headers when making a self-request
closes #7720. We previously decided not to automatically include request headers, but I think these exceptions are valid. Given that `accept` is used within Kit for content negotiation purposes, it makes sense to default it to `*/*` if unspecified. Similarly, if `accept-language` were to be used for i18n purposes, it makes sense for it to match the initial page request.

### Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
- [x] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
- [x] This message body should clearly illustrate what problems it solves.
- [x] Ideally, include a test that fails without this PR but passes with it.

### Tests
- [x] Run the tests with `pnpm test` and lint the project with `pnpm lint` and `pnpm check`

### Changesets
- [x] If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running `pnpm changeset` and following the prompts. All changesets should be `patch` until SvelteKit 1.0


Patch:
diff --git a/.changeset/perfect-needles-tap.md b/.changeset/perfect-needles-tap.md
new file mode 100644
index 000000000..be8b72924
--- /dev/null
+++ b/.changeset/perfect-needles-tap.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/kit': patch
+---
+
+Always set `Accept` and `Accept-Language` headers when making a self-request
diff --git a/packages/kit/src/runtime/server/fetch.js b/packages/kit/src/runtime/server/fetch.js
index 1b1b60bf6..89f21b5db 100644
--- a/packages/kit/src/runtime/server/fetch.js
+++ b/packages/kit/src/runtime/server/fetch.js
@@ -128,6 +128,17 @@ export function create_fetch({ event, options, state, get_cookie_header }) {
 					throw new Error('Request body must be a string or TypedArray');
 				}
 
+				if (!request.headers.has('accept')) {
+					request.headers.set('accept', '*/*');
+				}
+
+				if (!request.headers.has('accept-language')) {
+					request.headers.set(
+						'accept-language',
+						/** @type {string} */ (event.request.headers.get('accept-language'))
+					);
+				}
+
 				response = await respond(request, options, state);
 
 				const set_cookie = response.headers.get('set-cookie');


Test patch:
diff --git a/packages/kit/test/apps/basics/src/routes/load/fetch-request-headers.json/+server.js b/packages/kit/test/apps/basics/src/routes/load/fetch-request-headers.json/+server.js
deleted file mode 100644
index d58d91263..000000000
--- a/packages/kit/test/apps/basics/src/routes/load/fetch-request-headers.json/+server.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import { json } from '@sveltejs/kit';
-
-/** @type {import('./$types').RequestHandler} */
-export function GET({ request }) {
-	/** @type {Record<string, string>} */
-	const body = {};
-
-	request.headers.forEach((value, key) => {
-		body[key] = value;
-	});
-
-	return json(body);
-}
diff --git a/packages/kit/test/apps/basics/src/routes/load/fetch-request-headers/+page.js b/packages/kit/test/apps/basics/src/routes/load/fetch-request-headers/+page.js
index 69e85a35b..991d09aef 100644
--- a/packages/kit/test/apps/basics/src/routes/load/fetch-request-headers/+page.js
+++ b/packages/kit/test/apps/basics/src/routes/load/fetch-request-headers/+page.js
@@ -1,6 +1,6 @@
 /** @type {import('@sveltejs/kit').Load} */
 export async function load({ fetch }) {
-	const res = await fetch('/load/fetch-request-headers.json');
+	const res = await fetch('/load/fetch-request-headers/data');
 
 	return {
 		headers: await res.json()
diff --git a/packages/kit/test/apps/basics/src/routes/load/fetch-request-headers/+page.svelte b/packages/kit/test/apps/basics/src/routes/load/fetch-request-headers/+page.svelte
index 27cbe80d0..3987470dd 100644
--- a/packages/kit/test/apps/basics/src/routes/load/fetch-request-headers/+page.svelte
+++ b/packages/kit/test/apps/basics/src/routes/load/fetch-request-headers/+page.svelte
@@ -3,6 +3,8 @@
 	export let data;
 
 	const json = JSON.stringify({
+		accept: data.headers['accept'],
+		'accept-language': data.headers['accept-language'],
 		connection: data.headers['connection'],
 		'sec-fetch-dest': data.headers['sec-fetch-dest'],
 		'sec-fetch-mode': data.headers['sec-fetch-mode'],
diff --git a/packages/kit/test/apps/basics/src/routes/load/fetch-request-headers/data/+server.js b/packages/kit/test/apps/basics/src/routes/load/fetch-request-headers/data/+server.js
new file mode 100644
index 000000000..4d9966804
--- /dev/null
+++ b/packages/kit/test/apps/basics/src/routes/load/fetch-request-headers/data/+server.js
@@ -0,0 +1,6 @@
+import { json } from '@sveltejs/kit';
+
+/** @type {import('./$types').RequestHandler} */
+export function GET({ request }) {
+	return json(Object.fromEntries(request.headers));
+}
diff --git a/packages/kit/test/apps/basics/test/test.js b/packages/kit/test/apps/basics/test/test.js
index 2ee921709..be47fcb68 100644
--- a/packages/kit/test/apps/basics/test/test.js
+++ b/packages/kit/test/apps/basics/test/test.js
@@ -817,6 +817,8 @@ test.describe('Load', () => {
 
 		if (javaScriptEnabled) {
 			expect(headers).toEqual({
+				accept: '*/*',
+				'accept-language': 'en-US',
 				// the referer will be the previous page in the client-side
 				// navigation case
 				referer: `${baseURL}/load`,
@@ -827,7 +829,10 @@ test.describe('Load', () => {
 				connection: 'keep-alive'
 			});
 		} else {
-			expect(headers).toEqual({});
+			expect(headers).toEqual({
+				accept: '*/*',
+				'accept-language': 'en-US'
+			});
 		}
 	});