Ingresses
Ingresses create a harmonized API for invoking reactor components over various transport protocols. They provide a consistent way to expose component functionality to external systems, regardless of the underlying transport mechanism.
What are Ingresses?
An ingress is a resource that defines how to call a reactor component using a specific transport protocol. Hantera supports three ingress types:
| Type | Transport | For |
|---|---|---|
http | HTTP | Request/response API endpoints, webhooks, SSE streaming |
queue | AMQP-backed connections | Work-message queues with at-least-once settlement (RabbitMQ, Azure Service Bus) |
stream | AMQP-backed connections | Retained, partitioned event streams with durable checkpoints (Azure Event Hubs) |
Ingresses bridge the gap between external systems and Hantera's reactor components, allowing you to:
- Create custom API endpoints
- Process messages from message queues
- Handle webhooks and callbacks
- Expose component functionality to external applications
Relationship to Components and Jobs
Reactor components can be used in two main ways in Hantera:
- Jobs: Schedule components to run in the background at specific times or intervals
- Ingresses: Expose components as callable endpoints over various transport protocols
Both use the same reactor runtime to execute component code, but serve different purposes:
- Jobs are time-triggered and run autonomously
- Ingresses are request-triggered and respond to external calls
A Simple Example
Here's how to create an HTTP ingress that calls a component to create orders:
First, create a reactor component that handles order creation:
filtrera//create-order.hreactor param channelKey: text param items: [{ productNumber: text, quantity: number }] let fulfillmentId = newid let channel = registry->$'channels/{channelKey}' let orderCommands = [{ type = 'setChannelKey' value = channelKey },{ type = 'createFulfillment' fulfillmentId = fulfillmentId }] let orderLineCommands = items select i => { type = 'createOrderLine' fulfillmentId = fulfillmentId productNumber = i.productNumber quantity = i.quantity } from channel match nothing |> 'Channel not found' { currencyCode: not nothing, taxIncluded: bool } |> messageActor( 'order' 'new' [{ type = 'create' body = { currencyCode = channel.currencyCode taxIncluded = channel.taxIncluded commands = [orderCommands, orderLineCommands] flatten } }] ) |> 'Something went wrong'Create a manifest file to install the component and create the ingress:
yaml# Install the component uri: /resources/components/create-order.hreactor spec: componentVersion: '1.0.0' codeFile: create-order.hreactor --- # Create an HTTP ingress that calls the component uri: /resources/ingresses/api/orders/create spec: type: http componentId: create-order.hreactor properties: route: api/orders/create httpMethod: post body: mode: structured --- # Add a test channel for the example uri: /resources/registry/channels/WEB_SE spec: value: currencyCode: 'SEK' taxIncluded: trueApply the manifest to your Hantera instance:
bashh_ manage apply h_manifest.yamlThe ingress is now live! You can call it via HTTP:
bashcurl -X POST https://your-instance.hantera.io/ingress/api/orders/create \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_TOKEN" \ -d '{ "channelKey": "WEB_SE", "items": [{ "productNumber": "PROD001", "quantity": 2 }] }'
The ingress automatically maps the HTTP request to component parameters and handles the response.
Access Control
Managing Ingresses
Managing ingress resources requires standard resource permissions:
ingresses:read # View ingress configurations (and stream checkpoints)
ingresses:write # Create, update, and delete ingressesStream ingress checkpoint management is a separate operational permission:
ingresses/{id}:manage # operate a specific ingress's checkpoints
ingresses:manage # class-level wildcardmanage is deliberately separate from write: operating a consumer's position is an operations concern, not a configuration change. Every checkpoint action requires a reason, audited with the before/after positions (see Checkpoint management).
These permissions control access to the ingress resource itself through the management API (/resources/ingresses).
ACL Elevation
Ingresses can define an Access Control List (ACL) that determines what permissions the component has when it runs. This is a powerful feature that enables secure delegation:
Key Capabilities:
- The ingress component can run with different permissions than the calling session
- Grant the ingress access to resources the caller doesn't have
- Enable limited users to trigger privileged operations
- Access internal resources on behalf of external systems
Example:
uri: /resources/ingresses/admin/reset-cache
spec:
type: http
componentId: cache-manager.hreactor
# This ingress runs with elevated permissions
acl:
- system/admin:*
properties:
route: admin/reset-cache
httpMethod: postIn this example, any user authorized to call the ingress can trigger cache management operations, but the actual cache operations run with admin privileges as defined in the ACL.
Important: The ACL applies to what the component can do, not who can call the ingress. Authorization to call an ingress is transport-specific (see individual transport documentation for details).
Transport Types
HTTP Ingresses
HTTP ingresses expose components as HTTP endpoints. They support:
- All standard HTTP methods (GET, POST, PUT, PATCH, DELETE)
- Route parameters, headers, query strings, and body mapping
- Structured and raw body modes
- Public and authenticated access
- Server-Sent Events (SSE) for real-time streaming
Learn more about HTTP Ingresses →
Deep-dive guides:
- Parameter Mapping - Headers, query params, body handling
- Response Handling - JSON, streams, error responses
- SSE Streaming - Real-time server-sent events
Future Transports
Additional transports are planned, including:
- AMQP: Process messages from message queues
Each transport will provide transport-specific configuration while maintaining the same core ingress model.
Managing Ingresses
Ingresses are managed through the /resources/ingresses API endpoints. You can:
- List all ingresses:
GET /resources/ingresses - Get an ingress:
GET /resources/ingresses/{ingressId} - Create/update an ingress:
PUT /resources/ingresses/{ingressId} - Delete an ingress:
DELETE /resources/ingresses/{ingressId}
See the API Reference in the OpenAPI browser for detailed endpoint documentation.
Best Practices
Component Design
When creating components for ingresses:
- Validate input: Always validate parameters, especially for public ingresses
- Handle errors gracefully: Return meaningful error messages
- Keep it focused: One ingress should do one thing well
- Document parameters: Use clear parameter names and types
Security
- Use ACLs carefully: Only grant necessary permissions
- Avoid public ingresses unless absolutely needed
- Validate input carefully: Especially for public ingresses
Naming Conventions
- Use hierarchical ingress IDs:
api/orders/create,webhooks/payment/callback - Match HTTP routes to ingress IDs when possible
- Use clear, descriptive names that indicate purpose
See Also
- Components - Learn about reactor components
- Jobs - Schedule components to run in the background
- HTTP Ingresses - Detailed HTTP ingress configuration
- API Reference - Complete API documentation