HTTP Parameter Mapping
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:
- Route parameters - Extracted from the URL path
- Headers - Mapped HTTP headers
- Query parameters - URL query string values
- 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:
properties: route: api/orders/{orderId}/items/{itemId}Parameters are automatically extracted and passed to the component:
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:
properties: headers: userId: X-User-Id apiKey: X-API-Key correlationId: X-Correlation-IDThe key is the component parameter name, and the value is the HTTP header name:
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.
Query Parameters
Map URL query string parameters using the queryParams property:
properties: queryParams: pageSize: limit pageNumber: offset searchTerm: qThe key is the component parameter name, and the value is the query string key:
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:
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:
properties: body: mode: structuredWithout a parameter name, each JSON property becomes a component parameter:
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:
properties: body: mode: structured parameter: orderDatacurl -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:
properties: body: mode: raw parameter: fileDataThis 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]):
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 productsComplete Example
Here’s an example combining multiple parameter sources to create an order cancellation endpoint:
uri: /resources/ingresses/api/orders/cancelspec: type: http componentId: cancel-order.hreactor acl: - orders:write properties: route: api/orders/{orderId}/cancel httpMethod: post headers: requestId: X-Request-ID body: mode: structuredComponent:
param orderId: uuidparam requestId: text | nothingparam 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:
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:
param orderId: textparam limit: number | nothingparam includeDeleted: bool | nothingFor JSON bodies, the original JSON types are preserved.
Missing Parameters
If a required parameter is not provided, the ingress returns 400 Bad Request:
{ "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
- HTTP Ingresses - Overview and configuration
- Response Handling - JSON, streams, and error responses
- SSE Streaming - Real-time server-sent events