Let's just hope the GC does its job correctly and don't try to help it
out. This case is probably triggered very infrequently since most people
set up their middleware before they accept a single request, and it's
worth about 100ns of perf on the common case for us if we get rid of the
defer.
The fast routing diff introduced a regression with how method sets were
calculated for routes that did not match. This fixes that behavior, as
well as making routing considerably more memory-efficient (and therefore
CPU-efficient too) for the case in which many routes share a prefix.
Swap out the naive "try all the routes in order" router with a "compile
a trie down to bytecode" router. It's a ton faster, while providing all
the same semantics.
See the documentation at the top of web/fast_router.go for more.
Partially sort the routes on insertion. We're doing this so we can do
more efficient things to routes later.
The sorting rules are a bit subtle since we aren't allowed to rearrange
routes in a way that would cause the semantics to differ from the dumb
linear scan.
This middleware allows you to override a http.Request's RemoteAddr with
a value derived from either the X-Forwarded-For or X-Real-IP headers.
Fixes#12.
Provide a standard middleware to set c.Env. Don't include it in the
default stack, however, since the RequestID middleware will end up
allocating Env anyways.
Fixes#11
Instead of returning awkward untyped error strings, return real error
structs. This will allow users of the library to extract interesting
semantic meaning from our errors, and is just all around less awful than
what we had before.
Previously, we disallowed setting the empty string as a key in a map,
since at the time it seemed like doing so would allow all sorts of
unsavory bugs. In practice, I think this probably isn't actually true,
as I wasn't able to think of a scenario in which this bug would
materialize during the several moments I thought about it.
Plus, the code here to do sanity checking was wrong anyways.
httptest was adding an extra flag, which was sort of ugly. Instead,
reimplement the parts of its functionality we were using. Bonus: due to
specialization, it's now a bit more efficient as well!
graceful.Server was made private in 05c2ca7e, but I think the increased
flexibility you get with being able to provide your own TLS options
(etc.) outweighs the API complexity of an additional type.
The "name" parameter was originally a workaround for the fact that function
pointers in Go never compare equal to each other (unless they are both nil).
Unfortunately, this presents a pretty terrible interface to the end programmer,
since they'll probably end up stuttering something like:
mux.Use("MyMiddleware", MyMiddleware)
Luckily, I found a workaround for doing function pointer equality (it doesn't
even require "unsafe"!), so we can get rid of the name parameter for good.
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.