diff options
author | Matthew Holt <mholt@users.noreply.github.com> | 2020-07-16 19:25:37 -0600 |
---|---|---|
committer | Matthew Holt <mholt@users.noreply.github.com> | 2020-07-16 19:25:37 -0600 |
commit | 6f0f159ba56adeb6e2cbbb408651419b87f20856 (patch) | |
tree | 8717630e518b964358c6873a3c740403c1851047 | |
parent | 6eafd4e82fbf894067e474b4cffa5d3d8498705d (diff) |
caddyhttp: Add {http.request.body} placeholder
-rw-r--r-- | modules/caddyhttp/app.go | 1 | ||||
-rw-r--r-- | modules/caddyhttp/replacer.go | 21 |
2 files changed, 22 insertions, 0 deletions
diff --git a/modules/caddyhttp/app.go b/modules/caddyhttp/app.go index 45845ea..40ae3a2 100644 --- a/modules/caddyhttp/app.go +++ b/modules/caddyhttp/app.go @@ -47,6 +47,7 @@ func init() { // // Placeholder | Description // ------------|--------------- +// `{http.request.body}` | The request body (⚠️ inefficient; use only for debugging) // `{http.request.cookie.*}` | HTTP request cookie // `{http.request.header.*}` | Specific request header field // `{http.request.host.labels.*}` | Request host labels (0-based from right); e.g. for foo.example.com: 0=com, 1=example, 2=foo diff --git a/modules/caddyhttp/replacer.go b/modules/caddyhttp/replacer.go index f595021..3f4a808 100644 --- a/modules/caddyhttp/replacer.go +++ b/modules/caddyhttp/replacer.go @@ -15,6 +15,7 @@ package caddyhttp import ( + "bytes" "context" "crypto/ecdsa" "crypto/ed25519" @@ -25,6 +26,8 @@ import ( "crypto/x509" "encoding/asn1" "fmt" + "io" + "io/ioutil" "net" "net/http" "net/textproto" @@ -136,6 +139,24 @@ func addHTTPVarsToReplacer(repl *caddy.Replacer, req *http.Request, w http.Respo return dir, true case "http.request.uri.query": return req.URL.RawQuery, true + case "http.request.body": + if req.Body == nil { + return "", true + } + // normally net/http will close the body for us, but since we + // are replacing it with a fake one, we have to ensure we close + // the real body ourselves when we're done + defer req.Body.Close() + // read the request body into a buffer (can't pool because we + // don't know its lifetime and would have to make a copy anyway) + buf := new(bytes.Buffer) + _, err := io.Copy(buf, req.Body) + if err != nil { + return "", true + } + // replace real body with buffered data + req.Body = ioutil.NopCloser(buf) + return buf.String(), true // original request, before any internal changes case "http.request.orig_method": |