Basic instructions for middleware

Matt Holt 2015-01-19 17:03:25 -07:00
parent 2579747815
commit 7715a03398

80
Middleware.md Normal file

@ -0,0 +1,80 @@
This page describes what middleware is related to Caddy and introduces you to a way to write your own middleware.
Caddy is powerful because of its extensible middleware stack. Middleware have the power to parse their own directives from config files, run code when the server starts, and intercept requests before and after the response is written.
Middleware are registered, in a particular order, in the middleware.go file:
```go
func init() {
register("gzip", Gzip)
register("header", Headers)
register("log", RequestLog)
// etc ...
}
```
Middleware take the basic form of a doubly-nested function:
```go
func MyMiddleware(p parser) Middleware {
return func(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// handler
}
}
}
```
- The inner-most layer is the actual HTTP request handler.
- The middle layer is the is the common notion of a "middleware": it wraps the next handler.
- The outer layer is a "middleware generator" which receives a parser.
Most of the logic will be in the generator and handler functions:
```go
func MyMiddleware(p parser) Middleware {
// use p to set up the middleware here
return func(next http.HandlerFunc) http.HandlerFunc {
// not much usually happens here
return func(w http.ResponseWriter, r *http.Request) {
// do stuff before
next(w, r)
// do stuff after
}
}
}
```
When `caddy` is run and the config file is parsed and found to use a middleware, that middleware is unwrapped one piece at a time, to eventually expose the underlying handler, which is ready to use thanks to Go closures. (The handler chain is pre-compiled so it doesn't have to do that for every request.)
That's all there is to it!
## Creating new middleware
Extend Caddy by writing your own middleware! First open an issue to detail what you want it to do and how it will work, including what the syntax in the Caddyfile would look like. Then once it looks good, go ahead and submit a pull request.
So how do you start writing middleware? There are two main things to do:
1. Write the middleware code
2. Register it with a certain directive in `init()`
When the server starts up, the middle
### Parsing
The generator function is the first layer to be unwrapped. It is passed a parser, which you can use to get data out of the Caddyfile. Better documentation on how to do this is coming, but for now, look at examples of existing middleware. You have a lot of control and there's a lot of power in being able to do your own parsing of the config.
### Handler logic
Once your middleware is configured (the generator layer), the second layer will be used by the server to compile your handler into the chain. The handler can do whatever you need it to do, as long as it calls `next`. You have to have a deliberate reason to not call the next HandlerFunc.
Again, look at existing middleware for examples. There's already a good variety to get you started.
### Registration
Now that your middleware is ready, register it to a directive. In the `init()` function of the `middleware.go` file, there are a bunch of `register()` calls made. Simply register your middleware in the proper spot (ordering is important, depending on what it does) and with the specific directive that activates your middleware. You can bind to more than one directive, but this is rare and should be discussed in an issue first.