http
Beginning of an HTTP server clause with a name defined as a parameter. Multiple HTTP servers can be defined.
HTTP servers handle web-based requests and can be used for custom HTTP APIs, webhooks, or REST-based authentication services. The server processes incoming HTTP requests through AAA policies, where handlers match requests based on HTTP method, path, headers, and other attributes.
Protocols
The HTTP server supports the following transport protocols:
- tcp - Plain HTTP over TCP.
- tls - HTTPS with TLS encryption. Requires certificate configuration. Supports HTTP/1.1 and HTTP/2.
Parameters
| Parameter | Description | Required |
|---|---|---|
| listen | Network listener configuration (protocol, port, IP addresses, TLS) | Yes |
| clients | Reference to an HTTP client list that defines allowed client sources | No |
| @pre-client | Pipeline executed before client matching | No |
| policy | Default AAA policy for handling requests | No |
| capture | Packet capture configuration name | No |
| statistics | Statistics collection configuration | No |
Note: The
@prefix is required for pipeline blocks. The legacy syntax without@(e.g.,pre-client {}) is deprecated and emits warnings. Use@pre-client {}for new configurations.
HTTP Context Variables
When processing HTTP requests, context variables in the http namespace are available in pipelines.
For the complete list of available variables, see the HTTP namespace documentation.
Default Response Behavior
When no custom response body is set via http.response.*, the server returns a JSON object based on the pipeline result:
{
"result": "accept",
"message": "Optional message"
}
Default HTTP status codes based on pipeline results:
| Pipeline Result | HTTP Status |
|---|---|
| accept | 200 OK |
| reject | 403 Forbidden |
| ignore | 404 Not Found |
| error | 500 Internal Server Error |
Set http.status explicitly to override these defaults.
Response headers automatically included:
X-AAA-Context-Id- The AAA context identifierX-AAA-Result- The pipeline result (accept, reject, ignore, error)X-AAA-Message- Optional message from the pipeline (when set)
Response Construction
Use the HTTP response variables with these rules:
http.statussets the actual HTTP status code.http.responsesets the entire response body. By default, Radiator returns it as JSON. Set it tononeto send no response body.http.response.KEYsets a field inside an object response body. For example,http.response.message = "hello";returns{"message":"hello"}with the defaulthttp.json = true.http.jsonchooses whether Radiator returns the response body as JSON or as non-JSON text. Set it tofalsewhen you want a plain-text or other non-JSON response body.http.response_header.NAMEsets an outgoing HTTP header.http.bodyreads the incoming request body and is not writable in policy configuration.
Examples:
With the default http.json = true, multiple http.response.KEY assignments
build one JSON object response body.
modify {
http.status = 200;
http.response.result = "accept";
http.response.message = "Hello from Radiator";
http.response.details.source = "policy";
}
This returns:
{
"result": "accept",
"message": "Hello from Radiator",
"details": {
"source": "policy"
}
}
With the default http.json = true, this returns JSON {"body":null} because body is a response field name in this form.
modify {
http.response.body = none;
}
This sends no response body. Use http.NO_CONTENT when you want the response to
be an explicit 204 No Content.
modify {
http.status = http.NO_CONTENT;
http.response = none;
}
This sets the HTTP status code to 400, writes JSON body {"status":400} with the default http.json = true, and sends a Location header.
modify {
http.status = http.BAD_REQUEST;
http.response.status = 400;
http.response_header.Location = "/login";
}
This returns plain text instead of JSON. Set http.json = false when you want Radiator to send the top-level http.response value as a non-JSON text body. Set http.response_header.Content-Type to the media type you want, such as text/plain, text/html, or application/xml.
modify {
http.json = false;
http.response_header.Content-Type = "text/plain; charset=utf-8";
http.response = "Hello from Radiator";
}
If you set http.json = false and still use http.response.KEY, Radiator
still builds one object response body from those fields. It then sends that
object as non-JSON text. For example, http.response.first = "a"; and
http.response.second = "b"; still produce body {"first":"a","second":"b"}.
Use top-level http.response = "..."; when you want plain text.
Use http.response_header.NAME for outgoing headers. http.response.header
and http.response.header.NAME write response body fields named header; they
are not header aliases.
Example: Basic HTTP Server
servers {
http "HTTP_SERVER" {
listen {
protocol tcp;
ip 0.0.0.0;
port 8000;
}
clients "HTTP_CLIENTS";
}
}
clients {
http "HTTP_CLIENTS" {
client "LOCALHOST" {
source {
ip 127.0.0.1;
ip ::1;
}
}
}
}
Example: HTTPS Server with TLS
certificates {
x509 "SERVER_CERT" {
filename "/etc/radiator/certs/server.pem";
}
key "SERVER_KEY" {
filename "/etc/radiator/private/server-key.pem";
}
x509 "CA_CERT" {
filename "/etc/radiator/certs/ca.pem";
}
}
servers {
http "HTTPS_SERVER" {
listen {
protocol tls;
ip 0.0.0.0;
port 8443;
tls {
certificate "SERVER_CERT";
certificate_key "SERVER_KEY";
server_ca_certificate "CA_CERT";
require_client_certificate false;
}
}
clients "HTTP_CLIENTS";
}
}
Example: Multiple Endpoints with Different Responses
This example demonstrates an HTTP server with multiple endpoints returning different JSON responses:
logging {
aaa {
logger "HTTP_ACCESS" {
file {
filename "/var/log/radiator/http-access.log";
}
}
}
}
clients {
http "HTTP_CLIENTS" {
client "LOCALHOST" {
source {
ip 127.0.0.1;
ip ::1;
}
}
}
}
servers {
http "HTTP_SERVER" {
listen {
protocol tcp;
ip 0.0.0.0;
port 4000;
}
clients "HTTP_CLIENTS";
}
}
aaa {
@pipeline "LOG_REQUEST" {
log "HTTP_ACCESS" {
json {
"timestamp" datetime.timestamp;
"method" http.method;
"path" http.path;
"client_ip" http.client.ip;
"status" http.status;
"handler" aaa.handler;
}
}
}
policy "DEFAULT" {
handler "FOO" {
conditions all {
http.method == "GET";
http.path == "/foo";
}
@execute {
modify {
http.status = 200;
http.response.endpoint = "foo";
http.response.message = "Hello from /foo";
}
accept;
}
@final-execute {
invoke "LOG_REQUEST";
}
}
handler "BAR" {
conditions all {
http.method == "GET";
http.path == "/bar";
}
@execute {
modify {
http.status = 200;
http.response.endpoint = "bar";
http.response.data.value = 42;
http.response.data.items = "one,two,three";
}
accept;
}
@final-execute {
invoke "LOG_REQUEST";
}
}
handler "NESTED_PATH" {
conditions all {
http.method == "GET";
http.path == "/some/path";
}
@execute {
modify {
http.status = 200;
http.response.endpoint = "some/path";
http.response.nested.level1.level2 = "deep value";
}
accept;
}
@final-execute {
invoke "LOG_REQUEST";
}
}
handler "POST_HANDLER" {
conditions all {
http.method == "POST";
http.path == "/some/path";
}
@execute {
modify {
http.status = 201;
http.response.endpoint = "some/path";
http.response.method = "POST";
http.response.received = http.body;
}
accept;
}
@final-execute {
invoke "LOG_REQUEST";
}
}
handler "NOT_FOUND" {
@execute {
modify {
http.status = 404;
http.response.error = "Not Found";
http.response.message = "The requested path does not exist";
}
reject;
}
@final-execute {
invoke "LOG_REQUEST";
}
}
}
}
This configuration:
- Serves
/fooreturning{"endpoint": "foo", "message": "Hello from /foo"} - Serves
/barreturning nested data with{"endpoint": "bar", "data": {"value": 42, ...}} - Serves GET
/some/pathreturning deeply nested JSON - Serves POST
/some/pathreturning status 201 with the received body - Returns 404 for any unmatched paths
- Logs all requests in JSON format to an access log file
See Also
- servers - Server configuration overview
- clients.http - HTTP client list configuration
- aaa.policy - AAA policy configuration