---
description: Reference for the request metadata, identity, and device posture Gateway sends to a Worker invoked by a policy using the Forward action.
title: Available context
image: https://developers.cloudflare.com/cloudflare-one/traffic-controls/integrate-workers/available-context/og.png?v=3c6953310bfd9c88
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/cloudflare-one/llms.txt  
> Use this file to discover all available pages before exploring further.

# Available context

Last updated Oct 15, 2026|Copy as Markdown| [View as Markdown](https://developers.cloudflare.com/cloudflare-one/traffic-controls/integrate-workers/available-context/index.md)| [Agent setup](https://developers.cloudflare.com/agent-setup/)

Public beta

The Gateway Forward action is available in public beta on all Zero Trust plans. Workers usage is subject to [Workers pricing](https://developers.cloudflare.com/workers/platform/pricing/).

Gateway passes `context` as the second argument to `GatewayMiddleware.handle(request, context, next)`. Context describes the original request when Gateway selects a [Forward policy](https://developers.cloudflare.com/cloudflare-one/traffic-controls/integrate-workers/forward-traffic/). Modifying the `Request` does not update context.

Field names use camelCase. Optional fields are omitted when unavailable, and empty metadata lists are omitted. Availability depends on the connection method, destination, and authenticated session. Check optional values before using them.

## TypeScript types

Install [`@cloudflare/zt-types` ↗︎](https://www.npmjs.com/package/@cloudflare/zt-types) version `2026.10.1` or later in your Worker project:

npmyarnpnpmbun

```
npm i -D @cloudflare/zt-types
```

```
yarn add -D @cloudflare/zt-types
```

```
pnpm add -D @cloudflare/zt-types
```

```
bun add -d @cloudflare/zt-types
```

Use `import type` for Gateway types, as shown in the [example](#example) and each [Worker template](https://developers.cloudflare.com/cloudflare-one/traffic-controls/integrate-workers/worker-templates/). These imports are removed when TypeScript compiles and add no runtime dependency. JavaScript examples omit the type imports and annotations and do not need this package. The package exports the following Gateway types:

| Type | Description |
| --- | --- |
| `GatewayMiddlewareContext` | Request metadata, identity getter, and device posture getter. |
| `GatewayMiddlewareNext` | Continuation that sends a `Request` through Gateway and returns a `Promise<Response>`. |
| `GatewayIdentity` | User identity returned by `identity()`. |
| `GatewayIdentityGroup` | A group in the user's identity. |
| `GatewayDevicePosture` | Device posture returned by `devicePosture()`. |
| `GatewayDevicePostureChecks` | Passed posture check identifiers. |

## Request and connection fields

| Field | Type | Description |
| --- | --- | --- |
| `srcIp` | `string` | Source IP address as seen by Gateway. Use this field instead of a client-supplied IP header. |
| `srcPort` | `number` | Source port. |
| `dstIp` | `string`, optional | Destination IP address, when available. |
| `dstPort` | `number`, optional | Destination port, when available. |
| `networkProtocol` | `string` | Network transport protocol, such as `tcp`. |
| `sni` | `string`, optional | Server Name Indication from the TLS connection. |
| `onrampType` | `string`, optional | Connection method used to reach Gateway. |
| `vnetId` | `string`, optional | Virtual network identifier. |
| `proxyEndpoint` | `string`, optional | Proxy endpoint associated with the connection. |
| `internalSrcIp` | `string`, optional | Internal source IP address, when available. |
| `accountId` | `string` | Cloudflare account identifier. |
| `policyId` | `string` | UUID of the Forward policy that selected this Worker. |
| `host` | `string` | Original request host. |
| `uri` | `string` | Normalized original request URL. |
| `embeddedProtocols` | `readonly string[]`, optional | Detected protocols embedded in HTTP traffic. |
| `domainCategories` | `readonly number[]`, optional | Destination domain category IDs. |

`context.uri` includes the scheme and authority. Normalization removes default ports and fragments, sorts query parameters, and normalizes encoding. It can differ from `request.url`. Use `request.url` when operating on the request itself and `context.uri` when comparing normalized metadata.

Use standard `Request` APIs to access the method, headers, cookies, and body. Context does not include custom function results, DLP match details, or raw internal device records.

## Identity

Call `await context.identity()` only when your script needs identity associated with the Gateway session. Its return type is `Promise<GatewayIdentity | null>`.

The awaited call behaves as follows:

- Returns an identity object when the user is identified.
- Returns `null` when there is no identified user.
- Throws an error if Gateway cannot retrieve identity.

| Field | Type | Description |
| --- | --- | --- |
| `email` | `string`, optional | User email address. |
| `name` | `string`, optional | User display name. |
| `groups` | `readonly GatewayIdentityGroup[]`, optional | Group memberships. Each group can have optional `id`, `email`, and `name` fields. |
| `samlAttributes` | `readonly string[]`, optional | SAML attributes associated with the identity. |
| `oidcClaims` | `readonly string[]`, optional | OIDC claims associated with the identity. This is a list, rather than a decoded token object. |

Use Gateway-provided identity for user-aware logic. Client-supplied identity headers are not an authoritative substitute.

Check for a missing identity (`!identity`) to explicitly allow or deny anonymous traffic.

## Device posture

Call `await context.devicePosture()` to retrieve passed posture check identifiers:

```json
{
	"checks": {
		"passed": ["<POSTURE_CHECK_UUID>"]
	}
}
```

`checks.passed` is a read-only list of posture check UUIDs. An empty array means no checks passed. When no device is registered, the getter resolves to `{ checks: { passed: [] } }`. A Worker that requires a specific passed check must deny this request.

If Gateway cannot retrieve device posture, awaiting `devicePosture()` throws an error. Handle this separately from a session with no passed checks.

The getter does not return raw test results or a list of failed checks.

## Handle identity and posture errors

Gateway still invokes the Worker if it cannot retrieve identity or device posture. If either awaited call throws and your Worker does not catch the error, Gateway returns HTTP `500`.

Use `try/catch` to choose how your Worker handles these errors. The [example](#example) returns HTTP `503` for retrieval errors and HTTP `403` when identity or a required posture check is missing.

If your application deliberately allows traffic when Gateway cannot retrieve identity or posture, return `next(request)` from the `catch` block. This continues the request without requiring the missing result.

Only use this approach before calling `next()`. [Call `next()` at most once per invocation](https://developers.cloudflare.com/cloudflare-one/traffic-controls/integrate-workers/forward-traffic/#how-it-works).

## Example

This script requires an identity email and a specific passed posture check before continuing. Anonymous traffic and devices without the required check receive a synthetic `403` response.

Identity or posture retrieval errors receive `503`. Replace `<POSTURE_CHECK_UUID>` with a check in your account.

*src/index.jsjs*

```js
import { WorkerEntrypoint } from "cloudflare:workers";

export class GatewayMiddleware extends WorkerEntrypoint {
	async handle(request, context, next) {
		try {
			const identity = await context.identity();
			if (!identity?.email) {
				return new Response(null, { status: 403 });
			}
			const passed = (await context.devicePosture())?.checks.passed ?? [];
			if (!passed.includes("<POSTURE_CHECK_UUID>")) {
				return new Response(null, { status: 403 });
			}
		} catch {
			return new Response(null, { status: 503 });
		}
		return next(request);
	}
}
```

*src/index.tsts*

```ts
import { WorkerEntrypoint } from "cloudflare:workers";
import type {
	GatewayMiddlewareContext,
	GatewayMiddlewareNext,
} from "@cloudflare/zt-types";

export class GatewayMiddleware extends WorkerEntrypoint {
	async handle(
		request: Request,
		context: GatewayMiddlewareContext,
		next: GatewayMiddlewareNext,
	): Promise<Response> {
		try {
			const identity = await context.identity();
			if (!identity?.email) {
				return new Response(null, { status: 403 });
			}
			const passed = (await context.devicePosture())?.checks.passed ?? [];
			if (!passed.includes("<POSTURE_CHECK_UUID>")) {
				return new Response(null, { status: 403 });
			}
		} catch {
			return new Response(null, { status: 503 });
		}
		return next(request);
	}
}
```

When the requirement can be expressed using built-in [identity selectors](https://developers.cloudflare.com/cloudflare-one/traffic-controls/identity-selectors/) or [device posture selectors](https://developers.cloudflare.com/cloudflare-one/traffic-controls/http-policies/#device-posture), configure it in your Gateway filtering policy. Use Worker logic for requirements that need custom code.

## Header representation

Gateway combines repeated `Cookie` headers with semicolons and other repeated headers with commas. `Set-Cookie` values retain separate entries. Use `response.headers.getSetCookie()` to read the individual response cookies. When modifying headers, copy them with `new Headers(response.headers)` to preserve their representation.

Was this helpful?

YesNo

## On this page

[![](https://developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/cloudflare-one/traffic-controls/integrate-workers/available-context/#page","headline":"Available context","description":"Reference for the request metadata, identity, and device posture Gateway sends to a Worker invoked by a policy using the Forward action.","url":"https://developers.cloudflare.com/cloudflare-one/traffic-controls/integrate-workers/available-context/","inLanguage":"en","image":"https://developers.cloudflare.com/cloudflare-one/traffic-controls/integrate-workers/available-context/og.png?v=3c6953310bfd9c88","dateModified":"2026-10-15","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```
