Skip to content

HTTP ingresses map various parts of HTTP requests to component parameters. This page covers all the ways to extract data from incoming requests.

Parameter Resolution Order ​

Parameters are resolved in a specific order, with later mappings potentially overriding earlier ones:

  1. Route parameters - Extracted from the URL path
  2. Headers - Mapped HTTP headers
  3. Query parameters - URL query string values
  4. Body - Request body content

This order allows intentional parameter overloading. For example, a query parameter can override a route parameter if needed.

Route Parameters ​

Route parameters are defined in the route path using {paramName} syntax:

yaml
properties:
  route: api/orders/{orderId}/items/{itemId}

Parameters are automatically extracted and passed to the component:

bash
curl https://example.hantera.io/ingress/api/orders/ORD-123/items/ITEM-456
# Component receives: orderId="ORD-123", itemId="ITEM-456"

Route parameters are always extracted as text values.

Headers ​

Map HTTP headers to component parameters using the headers property:

yaml
properties:
  headers:
    userId: X-User-Id
    apiKey: X-API-Key
    correlationId: X-Correlation-ID

The key is the component parameter name, and the value is the HTTP header name:

bash
curl -H "X-User-Id: user-123" \
     -H "X-API-Key: secret-key" \
     https://example.hantera.io/ingress/api/protected
# Component receives: userId="user-123", apiKey="secret-key"

If multiple values exist for a header, they are joined with semicolons.

Client IP Address ​

Hantera resolves the originating client IP from the proxy chain and exposes it through a single canonical header, X-Hantera-Client-IP. Map it like any other header instead of parsing X-Forwarded-For yourself:

yaml
properties:
  headers:
    clientIp: X-Hantera-Client-IP
filtrera
param clientIp: text

This header is always set by Hantera from the trusted proxy chain and overwrites any value a client may send, so it cannot be spoofed. It is also visible in the dev-mode ingress request log.

Query Parameters ​

Map URL query string parameters using the queryParams property:

yaml
properties:
  queryParams:
    pageSize: limit
    pageNumber: offset
    searchTerm: q

The key is the component parameter name, and the value is the query string key:

bash
curl "https://example.hantera.io/ingress/api/products?limit=50&offset=0&q=laptop"
# Component receives: pageSize="50", pageNumber="0", searchTerm="laptop"

If multiple values exist for a query parameter, they are joined with semicolons:

bash
curl "https://example.hantera.io/ingress/api/products?tag=electronics&tag=sale"
# Component receives: tag="electronics;sale"

Body Handling ​

The body configuration determines how the HTTP request body is processed.

Structured Mode ​

In structured mode, the request body must be JSON and is parsed into component parameters:

yaml
properties:
  body:
    mode: structured

Without a parameter name, each JSON property becomes a component parameter:

bash
curl -X POST https://example.hantera.io/ingress/api/orders \
  -H "Content-Type: application/json" \
  -d '{
    "customerId": "CUST001",
    "items": [{"sku": "PROD001", "quantity": 2}]
  }'
# Component receives: customerId="CUST001", items=[...]

With a parameter name, the entire JSON body becomes one parameter:

yaml
properties:
  body:
    mode: structured
    parameter: orderData
bash
curl -X POST https://example.hantera.io/ingress/api/orders \
  -H "Content-Type: application/json" \
  -d '{
    "customerId": "CUST001",
    "items": [{"sku": "PROD001", "quantity": 2}]
  }'
# Component receives: orderData={customerId: "CUST001", items: [...]}

Structured mode requires Content-Type: application/json. Other content types result in a 400 Bad Request.

Raw Mode ​

In raw mode, the request body is passed as a stream to the component:

yaml
properties:
  body:
    mode: raw
    parameter: fileData

This is useful for:

  • Large structured data imports (XML, CSV)
  • Binary data processing
  • File uploads
  • Custom content types

The component receives the raw stream as a byte iterator ([byte]):

filtrera
import 'xml'

param xmlData: [byte]

let products = 
  xmlData
  |> xml.readXml
  |> xml.whereElement('product')
  select product => {
    skuNumber = product |> xml.whereElement('sku') |> xml.getText
    name = product |> xml.whereElement('name') |> xml.getText
    price = product |> xml.whereElement('price') |> xml.getText
  }

from products

Complete Example ​

Here's an example combining multiple parameter sources to create an order cancellation endpoint:

yaml
uri: /resources/ingresses/api/orders/cancel
spec:
  type: http
  componentId: cancel-order.hreactor
  acl:
    - orders:write
  properties:
    route: api/orders/{orderId}/cancel
    httpMethod: post
    headers:
      requestId: X-Request-ID
    body:
      mode: structured

Component:

filtrera
param orderId: uuid
param requestId: text | nothing
param reason: text | nothing

let order = query orders(orderId, orderState) 
  filter $'orderId == ''{orderId}''' 
  first

from order match
  nothing |> { error = { code = 'NOT_FOUND', message = 'Order not found' } }
  { orderState: 'cancelled' } |> { error = { code = 'ALREADY_CANCELLED', message = 'Order is already cancelled' } }
  |> messageActor(
    actorType = 'order'
    actorId = orderId
    messages = [{
      type = 'applyCommands'
      commands = [{
        type = 'setOrderState'
        orderState = 'cancelled'
      }]
    }]
  )

Request:

bash
curl -X POST \
  "https://example.hantera.io/ingress/api/orders/abc-123/cancel" \
  -H "X-Request-ID: req-456" \
  -H "Content-Type: application/json" \
  -d '{"reason": "Customer requested cancellation"}'

# Component receives:
# - orderId: "abc-123" (from route)
# - requestId: "req-456" (from header)
# - reason: "Customer requested cancellation" (from body)

Parameter Type Conversion ​

Parameters extracted from routes, headers, and query strings are always text. The component can define typed parameters, and Hantera will attempt to convert:

filtrera
param orderId: text
param limit: number | nothing
param includeDeleted: bool | nothing

For JSON bodies, the original JSON types are preserved.

Missing Parameters ​

If a required parameter is not provided, the ingress returns 400 Bad Request:

json
{
  "error": {
    "code": "MISSING_PARAMETER",
    "message": "Missing parameter orderId"
  }
}

Optional parameters (those with | nothing types or default values) are simply not passed to the component.

See Also ​

© 2026 Hantera AB. Org. no.: 559242-9582