Skip to content

Commit df0e697

Browse files
add HTTP virtual server docs and example config
1 parent e3127a5 commit df0e697

File tree

7 files changed

+631
-0
lines changed

7 files changed

+631
-0
lines changed

doc/antora/modules/developers/nav.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
*** xref:rfc/dhcpv4.adoc[DHCPv4]
3030
*** xref:rfc/dhcpv6.adoc[DHCPv6]
3131
*** xref:rfc/dns.adoc[DNS]
32+
*** xref:rfc/http.adoc[HTTP]
3233
*** xref:rfc/tacacs.adoc[TACACS+]
3334
** xref:guidelines.adoc[Documentation Guidelines]
3435
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
= HTTP RFCs
2+
3+
The following is a comprehensive set of tables that list all the
4+
related RFCs. Depending on the section or feature that you are
5+
developing, will determine which documents you need to review.
6+
7+
.Hypertext Transfer Protocol (HTTP)
8+
include::partial$dict_http.adoc[]
9+
10+
// Copyright (C) 2026 Network RADIUS SAS. Licenced under CC-by-NC 4.0.
11+
// This documentation was developed by Network RADIUS SAS.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[options=header,cols="20,~",autowidth]
2+
|====
3+
4+
|RFC |Description
5+
6+
|https://datatracker.ietf.org/doc/html/rfc9110[RFC 9110] | HTTP Semantics
7+
8+
|https://datatracker.ietf.org/doc/html/rfc9112[RFC 9112] | HTTP/1.1
9+
10+
|====

doc/antora/modules/reference/nav.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,8 @@
260260
**** xref:raddb/sites-available/dhcpv6.adoc[Virtual Server]
261261
*** xref:raddb/sites-available/doc/dns.adoc[DNS]
262262
**** xref:raddb/sites-available/dns.adoc[Virtual Server]
263+
*** xref:raddb/sites-available/doc/http.adoc[HTTP]
264+
**** xref:raddb/sites-available/http.adoc[Virtual Server]
263265
*** xref:raddb/sites-available/ldap_sync.adoc[LDAP Sync]
264266
*** xref:raddb/sites-available/doc/radius.adoc[RADIUS]
265267
**** xref:raddb/sites-available/default.adoc[Default]
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
= HTTP
2+
3+
Hypertext Transfer Protocol (HTTP) is the foundation of data
4+
communication on the Web. FreeRADIUS implements an HTTP/1.1 server,
5+
allowing it to accept and respond to HTTP requests over TCP.
6+
7+
This is intended as a building block for protocols layered on HTTP,
8+
such as ACME (RFC 8555) or custom REST APIs for network management.
9+
10+
// Copyright (C) 2026 Network RADIUS SAS. Licenced under CC-by-NC 4.0.
11+
// This documentation was developed by Network RADIUS SAS.
Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
= The HTTP Virtual Server
2+
3+
The `http` virtual server implements an HTTP/1.1 server, allowing
4+
FreeRADIUS to accept and respond to HTTP requests over TCP.
5+
6+
This is intended as a building block for protocols layered on HTTP,
7+
such as ACME (RFC 8555) or custom REST APIs for network management.
8+
9+
== Processing flow
10+
11+
For each incoming request the server runs:
12+
13+
1. A `recv <METHOD> { ... }` section that matches the HTTP method.
14+
This is where routing and response formulation happen.
15+
16+
2. A `send <METHOD>-Response { ... }` section that runs just before
17+
the response is serialised to the wire. This is a good place to
18+
inject headers that should appear on every response of that type.
19+
20+
== Automatic rcode-to-status mapping
21+
22+
When a `recv` section returns without explicitly setting
23+
`&reply.HTTP.Response.Status-Code`, the process layer automatically
24+
derives a status code from the rlm_rcode:
25+
26+
[options=header,cols="30,~",autowidth]
27+
|====
28+
|rcode |HTTP status
29+
|ok / noop / updated |200 OK
30+
|reject / disallow |403 Forbidden
31+
|fail |500 Internal Server Error
32+
|notfound |404 Not Found
33+
|invalid |400 Bad Request
34+
|timeout |503 Service Unavailable
35+
|handled |(none — operator must set `Status-Code` explicitly)
36+
|====
37+
38+
To override any of these, set `&reply.HTTP.Response.Status-Code`
39+
before returning from the section.
40+
41+
== Response body
42+
43+
Set `&reply.HTTP.Body` to include a response body. The
44+
`Content-Length` header is injected automatically by the encoder;
45+
do not set it manually.
46+
47+
== The Virtual Server
48+
49+
```
50+
server http {
51+
```
52+
53+
namespace:: Must be `http` for HTTP/1.1 functionality.
54+
55+
```
56+
namespace = http
57+
58+
listen {
59+
```
60+
61+
type:: Which HTTP methods this listener accepts.
62+
63+
Requests for methods not listed here are silently ignored by the
64+
listener. List only the methods your server needs to handle.
65+
66+
```
67+
type = GET
68+
type = POST
69+
type = PUT
70+
type = DELETE
71+
type = PATCH
72+
type = HEAD
73+
type = OPTIONS
74+
75+
```
76+
77+
transport:: The underlying transport. Only `tcp` is supported at this time.
78+
79+
```
80+
transport = tcp
81+
82+
tcp {
83+
```
84+
85+
ipaddr:: IP address to listen on. Use `*` to accept connections on all interfaces.
86+
87+
```
88+
ipaddr = *
89+
90+
```
91+
92+
port:: TCP port to listen on.
93+
94+
The IANA-assigned well-known port for HTTP is 80. Ports below 1024
95+
require elevated privileges on most operating systems. For
96+
development and testing, consider using port 8080 or another
97+
unprivileged port.
98+
99+
```
100+
port = 80
101+
}
102+
}
103+
104+
```
105+
106+
=== recv GET
107+
108+
Process incoming GET requests.
109+
110+
Route by path using `&HTTP.Request.Path`. Set `&reply.HTTP.Body`
111+
to include a response body. The encoder automatically adds a
112+
`Content-Length` header.
113+
114+
Returning `ok` without setting a status code produces `200 OK`.
115+
Returning `notfound` produces `404 Not Found`.
116+
117+
```
118+
recv GET {
119+
if (&HTTP.Request.Path == '/healthz') {
120+
ok
121+
}
122+
elsif (&HTTP.Request.Path =~ /^\/api\//) {
123+
&reply.HTTP.Body := '{"status":"ok"}'
124+
ok
125+
}
126+
else {
127+
notfound
128+
}
129+
}
130+
131+
```
132+
133+
=== send GET-Response
134+
135+
Runs immediately before the GET response is serialised to the wire.
136+
137+
Use this section to add headers that should appear on every GET
138+
response (e.g. cache control, CORS headers).
139+
140+
```
141+
send GET-Response {
142+
}
143+
144+
```
145+
146+
=== recv POST
147+
148+
Process incoming POST requests.
149+
150+
The request body (if any) is available as `&HTTP.Body` (type
151+
octets). Request headers are available as `&HTTP.Header` struct
152+
pairs with `Name` and `Value` members.
153+
154+
By convention, successful resource creation should return `201
155+
Created`. Set the status code explicitly — there is no automatic
156+
mapping for 201.
157+
158+
```
159+
recv POST {
160+
&reply.HTTP.Response.Status-Code := 201
161+
&reply.HTTP.Response.Reason-Phrase := "Created"
162+
ok
163+
}
164+
165+
send POST-Response {
166+
}
167+
168+
```
169+
170+
=== recv PUT
171+
172+
Process incoming PUT requests (full resource replacement).
173+
174+
Returning `ok` auto-maps to `200 OK`. Return `notfound` if the
175+
target resource does not exist.
176+
177+
```
178+
recv PUT {
179+
ok
180+
}
181+
182+
send PUT-Response {
183+
}
184+
185+
```
186+
187+
=== recv DELETE
188+
189+
Process incoming DELETE requests.
190+
191+
RFC 9110 recommends `204 No Content` when the deletion succeeds
192+
and there is no response body to return. The encoder suppresses
193+
any Body pair for 204 responses automatically.
194+
195+
```
196+
recv DELETE {
197+
&reply.HTTP.Response.Status-Code := 204
198+
&reply.HTTP.Response.Reason-Phrase := "No Content"
199+
ok
200+
}
201+
202+
send DELETE-Response {
203+
}
204+
205+
```
206+
207+
=== recv PATCH
208+
209+
Process incoming PATCH requests (partial resource update).
210+
211+
```
212+
recv PATCH {
213+
ok
214+
}
215+
216+
send PATCH-Response {
217+
}
218+
219+
```
220+
221+
=== recv HEAD
222+
223+
Process incoming HEAD requests.
224+
225+
HEAD is semantically identical to GET, but the encoder automatically
226+
suppresses the response body — only the headers are sent. Your
227+
routing logic here should mirror your `recv GET` section so that the
228+
status code and headers are consistent.
229+
230+
```
231+
recv HEAD {
232+
if (&HTTP.Request.Path == '/healthz') {
233+
ok
234+
}
235+
else {
236+
notfound
237+
}
238+
}
239+
240+
send HEAD-Response {
241+
}
242+
243+
```
244+
245+
=== recv OPTIONS
246+
247+
Process incoming OPTIONS requests.
248+
249+
OPTIONS is used for CORS pre-flight requests and for capability
250+
discovery. A minimal implementation returns `200 OK`. Set
251+
`Allow` and CORS headers in the corresponding `send` section.
252+
253+
```
254+
recv OPTIONS {
255+
ok
256+
}
257+
258+
send OPTIONS-Response {
259+
}
260+
261+
```
262+
263+
=== send Do-Not-Respond
264+
265+
This section runs when no response is sent to the client.
266+
267+
This happens when:
268+
269+
* `&reply.Packet-Type := Do-Not-Respond` is set explicitly, or
270+
* CONNECT or TRACE requests are received (no response type is
271+
defined for those methods yet).
272+
273+
No data is written to the wire. Use this section for logging
274+
or accounting only.
275+
276+
```
277+
send Do-Not-Respond {
278+
}
279+
}
280+
```
281+
282+
== Default Configuration
283+
284+
```
285+
```
286+
287+
// Copyright (C) 2026 Network RADIUS SAS. Licenced under CC-by-NC 4.0.
288+
// This documentation was developed by Network RADIUS SAS.

0 commit comments

Comments
 (0)