Shunting the request/response cycle through custom handlers
This note describes how the server is configured to route dynamic resource requests.
The server can handle both static and dynamic resource requests.
A static resource request is defined as a request to receive, save, or delete the contents of a file of unvarying content. By contrast, a dynamic request is defined as a request to receive, save, or delete data of varying content, which is not serialized in a single file.
Some types of resource requests can't be fulfilled with static files. HTTP
POST requests, for example, must be handled in an application specific way. HTTP
GET requests that retrieve values from a database, are another example. These are common examples of dynamic requests.
When a static request is made to the server, standard HTTP protocol rules apply. The request's resource path and method determine what to process and how to process it: the resource path points to a file, and the
DELETE method is applied in a well-regulated way.
When a dynamic request is made to the server, HTTP protocol guidelines still dictate the rules-of-the-road, but no code exists on the server to actually carry out the request. This is where the router fits in.
The router shunts dynamic requests to plugin modules.
Normally, incoming requests work their way through a sequence of request handlers which check the validity of the request, then work their way through a sequence of response handlers to format the payload and its metadata into HTTP compliant responses. When a dynamic request is received, the router intercepts the processing cycle midway — between the request handlers and response handlers — and shunts the processing to the configured plugin handler.
The plugin handler is provided with pointers to the data structures that contain the request headers, payload, and response headers. What it does with them and how it does it, is application specific.
plugins section contains a
router subsection which comprises a collection of entries, where each entry has a path-pattern, a list of applicable methods, and a plugin name.
Unlike most other configuration sections, all defined path patterns are scanned, in top-to-bottom order, allowing multiple plugins to chain their handling of requests. Refer to the separate note regarding Path Patterns for a description of how patterns are matched.
The list of applicable methods is a comma-separated list of HTTP methods which will be honored by the router.
The plugin name is a reference to a user-defined plugin name. Read more about declaring and configuring plugins in the separate note about Plugins.
During processing, the entries in the router section are scanned from top to bottom, and each matching entry triggers the use of the declared plugin. If the incoming request's path and method do not match any resource-pattern/method combination, the router returns control to the normal request/response cycle and the request is handled as a static file.
router configuration section may appear in either the
server/plugins section or a
host/plugins section: merging is not supported. If values are placed in the
host/plugins section they will be used in their entirety; if not, the values in the
server/plugins section, if any, will be used as a fallback.
When a resource-pattern/method matches a request, but the plugin module is not reachable at its declared location, a
rw-router-missing-module information header is added to the response and it returns with status code
|file-system-chars||::=||(ALPHA | DIGIT | †)*|
|wildcards||::=||ASTERISK | QUESTION-MARK|
|path-pattern||::=||(SOLIDUS | file-system-chars | wildcards)*|
|delimited-path-pattern||::=||GRAVE-ACCENT path-pattern GRAVE-ACCENT|
|method-name||::=||'HEAD' | 'GET' | 'PUT' | 'DELETE' | 'POST' | 'PATCH' | 'OPTIONS' | 'TRACE'|
|methods-attribute||::=||ASTERISK 'methods' EQUALS-SIGN (method-name COMMA)*|
|plugin-name||::=||(ALPHA | DIGIT | HYPHEN)*|
|plugin-attribute||::=||ASTERISK 'plugin' EQUALS-SIGN plugin-name CR|
|router-entry||::=||delimited-path-pattern SP methods-attribute SP plugin-attribute CR|
|router-section||::=||'router' SP LEFT-CURLY-BRACKET CR|
† Legal file system characters vary by platform
Example 1: Routing GET requests to built-in Blue plugin
`*.blue` *methods=GET,HEAD *plugin=rwserve-blue
Example 2: Routing GET requests to built-in Counters plugin
`/rwserve/counters/*` *methods=GET *plugin=rwserve-counters
Example 3: Routing POST requests to builtin RBAC-Auth plugin
`/login-logout/*` *methods=POST *plugin=rwserve-rbac-auth
Example 4: Routing POST requests to builtin policy report handler
`/notifications` *origin="domain.tld" *headers=content-type *methods=POST
`/notifications` *methods=POST *plugin=rwserve-policy-reports
Example 5: Routing PATCH requests to custom plugin
custom-patch-handler is exemplary only.
`/api/*` *methods=PATCH *plugin=custom-patch-handler
Key points to remember:
- The request/response cycle can be interrupted by the router and shunted to plugin modules for handling.
- Plugin handlers are called in top-to-bottom order, allowing multiple plugins to chain their handling of requests.