In v1’s case there’s a corpus of existing open source third party plugins to draw inspiration from, but v2 is still in its early days.
There is a complete HTTP handler module example, which is where I expect you would want to implement a WAF (see: Extending Caddy — Caddy Documentation).
You get the http.Request passed to your ServeHTTP function, which is where the magic happens, so you can do a lot of inspection here based on what the http standard library gives you (see: http package - net/http - pkg.go.dev).
Those questions are more about how to approach web development in Go than being Caddy specific. If you’re already familiar with basics of Go, then you can follow these 2 tutorials sequentially:
Just to elaborate a bit further, we benefit from being able to use Golang’s standard http library. This library is incredibly widely used and incredibly widely documented, with tutorials everywhere. Just the godoc alone (see: https://godoc.org/net/http) is incredibly useful.
So the first few you’re looking for - definitely aren’t specific to Caddy at all. There’s much better literature out there explaining how to interact with those, and we’d be doing their authors and our readers a disservice by trying to recreate those guides and tutorials. As for these parts:
To be clear, there’s no response already built for you when your ServeHTTP function receives the request. It gets the http.Request and a http.ResponseWriter. You can write whatever you want to the ResponseWriter - you are 100% in charge. It’s entirely up to you how you do it - some conventional way (the tutorials linked above are great), or by importing other libs that help with the process, it’s your call. You can do almost literally anything. There’s nothing to modify or change. You get a blank slate.
You want to respond differently if a request is not valid? Time to throw in some conditional statements. Build your “invalid request” response and decide how you want to handle a “valid” request (maybe pass it along to the next handler?).