/:

The /: form addresses the edge worker of a deployment directly: the text before the first colon selects the route, and everything after it becomes the pathname that the worker sees.

Syntax

plain
https://name.rt.ht/:
https://name.rt.ht/:api/users
https://name.rt.ht/:/api/users
https://name.rt.ht/docs/:api

The text before the first : selects the route, and the text after it is the pathname the worker sees. A relative form works in a page: on https://name.rt.ht/docs/, the URL :api means https://name.rt.ht/docs/:api.

Behavior

The first colon

The first : in the path splits it. The text before it selects the route. The text after it becomes the worker's pathname: an empty remainder becomes /, and api/x becomes /api/x. The query string is kept.

URLRouteWorker pathname
https://name.rt.ht/:name/
https://name.rt.ht/:1.jsonname/1.json
https://name.rt.ht/:/api/usersname/api/users
https://name.rt.ht/docs/:apiname/docs/api
Write the slash

<route>: is redirected (307) to <route>/:. A path such as /docs:x belongs to the parent route name, so on a path route write /docs/:x.

Dispatched before the gates

RTEdge.net sends the request to the worker before it reads the deployment. No KV read happens, and edge:user is not applied. A worker that must authenticate checks request.rt.user itself.

The request

request.url keeps the visitor's scheme, host and query string, with the pathname described above. The method, headers and body are preserved.

Other :: names

A ::name that no platform handler claims, and that is not exactly ::kv, ::meta or ::owner at the end of the path, is an ordinary worker path: /::zz reaches the worker as /:zz.

Reserved text

The reserved sequences apply inside worker paths too: ::s, ::i, ::e, ::c, ::u, ::t, ::v, /::edge, and a trailing ::clear or ::qr. Keep them out of worker paths. See Reserved text in paths.

Response

CaseStatusBody
The worker returns a ResponseThe worker's statusThe worker's body and headers. The platform adds an edge-worker header and does not cache the response. Your Cache-Control passes through.
The route has no worker404"Worker does not exist."
The handler returns nothing501"Worker response is undefined."
The handler throws500An "Exception" page: "Worker encountered an exception."

A deployed worker answers its own CORS preflights. Preflights sent from RTCode.io pages are answered by the platform and never reach the worker; preflights from other sites do.

Access

Anyone can call the worker. edge:user is not applied to /: URLs, so the worker decides who may use it. See Protect a worker API.

In the playground

The playground output splits : paths the same way, so fetch(':api') and <iframe src=:1.json> behave as they do on RTEdge.net. A playground worker that returns nothing lets the request fall through to the network, where RTEdge.net would answer with the 501 page. See Playground and edge differences.

Examples

Call the worker from the page

html
<output id=out></output>
<script type=module>
  out.value = JSON.stringify(await fetch(':api/items?limit=5').then(r => r.json()))
</script>
<script type=worker edge io:guest>
  export default { fetch: r => Response.json({ path: new URL(r.url).pathname, query: new URL(r.url).search }) }
</script>

On https://name.rt.ht/docs/, :api/items?limit=5 goes straight to the worker of the route name/docs, with the pathname /api/items and the query ?limit=5. The same code works in the playground.

Show a worker page in a frame

html
<iframe src=:hello></iframe>
<script type=worker edge io:guest>
  export default { fetch: r => new Response('Hello from ' + new URL(r.url).pathname) }
</script>

The frame loads the worker's answer for /hello.

Specifications

Not part of any specification. /: is an RTEdge.net feature. The worker uses these standards and runtimes:

Specification
Fetch Standard, for Request and Response
Cloudflare Workers runtime

Availability

FeaturePlaygroundRTEdge.netNotes
/: worker pathsYesYesThe playground output applies the same split. An undefined response falls through to the network there, and gives a 501 page on RTEdge.net.
edge:user on /:NoNoNot applied in either place. The worker checks request.rt.user.

See also