- Oct 2023
-
datatracker.ietf.org datatracker.ietf.org
-
developer.mozilla.org developer.mozilla.org
-
<div itemscope itemtype="http://schema.org/Code"> ```abnf Alt-Svc: clear Alt-Svc: <protocol-id>=<alt-authority>; ma=<max-age> Alt-Svc: <protocol-id>=<alt-authority>; ma=<max-age>; persist=1 ``` </div> <div itemscope itemtype="http://schema.org/Code"> ```http Alt-Svc: h2=":443"; ma=2592000; Alt-Svc: h2=":443"; ma=2592000; persist=1 Alt-Svc: h2="alt.example.com:443", h2=":443" Alt-Svc: h3-25=":443"; ma=3600, h2=":443"; ma=3600 ``` </div>
-
-
datatracker.ietf.org datatracker.ietf.org
- Sep 2023
- Aug 2023
-
datatracker.ietf.org datatracker.ietf.org
-
datatracker.ietf.org datatracker.ietf.org
Tags
- cdn
- caching
- http:header=cdn-cache-control
- http:header=cdn-cache-control:private
- http:header=cdn-cache-control:no-cache
- wikipedia:en=HTTP_caching
- http:header=cdn-cache-control:must-revalidate
- http:header=cdn-cache-control:no-store
- http
- http:header=cdn-cache-control:max-age
- urn:ietf:rfc:9213
Annotators
URL
-
-
datatracker.ietf.org datatracker.ietf.org
Tags
- caching
- http:header=cache-control:min-fresh
- http:header=cache-control
- http:code=304
- http:header=cache-control:only-if-cached
- http:header=cache-control:no-cache
- http:header=cache-control:must-revalidate
- http:header=warning
- http:header=pragma
- http:header=if-range
- http:code=206
- http:header=expires
- http:header=if-unmodified-since
- http:header=cache-control:s-maxage
- http:header=cache-control:proxy-revalidate
- http:header=if-modified-since
- http:header=cache-control:no-transform
- http:header=if-match
- http:header=cache-control:must-understand
- http:header=cache-control:no-store
- http:header=cache-control:max-stale
- http:header=cache-control:private
- urn:ietf:rfc:9111
- http
- http:header=cache-control:max-age
- wikipedia:en=HTTP_caching
- http:header=cache-control:public
- http:header=age
- http:header=if-none-match
Annotators
URL
-
-
developer.chrome.com developer.chrome.com
-
You can mark topics provided by request headers as observed by setting an Observe-Browsing-Topics: ?1 header on the response to the request. The browser will then use those topics to calculate topics of interest for a user.
-
-
github.com github.com
-
A spec to optimize ad targeting (respectful of privacy, they say... 😂🤣).
Fuck you Google with your dystopian API:
```js // document.browsingTopics() returns an array of BrowsingTopic objects. const topics = await document.browsingTopics();
// Get data for an ad creative. const response = await fetch('https://ads.example/get-creative', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(topics) });
// Get the JSON from the response. const creative = await response.json();
// Display the ad. (or not) ```
-
-
kit.svelte.dev kit.svelte.dev
-
```js // CSP svelte.config.js
/* @type {import('@sveltejs/kit').Config} / const config = { kit: { csp: { directives: { 'script-src': ['self'] }, reportOnly: { 'script-src': ['self'] } } } };
export default config; ```
-
-
developer.mozilla.org developer.mozilla.org
-
www.w3.org www.w3.org
- Jul 2023
-
github.com github.com
-
datatracker.ietf.org datatracker.ietf.org
-
developer.chrome.com developer.chrome.com
-
html <meta http-equiv="Accept-CH" content="DPR, Viewport-Width, Width"> ... <picture> <!-- serve WebP to Chrome and Opera --> <source media="(min-width: 50em)" sizes="50vw" srcset="/image/thing-200.webp 200w, /image/thing-400.webp 400w, /image/thing-800.webp 800w, /image/thing-1200.webp 1200w, /image/thing-1600.webp 1600w, /image/thing-2000.webp 2000w" type="image/webp"> <source sizes="(min-width: 30em) 100vw" srcset="/image/thing-crop-200.webp 200w, /image/thing-crop-400.webp 400w, /image/thing-crop-800.webp 800w, /image/thing-crop-1200.webp 1200w, /image/thing-crop-1600.webp 1600w, /image/thing-crop-2000.webp 2000w" type="image/webp"> <!-- serve JPEGXR to Edge --> <source media="(min-width: 50em)" sizes="50vw" srcset="/image/thing-200.jpgxr 200w, /image/thing-400.jpgxr 400w, /image/thing-800.jpgxr 800w, /image/thing-1200.jpgxr 1200w, /image/thing-1600.jpgxr 1600w, /image/thing-2000.jpgxr 2000w" type="image/vnd.ms-photo"> <source sizes="(min-width: 30em) 100vw" srcset="/image/thing-crop-200.jpgxr 200w, /image/thing-crop-400.jpgxr 400w, /image/thing-crop-800.jpgxr 800w, /image/thing-crop-1200.jpgxr 1200w, /image/thing-crop-1600.jpgxr 1600w, /image/thing-crop-2000.jpgxr 2000w" type="image/vnd.ms-photo"> <!-- serve JPEG to others --> <source media="(min-width: 50em)" sizes="50vw" srcset="/image/thing-200.jpg 200w, /image/thing-400.jpg 400w, /image/thing-800.jpg 800w, /image/thing-1200.jpg 1200w, /image/thing-1600.jpg 1600w, /image/thing-2000.jpg 2000w"> <source sizes="(min-width: 30em) 100vw" srcset="/image/thing-crop-200.jpg 200w, /image/thing-crop-400.jpg 400w, /image/thing-crop-800.jpg 800w, /image/thing-crop-1200.jpg 1200w, /image/thing-crop-1600.jpg 1600w, /image/thing-crop-2000.jpg 2000w"> <!-- fallback for browsers that don't support picture --> <img src="/image/thing.jpg" width="50%"> </picture>
-
-
developer.chrome.com developer.chrome.com
-
```js // Log the full user-agent data navigator .userAgentData.getHighEntropyValues( ["architecture", "model", "bitness", "platformVersion", "fullVersionList"]) .then(ua => { console.log(ua) });
// output { "architecture":"x86", "bitness":"64", "brands":[ { "brand":" Not A;Brand", "version":"99" }, { "brand":"Chromium", "version":"98" }, { "brand":"Google Chrome", "version":"98" } ], "fullVersionList":[ { "brand":" Not A;Brand", "version":"99.0.0.0" }, { "brand":"Chromium", "version":"98.0.4738.0" }, { "brand":"Google Chrome", "version":"98.0.4738.0" } ], "mobile":false, "model":"", "platformVersion":"12.0.1" } ```
Tags
- http:header=accept-ch
- http:header=sec-ch-ua-mobile
- http:header=sec-ch-ua-model
- http:header=user-agent
- http:header=sec-ch-ua-arch
- conneg
- http:header=sec-ch-ua
- http:header=sec-ch-ua-bitness
- http:header=sec-ch-ua-full-version-list
- mobile
- http:header=sec-ch-ua-platform-version
- js
- cito:cites=urn:ietf:rfc:8942
- http:header=sec-ch-ua-full-version
- <meta http-equiv="accept-ch"/>
- cito:cites=urn:ietf:rfc:1945
- http
- http:header=sec-ch-ua-platform
- wikipedia:en=HTTP_Client_Hints
Annotators
URL
-
-
developer.mozilla.org developer.mozilla.org
-
- Note: Client hints can also be specified in HTML using the <meta> element with the
http-equiv
attribute.
html <meta http-equiv="Accept-CH" content="Width, Downlink, Sec-CH-UA" />
- Example:
http HTTP/1.1 200 OK Content-Type: text/html Accept-CH: Sec-CH-Prefers-Reduced-Motion Vary: Sec-CH-Prefers-Reduced-Motion Critical-CH: Sec-CH-Prefers-Reduced-Motion
- Note: Client hints can also be specified in HTML using the <meta> element with the
Tags
- http:header=accept-ch
- http:header=critical-ch
- mobile
- http:header=sec-ch-prefers-reduced-motion
- http:header=vary
- cito:cites=urn:ietf:rfc:8942
- <meta http-equiv="accept-ch"/>
- conneg
- http
- cito:cites=urn:ietf:id:draft-davidben-http-client-hint-reliability
- wikipedia:en=HTTP_Client_Hints
Annotators
URL
-
-
developer.mozilla.org developer.mozilla.org
-
http Sec-CH-UA-Mobile: ?1
-
-
wicg.github.io wicg.github.io
-
```idl dictionary NavigatorUABrandVersion { DOMString brand; DOMString version; };
dictionary UADataValues { DOMString architecture; DOMString bitness; sequence<NavigatorUABrandVersion> brands; DOMString formFactor; sequence<NavigatorUABrandVersion> fullVersionList; DOMString model; boolean mobile; DOMString platform; DOMString platformVersion; DOMString uaFullVersion; // deprecated in favor of fullVersionList boolean wow64; };
dictionary UALowEntropyJSON { sequence<NavigatorUABrandVersion> brands; boolean mobile; DOMString platform; };
[Exposed=(Window,Worker)] interface NavigatorUAData { readonly attribute FrozenArray<NavigatorUABrandVersion> brands; readonly attribute boolean mobile; readonly attribute DOMString platform; Promise<UADataValues> getHighEntropyValues (sequence<DOMString> hints ); UALowEntropyJSON toJSON (); };
interface mixin NavigatorUA { [SecureContext] readonly attribute NavigatorUAData userAgentData ; };
Navigator includes NavigatorUA; WorkerNavigator includes NavigatorUA; ```
Tags
- http:header=accept-ch
- http:header=sec-ch-ua-mobile
- http:header=sec-ch-ua-form-factor
- http:header=sec-ch-ua-model
- http:header=user-agent
- http:header=sec-ch-ua-arch
- conneg
- http:header=sec-ch-ua
- http:header=sec-ch-ua-bitness
- http:header=sec-ch-ua-full-version-list
- mobile
- http:header=sec-ch-ua-platform-version
- cito:cites=urn:ietf:rfc:8942
- http:header=sec-ch-ua-full-version
- http:header=sec-ch-ua-wow64
- http
- http:header=sec-ch-ua-platform
- wikipedia:en=HTTP_Client_Hints
Annotators
URL
-
-
developers.google.com developers.google.com
-
-
```js exports.handler = async (event) => { if (event.headers != undefined) { const headers = toLowerCaseProperties(event.headers);
if (headers['sec-websocket-protocol'] != undefined) { const subprotocolHeader = headers['sec-websocket-protocol']; const subprotocols = subprotocolHeader.split(','); if (subprotocols.indexOf('myprotocol') >= 0) { const response = { statusCode: 200, headers: { "Sec-WebSocket-Protocol" : "myprotocol" } }; return response; } } } const response = { statusCode: 400 }; return response;
};function toLowerCaseProperties(obj) { var wrapper = {}; for (var key in obj) { wrapper[key.toLowerCase()] = obj[key]; } return wrapper; } ```
-
- Jun 2023
-
developer.mozilla.org developer.mozilla.org
-
abnf Retry-After: <http-date> Retry-After: <delay-seconds>
http Retry-After: Wed, 21 Oct 2015 07:28:00 GMT Retry-After: 120
-
-
developer.mozilla.org developer.mozilla.org
-
A Retry-After header might be included to this response indicating how long to wait before making a new request.
http HTTP/1.1 429 Too Many Requests Content-Type: text/html Retry-After: 3600
-
- May 2023
-
www.bortzmeyer.org www.bortzmeyer.org
-
datatracker.ietf.org datatracker.ietf.org
-
developer.mozilla.org developer.mozilla.org
-
abnf Accept-Ranges: <range-unit> Accept-Ranges: none
-
-
developer.mozilla.org developer.mozilla.org
-
abnf Range: <unit>=<range-start>- Range: <unit>=<range-start>-<range-end> Range: <unit>=<range-start>-<range-end>, <range-start>-<range-end> Range: <unit>=<range-start>-<range-end>, <range-start>-<range-end>, <range-start>-<range-end> Range: <unit>=-<suffix-length>
-
-
www.youtube.com www.youtube.com
-
-
www.artificialworlds.net www.artificialworlds.net
-
www.artificialworlds.net www.artificialworlds.net
-
stackoverflow.com stackoverflow.com
-
byterot.blogspot.com byterot.blogspot.com
-
```http GET http://localhost:50714/api/Car HTTP/1.1 User-Agent: Fiddler Host: localhost:50714 Range: x-entity=2-5
HTTP/1.1 206 Partial Content Cache-Control: no-cache Pragma: no-cache Content-Type: application/json; charset=utf-8 Content-Range: x-entity 2-5/10 Expires: -1 Server: Microsoft-IIS/8.0 Date: Tue, 31 Jul 2012 19:00:19 GMT Content-Length: 447
[{"Id":3,"Make":"Toyota","Model":"Yaris","BuildYear":2003,"Price":3750.0,... ```
-
-
-
```http GET /users
200 OK Accept-Ranges: users Content-Range: users 0-9/200
[ 0, …, 9 ] ```
```http GET /users Range: users=0-9
206 Partial Content Accept-Ranges: users Content-Range: users 0-9/200
[ 0, …, 9 ] ```
```http GET /users Range: users=0-9,50-59
206 Partial Content Accept-Ranges: users Content-Type: multipart/mixed; boundary=next
--next Content-Range: users 0-9/200
[ 0, …, 9 ]
--next Content-Range: users 50-59/200
[ 50, …, 59 ]
--next-- ```
```http GET /users?name=Fred
206 Partial Content Accept-Ranges: users Content-Range: users 0-100/*
[ 0, …, 100 ] ```
-
-
stackoverflow.com stackoverflow.com
-
www.bortzmeyer.org www.bortzmeyer.org
-
datatracker.ietf.org datatracker.ietf.org
-
developer.mozilla.org developer.mozilla.orgIf-Match1
-
stackoverflow.com stackoverflow.com
-
github.com github.com
-
Figured it out. Cache-Control header is required.
js const headers = { 'Cache-Control': 'public, max-age=604800' }; const request = new Request('https://foobar.com/') const cacheResponse = new Response('bar',{ headers }) const cache = caches.default await cache.put(request, cacheResponse) const response = await cache.match(request);
-
-
www.npmjs.com www.npmjs.com
-
npx check-my-headers https://example.com
-
-
Tags
- hsts
- wikipedia:en=Data_breach
- wikipedia:en=Session_hijacking
- wikipedia:en=Clickjacking
- wikipedia:en=Cross-site_request_forgery
- http:header=x-frame-options
- security
- wikipedia:en=Man-in-the-middle_attack
- http:header=x-content-type-options
- http:header=content-security-policy
- http:header=strict-transport-security
- http
- csp
- http:header=referrer-policy
- sri
Annotators
URL
-
-
datatracker.ietf.org datatracker.ietf.org
-
developer.mozilla.org developer.mozilla.org
-
itsjameswhite.medium.com itsjameswhite.medium.com
-
Add more languages to be sent in the HTTP
Accept-Language
header field:http Accept-Language: en-US,en;q=0.9,fr;q=0.8`
-
- Apr 2023
-
developer.mozilla.org developer.mozilla.org
-
developer.mozilla.org developer.mozilla.org
Tags
- cito:cites=urn:ietf:rfc:6455
- http:header=sec-websocket-protocol
- http:header=sec-websocket-key
- http:header=sec-websocket-extensions
- websocket
- http:header=sec-websocket-accept
- cito:cites=urn:ietf:rfc:7230
- cito:cites=urn:ietf:rfc:7540
- http:header=upgrade:websocket
- http:header=connection:upgrade
- http:header=sec-websocket-version
- http
Annotators
URL
-
-
developer.mozilla.org developer.mozilla.org
-
datatracker.ietf.org datatracker.ietf.org
- Mar 2023
-
developer.mozilla.org developer.mozilla.org
-
developer.mozilla.org developer.mozilla.org
-
simonhearne.com simonhearne.com
-
developers.cloudflare.com developers.cloudflare.com
-
<table><tbody><tr><th colspan="4" rowspan="1">Status</th><th colspan="4" rowspan="1">Description</th></tr><tr><td colspan="5" rowspan="1">HIT</td><td colspan="5" rowspan="1">The resource was found in Cloudflare’s cache.</td></tr><tr><td colspan="5" rowspan="1">MISS</td><td colspan="5" rowspan="1">The resource was not found in Cloudflare’s cache and was served from the origin web server.</td></tr><tr><td colspan="5" rowspan="1">NONE/UNKNOWN</td><td colspan="5" rowspan="1">Cloudflare generated a response that denotes the asset is not eligible for caching. This may have happened because:
- A Worker generated a response without sending any subrequests. In this case, the response did not come from cache, so the cache status will be
none/unknown
.- A Worker request made a subrequest (
fetch
). In this case, the subrequest will be logged with a cache status, while the main request will be logged withnone/unknown
status (the main request did not hit cache, since Workers sits in front of cache).- A Firewall rule was triggered to block a request. The response will come from the edge network before it hits cache. Since there is no cache status, Cloudflare will log as
none/unknown
.- A redirect page rule caused the edge network to respond with a redirect to another asset/URL. This redirect response happens before the request reaches cache, so the cache status is
</td></tr><tr><td colspan="5" rowspan="1">EXPIRED</td><td colspan="5" rowspan="1">The resource was found in Cloudflare’s cache but was expired and served from the origin web server.</td></tr><tr><td colspan="5" rowspan="1">STALE</td><td colspan="5" rowspan="1">The resource was served from Cloudflare’s cache but was expired. Cloudflare could not contact the origin to retrieve an updated resource.</td></tr><tr><td colspan="5" rowspan="1">BYPASS</td><td colspan="5" rowspan="1">The origin server instructed Cloudflare to bypass cache via a Cache-Control header set tonone/unknown
.no-cache
,private
, ormax-age=0
even though Cloudflare originally preferred to cache the asset. BYPASS is returned when enabling Origin Cache-Control. Cloudflare also sets BYPASS when your origin web server sends cookies in the response header.</td></tr><tr><td colspan="5" rowspan="1">REVALIDATED</td><td colspan="5" rowspan="1">The resource is served from Cloudflare’s cache but is stale. The resource was revalidated by either anIf-Modified-Since
header or anIf-None-Match header
.</td></tr><tr><td colspan="5" rowspan="1">UPDATING</td><td colspan="5" rowspan="1">The resource was served from Cloudflare’s cache and was expired, but the origin web server is updating the resource. UPDATING is typically only seen for very popular cached resources.</td></tr><tr><td colspan="5" rowspan="1">DYNAMIC</td><td colspan="5" rowspan="1">Cloudflare does not consider the asset eligible to cache and your Cloudflare settings do not explicitly instruct Cloudflare to cache the asset. Instead, the asset was requested from the origin web server. Use Page Rules to implement custom caching options.</td></tr></tbody></table> - A Worker generated a response without sending any subrequests. In this case, the response did not come from cache, so the cache status will be
-
-
www.wireshark.org www.wireshark.org
-
Use Follow TCP Stream to display HTTP response chunks
-
-
developer.mozilla.org developer.mozilla.org
-
Chunked encoding is useful when larger amounts of data are sent to the client and the total size of the response may not be known until the request has been fully processed. For example, when generating a large HTML table resulting from a database query or when transmitting large images.A chunked response looks like this:
```http HTTP/1.1 200 OK Content-Type: text/plain Transfer-Encoding: chunked
7\r\n Mozilla\r\n 11\r\n Developer Network\r\n 0\r\n \r\n ```
-
chunked Data is sent in a series of chunks. The Content-Length header is omitted in this case and at the beginning of each chunk you need to add the length of the current chunk in hexadecimal format, followed by '\r\n' and then the chunk itself, followed by another '\r\n'. The terminating chunk is a regular chunk, with the exception that its length is zero. It is followed by the trailer, which consists of a (possibly empty) sequence of header fields.
-
```abnf Transfer-Encoding: chunked Transfer-Encoding: compress Transfer-Encoding: deflate Transfer-Encoding: gzip
// Several values can be listed, separated by a comma Transfer-Encoding: gzip, chunked ```
-
-
developer.mozilla.org developer.mozilla.org
-
www.w3.org www.w3.org
-
sergiodxa.com sergiodxa.com
-
Send the 304 Not Modified response
```js import etag from "etag"; import { renderToString } from "react-dom/server"; import type { EntryContext, HandleDataRequestFunction } from "remix"; import { RemixServer } from "remix";
export default function handleRequest( request: Request, status: number, headers: Headers, remixContext: EntryContext ) { let markup = renderToString( <RemixServer context={remixContext} url={request.url} /> );
headers.set("Content-Type", "text/html"); headers.set("ETag", etag(markup));
// check if the
If-None-Match
header matches the ETag if (request.headers.get("If-None-Match") === headers.get("ETag")) { // and send an empty Response with status 304 and the headers. return new Response("", { status: 304, headers }); }return new Response("<!DOCTYPE html>" + markup, { status, headers }); }
export let handleDataRequest: HandleDataRequestFunction = async ( response: Response, { request } ) => { let body = await response.text();
if (request.method.toLowerCase() === "get") { response.headers.set("etag", etag(body)); // As with document requests, check the
If-None-Match
header // and compare it with the Etag, if they match, send the empty 304 Response if (request.headers.get("If-None-Match") === response.headers.get("ETag")) { return new Response("", { status: 304, headers: response.headers }); } }return response; }; ```
-
-
developer.mozilla.org developer.mozilla.orgETag1
-
developer.mozilla.org developer.mozilla.orgTrailer1
-
```http HTTP/1.1 200 OK Content-Type: text/plain Transfer-Encoding: chunked Trailer: Expires
7\r\n Mozilla\r\n 9\r\n Developer\r\n 7\r\n Network\r\n 0\r\n Expires: Wed, 21 Oct 2015 07:28:00 GMT\r\n \r\n ```
-
-
Tags
Annotators
URL
-
-
developers.cloudflare.com developers.cloudflare.com
-
developer.mozilla.org developer.mozilla.org
-
gist.github.com gist.github.com
-
You'll notice that for the app/routes/jokes/$jokeId.tsx route in addition to Cache-Control we've also set Vary header to Cookie. This is because we're returning something that's specific to the user who is logged in. So we want the cache to associated to that particular Cookie value and not shared with different users, so the browser and CDN will not deliver the cached value if the cookie is different from the cached response's cookie.
-
-
-
-
```js import parseCacheControl from "parse-cache-control";
export function headers({ loaderHeaders, parentHeaders, }: { loaderHeaders: Headers; parentHeaders: Headers; }) { const loaderCache = parseCacheControl( loaderHeaders.get("Cache-Control") ); const parentCache = parseCacheControl( parentHeaders.get("Cache-Control") );
// take the most conservative between the parent and loader, otherwise // we'll be too aggressive for one of them. const maxAge = Math.min( loaderCache["max-age"], parentCache["max-age"] );
return { "Cache-Control":
max-age=${maxAge}
, }; } ```
```js import { renderToString } from "react-dom/server"; import { RemixServer } from "@remix-run/react"; import type { EntryContext } from "@remix-run/node"; // or cloudflare/deno
export default function handleRequest( request: Request, responseStatusCode: number, responseHeaders: Headers, remixContext: EntryContext ) { const markup = renderToString( <RemixServer context={remixContext} url={request.url} /> );
responseHeaders.set("Content-Type", "text/html"); responseHeaders.set("X-Powered-By", "Hugs");
return new Response("<!DOCTYPE html>" + markup, { status: responseStatusCode, headers: responseHeaders, }); } ```
Tags
Annotators
URL
-
- Feb 2023
-
developers.cloudflare.com developers.cloudflare.com
-
blog.cloudflare.com blog.cloudflare.com
- Jan 2023
-
www.smashingmagazine.com www.smashingmagazine.com
-
aohorodnyk.com aohorodnyk.com