denoland / denoland/std

Add `Sec-Fetch-Mode` and `Sec-Fetch-Dest` to `@std/http/unstable-headers`

Open
#6,116 1 comment 1 reaction 0 assignees View on GitHub
Dominant language
TypeScript
Stars
3.6k
Forks
681
PR merge metrics
No merged PRs in 30d

Description

**Is your feature request related to a problem? Please describe.**

In many frontend projects I've worked on, I've started relying on ``Sec-Fetch-Mode` and/or `Sec-Fetch-Dest` headers. Because it's very common to return `/index.html` for SPA apps, but returning it for CSS/JS and other unrelated static resources is annoying. Therefore it's very helpful to check that the current request is a `navigate` to `document` before returning `/index.html`, otherwise 404.

I don't know why this header is not included in https://www.iana.org/assignments/http-fields/http-fields.xhtml#field-names, but these headers were part of Baseline 2023, and are supported in all major browsers currently.

Would PR's adding the below be accepted, or does new API's require discussion first in issues?

**Describe the solution you'd like**

It would be great if the `Sec-Fetch-*` headers were just included in `HEADERS` from `jsr:@std/http@1/unstable-header`. It would be even more awesome if there was a dedicated API for this, like with `accepts` in negotiation.ts:

```ts
import { fetchMode, fetchDestination } from 'jsr:@std/http@1';

const request = new Request('https://example.com/', {
headers: {
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Dest': 'document'
}
});

fetchMode(req, 'navigate');
// true
fetchMode(req, 'same-origin');
// false
fetchMode(req, 'navigate', 'no-cors');
// true

fetchDestination(req, 'document');
// true
fetchDestination(req, 'iframe');
// false
fetchDestination(req, 'document', 'iframe', 'frame');
// true
```
The biggest win for this being able to write the values above in a type safe way:

```ts
import { serveFile, fethMode, fetchDestination } from '@std/http';

export const spaFallback: Deno.ServeHandler = (req) => {
if (!isDocumentReq(req)) return new Response(undefined, { status: 404 });
return serveFile(req, '/index.html');
}

export function isDocumentReq(req: Request) {
return fethMode(req, 'navigate') && fetchDestination(req, 'document');
}
```

**Describe alternatives you've considered**

There current code is not terrible, but using type-safe header values and type safe possible header values means it's easy to for instance misspell `'navigate'` to `'navigation'`.

```ts
export function isDocumentReq(req: Request) {
const mode = req.headers.get('Sec-Fetch-Mode');
const dest = req.headers.get('Sec-Fetch-Dest');
return mode === 'navigate' && dest === 'document';
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.