Runtime APIs
Fetch events
How OpenOrange supplies the Worker fetch execution context.
Status: Partial
Configuration
No Orange-specific configuration is required. A module Worker exports a
Wrangler-compatible fetch(request, env, context) handler.
How it works
OpenOrange creates one execution context per request. context.props contains
the runtime-supplied properties, context.exports contains the supplied
loopback export object, and context.waitUntil(promise) registers background
work. The runtime controller drains all registered promises, including work
registered while an earlier promise is settling, and retains fulfilled and
rejected outcomes for later diagnostics.
- The controlled loader constructs an extensible environment from configured bindings, installs the Cloudflare global manifest, imports the Worker, preserves its named exports, and rejects unsupported event handlers.
- The
env,exports,withEnv(),withExports(), andwithEnvAndExports()exports ofcloudflare:workersfollow workerd:envis readable while the Worker module evaluates, both proxies follow the current async-context override, and mutations throughenvchange the environment object passed to handlers. - Orange does not read the
disallow_importable_envflag. - Durable Object classes appear in
context.exportsandexportsas their namespaces. WorkerEntrypointis exported as a base class that storesctxandenv. A default export that extendsWorkerEntrypointhandles each request with a new instance.- Dispatch invokes the default module Worker’s
fetchhandler and requires it to return an OpenOrangeResponse. - The dispatch result includes that response and a promise for all
waitUntil()outcomes.
For development, a dedicated Node.js child owns the HTTP listener and runtime lifecycle. It streams request and response bodies, dispatches requests inside the child, and reports readiness, startup failures, request failures, background failures, signals, and clean shutdown to the parent CLI over IPC.
request.url uses the request’s Host header. Under orange serve, its scheme
is https: when the cluster’s gateway sends X-Forwarded-Proto: https, so a
Worker sees the URL its client used, as on Cloudflare. orange dev takes
requests directly and ignores that header.
Unsupported context APIs fail when called instead of being silently ignored.
ctx.cache is undefined, as in local workerd.
Conformance
The conformance check compiles a module Worker against the pinned
ExportedHandler<Env> fetch signature and proves an invalid response type is
rejected. The generated event registry check verifies the context has exactly
the Cloudflare ExecutionContext keys and is assignable to its generic contract.
Runtime tests cover entrypoint ordering, named exports, environment injection,
response validation, waitUntil() draining, each unsupported API, and the
dedicated process lifecycle over a real HTTP socket.
Deviations
passThroughOnException()is a no-op, because Orange has no origin to fall back to. An exception after the call still fails the request with a 500 response.abort()releases the context’s I/O objects and throws the reason, because Node.js cannot stop running JavaScript.context.cacheandcontext.accessareundefined, as in local workerd.context.tracingruns every span callback with a no-op span whoseisTracedisfalse, because Orange has no trace collector.- Background promise outcomes are returned to the runtime process, which reports rejected work to the parent CLI for local diagnostics.
Compatibility
From the latest conformance run. Scores on the compatibility page; every binding on the status page.
Workers
Runs on Node.js runtime with workerd-shaped globals, cloudflare:* and node:* modules.
fetch, scheduled, and queue handlers run unchanged. Compatibility dates and flags are not applied.
Scales by Runner count. Stateless requests go to any runner in the pool. Not measured across runners here.
In the feature matrix
Supportedvars (string values)Each string in vars appears on env as a string.Wrangler converts each string var to a plain_text binding, and Orange puts the string on env. 4 files
- Notes
- Named environments follow Wrangler's rules, because Orange reads the config with Wrangler's unstable_readConfig.
- Source
- src/config/load-wrangler.ts:787-792packages/runtime-node/src/runner.ts:471-473src/runtime/bindings.test.ts:138-148src/config/load-wrangler.test.ts:13-32
Supportedvars (JSON values)Each non-string value in vars appears on env as a parsed JSON value.Wrangler converts each non-string var to a json binding, and Orange puts the value on env. 3 files
- Notes
- A .dev.vars or .env key with the same name replaces the JSON value with a string.
- Source
- src/config/load-wrangler.ts:793-794packages/runtime-node/src/runner.ts:471-473src/runtime/bindings.test.ts:138-148
Supported.dev.vars secretswrangler dev loads keys from .dev.vars (or .dev.vars.<env>) into env as secret text.Orange calls Wrangler's unstable_getVarsForDev, so .dev.vars keys reach env as strings, like wrangler dev. 3 files
- Notes
- A .dev.vars key replaces a var with the same name. It does not replace a binding of another type, such as a Secrets Store secret. When the config has secrets.required, only listed keys and keys that are also vars load, and a missing required key prints a warning.
- Source
- src/config/load-wrangler.ts:889-919src/config/load-wrangler.ts:1435-1460src/runtime/bindings.test.ts:138-148
Supported.env secretsWhen no .dev.vars file exists, wrangler dev loads .env files into env as secret text.Orange gets the same behavior from Wrangler's unstable_getVarsForDev. A .env key reaches env as a string. 2 files
- Notes
- Orange passes no custom env file list, so Wrangler reads its default .env files. CLOUDFLARE_LOAD_DEV_VARS_FROM_DOT_ENV and CLOUDFLARE_INCLUDE_PROCESS_ENV apply as in Wrangler. Verified by loading a config with a .env file and no .dev.vars.
- Not verified by a test
- Not covered by a repository test. Verified once by a manual config load on the devbox.
- Source
- src/config/load-wrangler.ts:893-906src/config/load-wrangler.ts:1435-1460
Supportedctx.exports loopback bindingsctx.exports exposes this Worker's entrypoints as service stubs and its Durable Object classes as namespaces.Builds ctx.exports from the Worker's named exports: entrypoints become loopback service stubs, and Durable Object classes become namespaces, including classes without a binding. 1/1 pass · 4 files
- Notes
- ctx.exports in a Durable Object throws DurableObjectState.exports is not implemented. import { exports } from "cloudflare:workers" reads the same object.
- Tests
-
- api-tests--importable-exports-test › importableExports Pass
- Source
- packages/runtime-node/src/bindings/service.ts:529-554packages/runtime-node/src/runtime.ts:168-175packages/runtime-node/src/runner.ts:649-674packages/runtime-node/src/bindings/durable-objects/state.ts:374-378
Partialimport { env } from "cloudflare:workers"The env object is importable at module scope and in handlers.The importable env is the same object as the handler env, readable while the module evaluates. 0/2 pass · 2 files
- Notes
- importable-env-test fails because the runner drops its KV binding. disable-importable-env-test fails because Orange ignores the disallow_importable_env flag.
- Tests
-
- api-tests--importable-env-test › importableEnv 🍊 open-orange v0.0.1 · by rivet.dev | | Worker api-tests--importable-env-test Fail · File fails at load
- api-tests--disable-importable-env-test › test 🍊 open-orange v0.0.1 · by rivet.dev | | Worker api-tests--disable-importable-env-test Fail · File fails at load
- Source
- packages/runtime-node/src/modules/cloudflare-workers/env.ts:38-85packages/runtime-node/src/runtime.ts:145-146
Supportedassets bindingassets.binding gives the Worker a Fetcher for its static assets.env.ASSETS.fetch() serves the assets directory with not_found_handling and follows redirects like a Fetcher. 3 files
Supportedfetch handler (object default export)export default { fetch(request, env, ctx) } handles each HTTP request.Each inbound HTTP request calls fetch(request, env, ctx) with a new ExecutionContext. 1/1 pass · 3 files
- Notes
- A handler that throws gives a plain-text 500 Internal Server Error, not the Cloudflare 1101 error page. A non-Response result fails with Worker fetch handler must return a Response.
- Tests
-
- api-tests--fetch-test › test Pass
- Source
- packages/runtime-node/src/runtime.ts:75-82packages/runtime-node/src/events/fetch.ts:27-61packages/runtime-node/src/runner.ts:951-1015
Supportedfetch handler (WorkerEntrypoint class default export)export default class extends WorkerEntrypoint { fetch(request) } creates an instance per request.Constructs the class with (ctx, env) for each request and calls its fetch(request). 1/1 pass · 2 files
- Notes
- A class without fetch() loads, and each request fails with Handler does not export a fetch() function., as in workerd.
- Tests
-
- api-tests--js-rpc-test › defaultExportClass Pass
- Source
- packages/runtime-node/src/runtime.ts:65-76packages/runtime-node/src/runtime.ts:154-159
PartialNamed WorkerEntrypoint exportsNamed entrypoint exports receive fetch, RPC, and connect calls from service bindings, including bindings from other Workers.Named entrypoints receive fetch, RPC, and connect calls from this Worker's own service bindings and ctx.exports. 2/3 pass · 2 files
- Notes
- Other Workers cannot call them, because cross-Worker service bindings are stubs. js-rpc-test namedServiceBinding times out (cause not checked). extendingEntrypointClasses and testConstructEntrypoint pass.
- Not verified by a test
- The cause of the namedServiceBinding timeout is not checked.
- Tests
-
- api-tests--js-rpc-test › extendingEntrypointClasses Pass
- api-tests--js-rpc-test › testConstructEntrypoint Pass
- api-tests--js-rpc-test › namedServiceBinding TimeoutError: The operation was aborted due to timeout Fail · Hangs (60s timeout)
- Source
- packages/runtime-node/src/bindings/service.ts:97-130packages/runtime-node/src/bindings/service.ts:529-553