Next: (web middleware static-url), Previous: (web middleware route-url), Up: API
Match incoming request against a set of defined routes.
The first argument is a list of three bindings: a request, a request body and a continuation. Those are usual arguments any middleware would receive. The created bindings may be used in routes’ definitions. Routes definitions are passed as rest of parameters to this macro.
(match-route (request body cont) route route* ...)
Each route takes a form of:
(method route-name-or-nothing path exp* ...)
any, meaning matching any method.
As a convenience feature, this symbol may be equal to the route’s handler procedure name. It this case, if the route’s body exp* expressions are missing, then the handler procedure will be applied with keyword arguments. The handler’s keyword arguments are meant to be named after the middleware argument bindings’ names and (if any) the path bindings. For example:
(define* (handler #:key request body cont id)
;; code
)
(define app (compose-middlewares
(match-route (request body cont)
(get 'handler ("page" id)))))
*
can be used. E.g.:
(define* (handle-admin-routes #:key request body cont)
;; code
)
(any 'handle-admin-routes ("admin" *))
;; matches every path, every method under /admin/
The (web middleware route-url) package defines the
route-url procedure to make URLs by route name and parameters.
For example, assuming the 'handler example route from above is
defined:
(route-url 'handler #:id "1") ;; => "/page/1"
Parameterize values to be used within the continuation.
This middleware seems to make code more expressive. So, instead of:
;; without use-parameters
(define app (compose-middlewares
;; middleware closure can refer to defined parameter
(show-demo-with (request-context:some-first-parameter))
(lambda (request body cont)
(values '((content-type text/plain))
;; middleware itself can refer to defined parameter
(request-context:some-second-parameter)))))
(run-server
(lambda (request body)
(parameterize ((request-context:some-first-parameter some-first-value)
(request-context:some-second-parameter some-second-value))
(app request body))))
the code, using use-parameters macro may be expressed like this:
;; with use-parameters
(define app
(compose-middlewares
(use-parameters ((request-context:some-first-parameter some-first-value)
(request-context:some-second-parameter some-second-value)))
;; middleware closure can refer to defined parameter
(show-demo-with (request-context:some-first-parameter))
(lambda (request body cont)
(values '((content-type text/plain))
;; middleware itself can refer to defined parameter
(request-context:some-second-parameter)))))
(run-server app)
param param* (syntax) parameter assignment syntax, e.g.
(define app
(compose-middlewares
(use-parameters ((request-context:some-first-parameter some-first-value)
(request-context:some-second-parameter some-second-value)))
;; ...
))
Check a request to match all predicates.
pred . pred* (procedure): Predicate procedures checking the request object.
Return values response and response body.
Set an exception handler, render error data if an exception is caught.
The caught exception is printed to the (current-error-port) using
print-exception procedure (display, by default). If
debug? is #t, then don’t unwind the stack. While in
development, it is useful not to unwind the stack to be able to inspect
and even fix some things in the REPL’s debugger. As the result, return
the response as built with the build-response procedure. See
Default error response
builder
debug? (boolean): whether to unwind the stack. #f for
unwind (default).
print-exception (procedure) how the exception is printed to
standard error, display by default.
render-data (mixed): rendered error data, passed to build-response.
build-response (procedure): error response builder, sxml renderer by default. See Default error response builder.
Return values response and response body.
Print incoming request information to the output-port with a customizable message format.
By default, the log output goes to (current-output-port). Message
is formatted accordingly to the format-string, "~a ~a" by
default, and it logs the request method and the uri path. The data
being logged is selected by the getters argument. This argument
takes a list of procedures, each receiving an environment using a
property list. The default environment consists of (#:request
request #:body body). It can be augmented by specifying
additional-env property list.
There is an implicit requirement: the number of format-string placeholders must be equal to the number of getters elements.
Here is an example to demonstrate log message customization by adding a getter and using additional environment:
(use-modules ((web middlewares logger-env)
#:select (get-request-method
get-uri-path))
;; Procedure, expecting custom "service-prefix" and "default-prefix" keys
;; from the environment
(define* (get-prefix #:key
request
service-prefix
default-prefix
#:allow-other-keys)
(if (string-prefix? "/service" (uri-path (request-uri request)))
service-prefix
default-prefix))
(define app (compose-middlewares
(log-request #:format-string "~a: ~a ~a"
#:getters (list get-prefix
get-request-method
get-uri-path)
#:additional-env '(#:service-prefix "Service request"
#:default-prefix "Request")))
;; ...
))
output-port (port): the log output port (default:
(current-output-port)).
format-string (string): the log message format string, as accepted
by Guile’s format procedure (default: "~a ~a").
getters (list of procedures): procedures to get each format-string’s placeholder values.
additional-env (property list): additional parameters for
getters procedures (default '()).
Return values response and response body.
Do nothing, continue to the next middleware.
Serve directory contents under the path folder-path within url-path URL-prefix.
This middleware may be declared for several folders within a single app.
Each folder should be given it’s unique tag. The default tag is
'assets. Tags are useful for resource URL creation, and should
be created with a helper procedure static-url from (web
middleware static-url):
(use-modules (web middleware static-url)) (static-url "css/style.css" #:tag 'assets) ;; or just (static-url "css/style.css")
The mime-detection is a list of MIME-type detection methods.
Couple of those methods are defined by (web middleware
mime-detection). The default one is to detect MIME-type by common file
extensions. If not detected, "application/octet-stream" is used. There
is a mime-by-file-util method, which requires a Unix file
utility to be available in the system. If the first method fails, then
second is used, and so on.
This middleware reads the whole file into memory, which may be unwanted in some cases. It’s recommended to use a full blown web server to serve static files in production.
Strip the user-prefix subpath from input request.
Middlewares, following this middleware in a chain, would receive a new request with user-prefix being stripped from the URI path. The request must have a user-prefix path prefix, throws otherwise.
Adapt the standard Guile handler procedure for the middleware chain.
If handler receives request and request body as arguments, then it may be wrapped as a middleware. It must return a response then.
Next: (web middleware static-url), Previous: (web middleware route-url), Up: API