mirror of
https://github.com/caddyserver/caddy.git
synced 2025-06-19 13:35:29 -04:00
Created Writing Middleware (markdown)
parent
4a6fe10863
commit
bd55be2fa2
47
Writing-Middleware.md
Normal file
47
Writing-Middleware.md
Normal file
@ -0,0 +1,47 @@
|
||||
# Writing Middleware
|
||||
|
||||
This page describes how to write middleware for Caddy, which adds to its capabilities when serving requests. You should know Go and be familiar with its [net/http](https://golang.org/pkg/net/http) package. It may help to have written at least a simple web app before or have a basic understanding of how middleware works in general.
|
||||
|
||||
Caddy's middleware packages are independent and can be used in any Go program. (Learn how.) Keep that in mind when writing middleware: it's not just for Caddy.
|
||||
|
||||
## The `middleware` Package
|
||||
|
||||
Caddy has defined [a few important types](http://godoc.org/github.com/mholt/caddy/middleware) in its middleware package. The two that you will need to implement are middleware.Handler and middleware.Middleware. (The other types are for use by Caddy and are slated to be moved out of the package soon.) Take a quick look at their documentation; it will help.
|
||||
|
||||
## Basic Handler
|
||||
|
||||
middleware.Handler is an interface exactly like http.Handler, except that the ServeHTTP method returns (int, error). The int is the HTTP status code to respond with, and the error is an error that should be handled and/or logged. Read the godoc for more details about these return values. This method signature follows [a recommendation from the Go Blog](http://blog.golang.org/error-handling-and-go) for error handling related to middleware.
|
||||
|
||||
Handlers are usually a struct with at least one field, the next Handler in the chain:
|
||||
|
||||
```go
|
||||
type MyHandler struct {
|
||||
Next middleware.HandlerFunc
|
||||
}
|
||||
```
|
||||
|
||||
It must implement the middleware.Handler interface. We do this by adding a method called ServeHTTP, which happens to be a middlware.HandlerFunc. Right now, let's just pass the request to the next Handler in the chain:
|
||||
|
||||
```go
|
||||
func (h MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
|
||||
return h.Next(w, r)
|
||||
}
|
||||
```
|
||||
|
||||
That's all there is to it. Put your middleware logic in the ServeHTTP method, and add any properties that your middleware may need to access to the struct type you defined your middleware to be.
|
||||
|
||||
## Return Values and Writing Responses
|
||||
|
||||
Oh yes, those pesky return values. You read the documentation so you already know what they mean. But what does that imply for the behavior of your middleware?
|
||||
|
||||
Some handlers are endpoints: they create a response and write it along with the status code to the client. Effectively, this terminates the chain. You wouldn't want to write a document out to the client and then tell the next handler in the chain, "Okay it's all yours!" In this situation, you would *not* call Next().
|
||||
|
||||
So you've written the response to the client and you aren't calling the next handler. What do you return? If your handler completed successfully (and wrote the response), simply return the status code you wrote and a nil error.
|
||||
|
||||
But what if there was an error? If your handler fails and the client should receive an error response (HTTP status >= 400), your handler *should NOT* write anything—not even the status code—to the response. To handle errors consistently, the application or a dedicated error-handling middleware should take care of that (Caddy already has such middleware).
|
||||
|
||||
Also note that the status code return value is for the client's benefit, and the error return value is for the server. The server should (probably) not write the error string to the client. Instead, it should log it or report it privately somehow. The client should, however, receive a response with the appropriate status code. An error status code doesn't always have to correspond to a non-nil error value (for example, a 404 error doesn't usually require an entry in the error log).
|
||||
|
||||
## Integrating with Caddy
|
||||
|
||||
Now that your general-purpose middleware handler is working, it's time to integrate it with Caddy. Caddy parses middleware configuration out of a configuration file, so Caddy provides a parse facility for you to easily set up your middleware based on what the user typed in the text file.
|
Loading…
x
Reference in New Issue
Block a user