request_handler.mdin: /docs/internal/view/page/

Request Handler

The view that we've built is made for composition, but so is the request handler!

Our dependencies

Pretty standard for something dealing with an http request.

import (



The Handler

We export a Handler function that follows a middleware-like pattern, taking a handler and returning a handler. Handler composition is a little verbose (from the function signature), but really really nice once you're using it in practice.

I want to 1) Pass in defaults for the page/title, css, and js from the server and have it be configured and not hard-coded. And 2) maintain a middlware-ish style of composition.

func Handler(data Data) func(request.Handler) request.Handler {
    return func(rh request.Handler) request.Handler {
        return request.HandlerFunc(func(r *http.Request) (veun.AsView, http.Handler, error) {

Extracting mobile data

The page/css isn't responsive, but we can and do, potentially change layouts depending on if the page is mobile or not. We can

ua := useragent.New(r.UserAgent())
data.IsMobile = ua.Mobile()

Once again, you can see that when we're looking at any kind of code it ends up simply being function/interface composition.

There are small nuances in the way this specific middleware is implemented.

Errors and handlers

It always bubbles up the next handler to the caller, regardless of if there was an error or not.

v, next, err := rh.ViewForRequest(r)
if err != nil {
    return nil, next, err


It fully respects no view. If we passed this on to View, we would always be rendering an empty html page and 404s and redirects would kind of be busted. This also allows for a request.Handler to produce anything.

if v == nil {
    return nil, next, nil

Nice defaults

And if we get something to work with, we wrap with our page, and see check for that DataMutator hook.

return View(v, data), next, nil

End Handler: