http.serve{
route:{path:str, relgen:str},
addr:str,
tls:tuple{certfile:str, keyfile:str},
trusted_origin:{name:str},
err:str
}
Starts an http server.
The route path defines which URL is matched to which relgen handler. The server matches the URL of each incoming request against the set of route paths and calls the relgen handler for the one that most closely matches the URL. It calls the relgen handler by composing it with a relation containing the request information:
{
method:str,
path:str,
path_value:{k:str, v:str},
header:{k:str, seq:int, v:str},
body:str,
form:{k:str, seq:int, v:str},
}
Check if err is set for any failures.
If addr is given, it specifies the TCP address for the server to listen on, in the form "host:port". If empty, ":http" (port 80) is used.
If tls is given, then an https server is started.
If trusted_origin is given, then the server allows all requests with Origin headers which exactly match one of the given set of names.
Origin header values are of the form "scheme://host[:port]".
Each route relgen should name a relation generator which should set and yield a response and conform to:
{
method:str,
path:str,
path_value:{k:str, v:str},
header:{k:str, seq:int, v:str},
body:str,
form:{k:str, seq:int, v:str},
response:tuple{header:{k:str, seq:int, v:str}, status:int, body:str},
}
http.hh can be used as a dynamic template for such route relgen handlers, e.g.
index_handler := {attr_types(http.hh)} begin ... end
A pre-defined relgen named "http.FileServer" will serve files from its given route path. If the route path has two parts, separated by a space, the second part will be the local file dir (otherwise the path is used as the local file dir as well as the file URL path).
Routes
Note: This section is based on Go's ServeMux, adapted to suit the Ra environment.
Route paths
Route paths can match the method, host and path of a request. Some examples:
- "/index.html" matches the path "/index.html" for any host and method.
- "GET /static/" matches a GET request whose path begins with "/static/".
- "example.com/" matches any request to the host "example.com".
- "example.com/{$}" matches requests with host "example.com" and path "/".
- "/b/{bucket}/o/{objectname...}" matches paths whose first segment is "b" and whose third segment is "o". The name "bucket" denotes the second segment and "objectname" denotes the remainder of the path.
In general, a route path looks like
[METHOD ][HOST]/[PATH]All three parts are optional; "/" is a valid route path. If METHOD is present, it must be followed by at least one space or tab.
Literal (that is, non-wildcard) parts of a route path match the corresponding parts of a request case-sensitively.
A route path with no method matches every method. A route path with the method GET matches both GET and HEAD requests. Otherwise, the method must match exactly.
A route path with no host matches every host. A route path with a host matches URLs on that host only.
A path can include wildcard segments of the form {NAME} or {NAME...}. For example, "/b/{bucket}/o/{objectname...}". The wildcard name must be a valid Ra identifier. Wildcards must be full path segments: they must be preceded by a slash and followed by either a slash or the end of the string. For example, "/b_{bucket}" is not a valid route path.
Normally a wildcard matches only a single path segment, ending at the next literal slash (not %2F) in the request URL.
But if the "..." is present, then the wildcard matches the remainder of the URL path, including slashes.
(Therefore it is invalid for a "..." wildcard to appear anywhere but at the end of a route path.)
The match for a wildcard can be obtained via the request path_value relation with "k" as the wildcard's name,
e.g. path_value[k="bucket"].
A trailing slash in a path acts as an anonymous "..." wildcard.
The special wildcard {$} matches only the end of the URL. For example, the route path "/{$}" matches only the path "/", whereas the route path "/" matches every path.
For matching, both route path paths and incoming request paths are unescaped segment by segment. So, for example, the path "/a%2Fb/100%25" is treated as having two segments, "a/b" and "100%". The route path "/a%2fb/" matches it, but the route path "/a/b/" does not.
Precedence
If two or more route paths match a request, then the most specific route path takes precedence. A route path P1 is more specific than P2 if P1 matches a strict subset of P2’s requests; that is, if P2 matches all the requests of P1 and more. If neither is more specific, then the route paths conflict. There is one exception to this rule: if two route paths would otherwise conflict and one has a host while the other does not, then the route path with the host takes precedence.
As an example of the general rule, "/images/thumbnails/" is more specific than "/images/", so both can be in route.
The former matches paths beginning with "/images/thumbnails/" and the latter will match any other path in the "/images/" subtree.
As another example, consider the route paths "GET /" and "/index.html": both match a GET request for "/index.html", but the former route path matches all other GET and HEAD requests, while the latter matches any request for "/index.html" that uses a different method. The route paths conflict.
Trailing-slash redirection
Consider a call to http.serve with a relgen handler for a subtree, registered using a trailing slash or "..." wildcard.
If the relgen handler receives a request for the subtree root without a trailing slash, it redirects the request by adding the trailing slash.
This behavior can be overridden with a separate route entry for the path without the trailing slash or "..." wildcard.
For example, a route path of "/images/" causes http.serve to redirect a request for "/images" to "/images/",
unless "/images" has been added to route separately.
Request sanitizing
http.serve also takes care of sanitizing the URL request path and the Host header,
stripping the port number and redirecting any request containing . or .. segments or repeated slashes to an equivalent, cleaner URL.
Escaped path elements such as "%2e" for "." and "%2f" for "/" are preserved and aren't considered separators for request routing.
Portions of this page are modifications based on Go's ServeMux created and shared by Google and used according to terms described in the Creative Commons Attribution 4.0 License.