The "dryrun" parameter on Pattern.Match was kind of ugly and made for an
exceedingly mediocre public interface. Instead, split its functionality
in two: the previous "dryrun" behavior now lives in the Match method,
and Patterns now actually mutate state when Run is called.
The code on the backend is of course still the same (for now), but at
least the interface is a little nicer.
This change replaces a bit of API surface area (the Sub() method on Muxes) with
a slightly more expressive pattern syntax. I'm mostly doing this because it
seems cleaner: the "*" gets to take on a meaning very similar to what it means
in Sinatra (without growing regexp-like middle-of-a-path globbing, which sounds
terrifying and not particularly useful), and we get to nuke a useless function
from the API.
Package web will now add a key to the environment when it fails to find a
valid route for the requested method, but when valid routes exist for other
methods.
This allows either the 404 handler or a sufficiently clever middleware layer to
provide support for OPTIONS automatically.
Add tests for both string and regular expression patterns. Also, reimplement
regexp.Regexp.Prefix() on top of the raw regexp/syntax representation, so we can
get a little more information out of regexps:
- Whether or not the regexp is left-anchored (at the beginning of the string)
- What the prefix of the regular expression is, even for left-anchored
expressions.
We do this by running the regular expression instructions ourselves, more or
less cargo-culting the original implementation from package regexp/syntax.
Unfortunately it's ~impossible to make this abstraction non-leaky, because the
regexp package doesn't give us information about whether or not it was
constructed using POSIX or Perl syntax, for example, or if the longest-match
setting was applied.
The upshot is that regexps are now probably pretty performant-ish. Maybe. (I
haven't actually benchmarked it).