h:*

The h:* global attributes add a response header to an exported file or worker asset: h:<name>=<value> sends the header <name> with that value.

Syntax

html
<script type=module o:=code.js h:access-control-allow-origin=* h:cache-control="public, max-age=300">…</script>
<img hidden alt o:=signed.pdf h:content-type=application/pdf h:access-control-allow-origin=* src="data:application/pdf;base64,…">

Value

h:name

The attribute name after h: is the header name. The HTML parser lowercases attribute names, so h:cache-control sends cache-control.

value

The header value. Quote a value that contains spaces or =, for example h:cache-control="public, max-age=300".

Several headers

An element can carry any number of h:* attributes. They are kept in order as [name, value] pairs.

Description

On an element with o:, the headers go to the exported file. On an element with worker:fs, they are stored with the worker asset in env.FS[key].headers. On an element with neither, h:* has no effect and is stripped on deploy.

PlaygroundRTEdge.net
What is sentYour h:* headers, then forced origin-agent-cluster: ?1, cache-control: no-store, Referrer-Policy: unsafe-url and the computed content-type. Later keys win.Your h:* headers as written, then the computed content type (only when there is no h:content-type), edge and deploy.
Overriddenh:content-type, h:cache-control, h:origin-agent-cluster and h:referrer-policy. h:set-cookie has no effect.Platform headers take priority over yours. See Platform headers below.
AppliedOther headers, such as CORS headers, content-security-policy and content-disposition.All the others.

h:* applies to files only; it does not apply to the root document.

Usage notes

CORS

Another site can read an export only if the response allows it. Add h:access-control-allow-origin=* to a module, stylesheet or data file that other sites import or fetch. Test it from a page on another site: requests made from RTCode.io pages are not a reliable test.

Caching

RTEdge.net adds no cache-control to a file unless you set h:cache-control. The playground always sends cache-control: no-store, so check caching headers on the deployed file, for example with curl -I. The root document is no-store and cannot be changed with h:*.

Platform headers

RTEdge.net adds headers of its own, and they win over yours: server-actual and server-vendor on every response, strict-transport-security and referrer-policy on *.rt.ht hosts, and Edge: RTEdge.net on custom domains. A value you give for h:edge or h:deploy is combined with the platform value.

Elements that share a name

When several elements export the same file name, the headers of the first element apply. The h:* attributes of later elements are silently ignored.

Worker assets

For worker:fs assets the pairs are kept in env.FS[key].headers. Your worker decides what to send; the Experimental .response getter, described on worker:fs, builds a Response from them. Set o:type, not h:content-type, on assets.

On deploy

Deploy strips every h:* attribute from the served HTML and from export bodies. The deployed source keeps them.

Examples

CORS and caching headers

html
<script type=module o:=code.js h:access-control-allow-origin=* h:cache-control="public, max-age=300">
  export const answer = 42
</script>
<output id=hdrs></output>
<script type=module>
  const r = await fetch('code.js')
  hdrs.value = `${r.headers.get('access-control-allow-origin')} / ${r.headers.get('cache-control')}`
</script>

In the playground the output shows * / no-store: the CORS header applies and cache-control is overridden. After a deploy, curl -I https://<route>/code.js shows both headers as you wrote them.

Specifications

Not part of any specification. h:* is an RTCode.io and RTEdge.net feature.

It builds on these standards:

Specification
RFC 9110: HTTP Semantics
Fetch Standard
MDN: Cross-Origin Resource Sharing (CORS)

Availability

FeaturePlaygroundRTEdge.netNotes
h:* on exportsPartialYesSent as written on RTEdge.net.
h:content-type and h:cache-controlNoYesOverridden in the playground.
CORS, CSP and content-disposition headersYesYesSent as written.
h:* on worker:fs assetsYesYesStored in env.FS[key].headers.
Agent File Sync (Agent Folder Share)YesNoIn an export that holds the whole element, an agent's change to a h:* attribute is restored. Edit it in 📄.html. Chrome or Edge on desktop.

See also