Skip to content

Consider improvements to default route handling when no server or handler match #3879

@segevfiner

Description

@segevfiner

Caddy's current behavior when no site or handler match is to return a 200 status and empty body. The idea behind this is that the server defaults to answering with 200 and an empty body with no configuration without any "magic"/"convenience" behavior in certain cases to do otherwise. You need to explicitly match all routes to with the behavior you need. This is sadly not well documented and the documentation should likely explicitly state this and give examples.

Personally a 200 and an empty body might make sense if there are no handlers configured at all, but it can be argued that a 404 or even just closing the connection might be a better behavior when there are any handlers configured, as otherwise receiving a 200 and an empty body is highly confusing and it took me quite a while to figure out what is going on. Still that is "magic" behavior that some may like and some may not.

The other issue is that this is not that easy to do with the Caddyfile, forcing you to eschew some of the shorthand syntax and convenience it tries to provide. Let's imagine a Caddyfile that just does a plain reverse_proxy under some /api/ route:

localhost

reverse_proxy /api/ upstream

Any request to something not under /api/ will respond with a 200 and an empty body. Normally users coming from other servers will expect a 404, but since Caddy prefers to be explicit, this is not the case and you need to add that yourself. The problem? It is not possible to achieve this easily with just the simple "behavior-first" style configuration without using route or handle, as there is no support for configuring a "fallback" route that will match, if no other route does, in that style of configuration. You are forced to use either one of the more verbose:

localhost

route {
    reverse_proxy /api/ upstream
    respond 404
}

Or:

localhost

handle /api/ {
    reverse_proxy upstream
}

handle {
    respond 404
}

This is not only more verbose, but because this is such a commonly desired behavior IMHO, this simply eschews the use of the "behavior-first" style without route or handle at all.

The same problem also applies to site host matching, Caddy will respond with a 200 and an empty body for any unmatching host, when the site address includes a host in the Caddyfile. Forcing you to use the more verbose form of the Caddyfile with curly braces, eschewing the use of the shorthand without them at all:

localhost {
    handle /api/ {
        reverse_proxy upstream
    }

    handle {
        respond 404
    }
}

:80 {
     respond 404
}

This issue causes the loss of much of the convenience the Caddyfile shorthand syntax aims to offer, unless additional constructs are added to tackle this issue in a concise way (Or the default behavior is changed, but even then, some users might want to override it).

There are two things that could be added (Both or maybe just one of them):

  1. Defining a fallback route in a server when no other handler matches. (A special matcher? Shorthand Caddyfile syntax for it, like for paths?), this can also be useful to implement other kinds of configurations without resorting to route or handle.
  2. Defining a default handler/behavior that takes effect if no handler or server matches at all. (Without having to add curly braces to the server perhaps? In the global config block?)

Metadata

Metadata

Assignees

No one assigned

    Labels

    discussion 💬The right solution needs to be founddocumentation 📚Improvements or additions to documentation

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions