diff --git a/docs/src/.vuepress/config.js b/docs/src/.vuepress/config.js index 5483830..eb96c9b 100755 --- a/docs/src/.vuepress/config.js +++ b/docs/src/.vuepress/config.js @@ -75,7 +75,7 @@ module.exports = { title: 'Useful Handlers', collapsable: false, children: [ - 'handlers/path-delegating-handler', + 'handlers/path-handler', 'handlers/file-resolving-handler', 'handlers/filtered-handler', 'handlers/websocket-handler', diff --git a/docs/src/guide/handlers/path-delegating-handler.md b/docs/src/guide/handlers/path-delegating-handler.md index 8b6c323..6d1dfd8 100644 --- a/docs/src/guide/handlers/path-delegating-handler.md +++ b/docs/src/guide/handlers/path-delegating-handler.md @@ -1,5 +1,7 @@ # Path Delegating Handler +**This handler is deprecated in favor of the [PathHandler](./path-handler.md).** + As you may have read in [Handling Requests](./handling-requests.md), Handy-Httpd offers a pre-made [PathDelegatingHandler](ddoc-handy_httpd.handlers.path_delegating_handler.PathDelegatingHandler) that can match HTTP methods and URLs to specific handlers; a common use case for web servers. A PathDelegatingHandler is an implementation of [HttpRequestHandler](ddoc-handy_httpd.components.handler.HttpRequestHandler) that will _delegate_ incoming requests to _other_ handlers based on the request's HTTP method and URL. Handlers are registered with the PathDelegatingHandler via one of the overloaded `addMapping` methods. diff --git a/docs/src/guide/handlers/path-handler.md b/docs/src/guide/handlers/path-handler.md new file mode 100644 index 0000000..6e57abd --- /dev/null +++ b/docs/src/guide/handlers/path-handler.md @@ -0,0 +1,24 @@ +# Path Handler + +A common use-case for HTTP servers is to serve different content depending on the URL that the user requested. Handy-Httpd accomplishes this with its [PathHandler](ddoc-handy_httpd.handlers.path_handler.PathHandler) that can match HTTP methods (GET, POST, etc.) and URLs to specific handlers. + +A PathHandler is an implementation of [HttpRequestHandler](ddoc-handy_httpd.components.handler.HttpRequestHandler) that will *delegate* incoming requests to other handlers based on the request's HTTP method and URL. Handlers are registered with the PathHandler via one of the overloaded `addMapping` methods. + +For example, suppose we have a handler named `userHandler` that we want to invoke on **GET** requests to URLs like `/users/:userId:ulong`. + +```d +auto pathHandler = new PathHandler() + .addMapping(Method.GET, "/users/:userId:ulong", userHandler); +new HttpServer(pathHandler).start(); +``` + +## Path Patterns + +In our example, we used the pattern `/users/:userId:ulong`. This pattern matches URLs like `/users/`. Under the hood, the PathHandler is using the [path-matcher](https://github.com/andrewlalis/path-matcher) library to do matches. + +For a complete explanation of how path matching works, check out the path-matcher's README and source code, but we'll include some examples here for completeness' sake. + +- `/data` matches the URL `/data` literally, as-is. +- `/data/*` matches the URL `/data/a`, or `/data/1`, or any other single segment under `/data`, but not something like `/data/a/b/c`. +- `/users/:id:ulong` matches `/users/12345`, but not `/users/andrew`. +- `/**` matches any URL. diff --git a/docs/src/guide/handling-requests.md b/docs/src/guide/handling-requests.md index 7fa4471..7d5c037 100644 --- a/docs/src/guide/handling-requests.md +++ b/docs/src/guide/handling-requests.md @@ -42,7 +42,7 @@ Each request also contains a `remoteAddress`, which contains the remote socket a The request's headers are available via the `headers` associative array, where each header name is mapped to a single string value. There are no guarantees about which headers may be present, nor their type. It's generally up to the handler to figure out how to deal with them. -Similarly, the request's `params` associative array contains the named list of parameters that were parsed from the URL. For example, in `http://example.com/?x=5`, Handy-Httpd would provide a request whose params are `[x = "5"]`. Like the headers, no guarantee is made about what params are present, or what type they are. However, you can use the `getParamAs` function as a safe way to get a parameter as a specified type, or fallback to a default. +Similarly, the request's `params` associative array contains the named list of parameters that were parsed from the URL. For example, in `http://example.com/?x=5`, Handy-Httpd would provide a request whose params are `[x = "5"]`. Like the headers, no guarantee is made about what params are present, or what type they are. However, you can use the [getParamAs](ddoc-handy_httpd.components.request.HttpRequest.getParamAs) function as a safe way to get a parameter as a specified type, or fallback to a default. ```d void handle(ref HttpRequestContext ctx) { @@ -53,28 +53,26 @@ void handle(ref HttpRequestContext ctx) { #### Path Parameters -If a request is handled by a [PathDelegatingHandler](ddoc-handy_httpd.handlers.path_delegating_handler.PathDelegatingHandler), then its `pathParams` associative array will be populated with any path parameters that were parsed from the URL. +If a request is handled by a [PathHandler](ddoc-handy_httpd.handlers.path_handler.PathHandler), then its `pathParams` associative array will be populated with any path parameters that were parsed from the URL. The easiest way to understand this behavior is through an example. Suppose we define our top-level PathDelegatingHandler with the following mapping, so that a `userSettingsHandler` will handle requests to that endpoint: ```d auto handler = new PathDelegatingHandler(); -handler.addMapping("/users/{userId}/settings/{setting}", userSettingsHandler); +handler.addMapping("/users/:userId:ulong/settings/:setting", userSettingsHandler); ``` Then in our `userSettingsHandler` we can retrieve the path parameters like so: ```d void handle(ref HttpRequestContext ctx) { - string userId = ctx.request.pathParams["userId"]; - // Or more safely: - int userId2 = ctx.request.getPathParamAs!int("userId", -1); + ulong userId2 = ctx.request.getPathParamAs!ulong("userId"); string setting = ctx.request.pathParams["setting"]; // Do stuff for this user... } ``` -For more information about the PathDelegatingHandler, please see the [dedicated page on this topic](./handlers/path-delegating-handler.md). +For more information about the PathDelegatingHandler, please see the [dedicated page on this topic](./handlers/path-handler.md). #### Body Content