Octov0.4.2
ReferenceConnectors

HTTP

The HTTP server connector, HTTP client connector, and the rest block.

Octo ships two HTTP connectors: http, a server connector whose sources turn inbound requests into flow executions and write the flow's result back as the response, and http-client, an outbound client that the rest block runs requests through.

http connector

The http connector (label: HTTP Server) owns a single HTTP server — host, port, base path, server timeouts, and CORS. Each flow fronted by an http source registers a route on that shared server.

Provides a source: yes — the HTTP route source (below). Blocks that bind to it: none; the rest block binds to http-client.

Settings

SettingTypeRequiredDefaultDescription
hoststringNo$HTTP_HOST, else 0.0.0.0Bind address. An explicit value wins over the HTTP_HOST environment variable.
portintNo$HTTP_PORT, else 8080Bind port. An explicit 0 lets the OS pick a free port. An explicit value wins over the HTTP_PORT environment variable.
basePathstringNoPrefix for all routes (e.g. /api/v1).
keepAlivebooleanNoEnable HTTP keep-alives.
requestTimeoutdurationNo30sHow long a handler waits for the flow to finish.
readTimeoutdurationNoServer read timeout.
writeTimeoutdurationNoServer write timeout.
idleTimeoutdurationNoServer idle timeout.
corsobjectNoCross-origin resource sharing. Inert unless allowedOrigins is set.

Duration settings accept Go duration strings (5s, 250ms).

CORS settings (cors)

CORS is off unless allowedOrigins is non-empty. When set, the connector answers OPTIONS preflights and adds CORS headers on every route.

SettingTypeRequiredDefaultDescription
allowedOriginsstring[]NoOrigins allowed to make cross-origin requests. Exact matches; a single * allows any origin.
allowedMethodsstring[]NoGET, POST, PUT, PATCH, DELETE, HEAD, OPTIONSMethods allowed on preflight.
allowedHeadersstring[]Noecho requested headersRequest headers allowed on preflight; when unset, the requested headers are echoed back.
exposedHeadersstring[]NoResponse headers exposed to the browser on actual responses.
allowCredentialsbooleanNofalseAllow credentialed (cookie/authorization) requests. When true, the origin is echoed rather than *, per the CORS spec.
maxAgedurationNoHow long a browser may cache the preflight response.

http source

Each http source binds one route pattern to a flow. The request becomes the flow's input message; the flow's final message becomes the response.

SettingTypeRequiredDefaultDescription
pathstringYesRoute pattern; {name} params become vars.name.
headersstring[]NoRequest header names to copy into variables.
responseHeadersstring[]NoResponse header names to propagate from message variables of the same name after the flow completes. Content-Type is managed by the source.
correlationIdHeaderstringNoHeader to source the correlation ID from.
rawBodyVarstringNoCapture the exact request bytes into vars.<name> (e.g. to verify an HMAC signature over the raw body).
rawBodybooleanNofalseSource the request as raw content: skip the JSON check and store the body as {contentType, rawData} using the request's Content-Type, instead of parsing it. Lets non-JSON payloads (forms, XML, binary text) enter the flow.
timeoutdurationNoconnector's requestTimeoutPer-route wait for the flow.
maxBodyBytesintNo1048576Request body size cap (via http.MaxBytesReader). Oversized requests get 413.

How the request maps into the message

  • Path parameters — every {name} in path lands in vars.name (e.g. /orders/{id} sets vars.id).
  • Methodvars.method holds the HTTP method, so a flow can route on vars.method == "POST".
  • Query stringvars.query is a map of query parameters (first value of each key); it is always present, possibly empty.
  • Headers — each header listed in headers is copied into a variable of the same name, e.g. vars["X-Tenant"].
  • Body — a JSON body becomes body. A malformed JSON body is rejected with 400 before the flow runs, unless rawBody: true, in which case the body enters the flow as raw content carrying the request's Content-Type. An empty body is valid (body stays null).
  • Raw bytes — with rawBodyVar set, the exact request bytes are also stored in that variable as a string.

How the response is written

  • A completed flow returns its final body as JSON with status 200, or as raw content with its own Content-Type when the body is raw content.
  • Setting vars.httpStatus to a valid code (100–599) overrides the response status.
  • Variables named in responseHeaders are emitted as response headers (scalar values only).
  • A dropped message (e.g. a filter matched nothing) responds 204 No Content.
  • A failed flow responds 500 with a JSON {"error": ...} body — see error handling.
  • A flow that exceeds the timeout responds 504.

The runtime reads the whole request into memory and writes the whole response at once — there is no streaming. See Raw Content and Streaming for how to serve non-JSON payloads and why the payload is always materialized.

Example

Adapted from samples/http-orders.yaml:

service:
  name: http-orders

env:
  - name: HTTP_PORT
    default: "8080"

connectors:
  - name: api
    type: http
    settings:
      port: ${HTTP_PORT}
      basePath: /api/v1
      requestTimeout: 5s

flows:
  - name: orders-api
    source:
      connector: api
      type: http
      settings:
        path: /orders/{id}            # {id} -> vars.id
        correlationIdHeader: X-Request-Id
        headers: [X-Tenant]           # captured as vars["X-Tenant"]
    process:
      - type: set-payload
        settings:
          value: '{"orderId": vars.id, "tenant": vars["X-Tenant"], "status": "found"}'
curl -s localhost:8080/api/v1/orders/42 -H 'X-Tenant: acme'

http-client connector

The http-client connector (label: HTTP Client) owns a configured client for calling external HTTP APIs: base URL, authentication, default headers, a request timeout, retry on 429, and an opt-in in-memory response cache for GETs. The rest block references it by name.

Provides a source: no — it is outbound only. Blocks that bind to it: rest.

Settings

SettingTypeRequiredDefaultDescription
baseURLstringYesPrepended to each request path. Must be absolute (scheme and host).
timeoutdurationNo30sBounds each request.
headersmapNoApplied to every request unless already set by the block.
maxResponseBytesintNo1048576Response body size cap.
authobjectNononeAuthentication applied to every request (below).
retryobjectNoRetry policy for rate-limited (429) responses (below).
cacheobjectNodisabledIn-memory response cache for GET requests (below). Not exposed in the editor schema; configure it in YAML.

Authentication (auth)

SettingTypeRequiredDefaultDescription
typeenum: bearer | basic | oauth2NononeAuthentication scheme.
tokenstringWith type: bearerToken sent as Authorization: Bearer.
usernamestringWith type: basicBasic auth username.
passwordstringNoBasic auth password.
tokenURLstringWith type: oauth2OAuth2 token endpoint (client-credentials grant).
clientIDstringWith type: oauth2OAuth2 client identifier.
clientSecretstringWith type: oauth2OAuth2 client secret.
scopesstring[]NoRequested OAuth2 scopes.

For oauth2, the connector mints and refreshes a bearer token via the client-credentials grant and applies it to each request. A request that already carries an Authorization header is never overwritten.

Retry (retry)

When an upstream returns 429 Too Many Requests, the connector honors the Retry-After header when present, otherwise backs off exponentially. Each wait is capped at maxBackoff.

SettingTypeRequiredDefaultDescription
maxAttemptsintNo3Total attempts including the first; <= 1 disables retrying.
maxBackoffdurationNo30sUpper bound on each wait between attempts (also caps a large Retry-After).

Cache (cache)

SettingTypeRequiredDefaultDescription
enabledbooleanNofalseEnable the GET response cache.
ttldurationNo60sHow long a cached response is served.
maxEntriesintNo256Cache size cap.

rest block

REST Call — make an HTTP request through an http-client connector. Method and path are static; query parameters, headers, and the request body are CEL expressions evaluated per message. The response is folded into the message body: JSON parses into body, anything else becomes raw content carrying the response's Content-Type, and an empty response leaves body null.

SettingTypeRequiredDefaultDescription
connectorstringYesName of the http-client connector to use.
methodenum: GET | POST | PUT | PATCH | DELETE | HEADNoGETHTTP method.
pathstringNoPath appended to the connector base URL.
querymap of expressionNoQuery params; each value is a CEL expression.
headersmap of expressionNoRequest headers; each value is a CEL expression.
bodyexpressionNoCEL expression for the request body. A string result is sent verbatim; any other value is JSON-encoded (with Content-Type: application/json unless a header overrides it).
failOnErrorbooleanNotrueTurn a 400+ status into a flow error.
statusVarstringNostatusCodeVariable to store the response status code in.

Example

Adapted from samples/weather.yaml — a scheduled GET against a public API, cached for 60 seconds:

service:
  name: weather

connectors:
  - name: open-meteo
    type: http-client
    settings:
      baseURL: https://api.open-meteo.com
      timeout: 10s
      cache:
        enabled: true
        ttl: 60s
  - name: ticker
    type: cron

flows:
  - name: weather
    source:
      connector: ticker
      type: cron
      settings:
        schedule: "@every 30s"
    process:
      - type: rest
        name: fetch-forecast
        settings:
          connector: open-meteo
          method: GET
          path: /v1/forecast
          query:                       # values are CEL expressions
            latitude: '"52.52"'
            longitude: '"13.41"'
            current: '"temperature_2m"'
      - type: log
        settings:
          message: '"current temperature: " + string(body.current.temperature_2m)'

Keep credentials out of the flow file: declare them in the env section and reference them as ${API_TOKEN} — see environment and config.

On this page