Commit 7dd385f6 authored by Carter's avatar Carter Committed by GitHub

Merge pull request #1023 from mholt/log-request-body

Now logging the request body
parents c8a99d2f ac0dd303
package httpserver package httpserver
import ( import (
"bytes"
"io"
"io/ioutil"
"net" "net"
"net/http" "net/http"
"net/http/httputil" "net/http/httputil"
...@@ -116,6 +119,18 @@ func NewReplacer(r *http.Request, rr *ResponseRecorder, emptyValue string) Repla ...@@ -116,6 +119,18 @@ func NewReplacer(r *http.Request, rr *ResponseRecorder, emptyValue string) Repla
return requestReplacer.Replace(string(dump)) return requestReplacer.Replace(string(dump))
}, },
"{request_body}": func() string {
if !canLogRequest(r) {
return ""
}
body, err := readRequestBody(r, maxLogBodySize)
if err != nil {
return ""
}
return requestReplacer.Replace(string(body))
},
}, },
emptyValue: emptyValue, emptyValue: emptyValue,
} }
...@@ -129,6 +144,39 @@ func NewReplacer(r *http.Request, rr *ResponseRecorder, emptyValue string) Repla ...@@ -129,6 +144,39 @@ func NewReplacer(r *http.Request, rr *ResponseRecorder, emptyValue string) Repla
return rep return rep
} }
func canLogRequest(r *http.Request) bool {
if r.Method == "POST" || r.Method == "PUT" {
for _, cType := range r.Header[headerContentType] {
// the cType could have charset and other info
if strings.Index(cType, contentTypeJSON) > -1 || strings.Index(cType, contentTypeXML) > -1 {
return true
}
}
}
return false
}
// readRequestBody reads the request body and sets a
// new io.ReadCloser that has not yet been read.
func readRequestBody(r *http.Request, n int64) ([]byte, error) {
defer r.Body.Close()
body, err := ioutil.ReadAll(io.LimitReader(r.Body, n))
if err != nil {
return nil, err
}
// Read the remaining bytes
remaining, err := ioutil.ReadAll(r.Body)
if err != nil {
return nil, err
}
buf := bytes.NewBuffer(append(body, remaining...))
r.Body = ioutil.NopCloser(buf)
return body, nil
}
// Replace performs a replacement of values on s and returns // Replace performs a replacement of values on s and returns
// the string with the replaced values. // the string with the replaced values.
func (r *replacer) Replace(s string) string { func (r *replacer) Replace(s string) string {
...@@ -223,6 +271,10 @@ func (r *replacer) Set(key, value string) { ...@@ -223,6 +271,10 @@ func (r *replacer) Set(key, value string) {
} }
const ( const (
timeFormat = "02/Jan/2006:15:04:05 -0700" timeFormat = "02/Jan/2006:15:04:05 -0700"
headerReplacer = "{>" headerReplacer = "{>"
headerContentType = "Content-Type"
contentTypeJSON = "application/json"
contentTypeXML = "application/xml"
maxLogBodySize = 100 * 1024
) )
package httpserver package httpserver
import ( import (
"bytes"
"io/ioutil"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"os" "os"
...@@ -161,3 +163,28 @@ func TestRound(t *testing.T) { ...@@ -161,3 +163,28 @@ func TestRound(t *testing.T) {
} }
} }
} }
func TestReadRequestBody(t *testing.T) {
payload := []byte(`{ "foo": "bar" }`)
var readSize int64 = 5
r, err := http.NewRequest("POST", "/", bytes.NewReader(payload))
if err != nil {
t.Error(err)
}
defer r.Body.Close()
logBody, err := readRequestBody(r, readSize)
if err != nil {
t.Error("readRequestBody failed", err)
} else if !bytes.EqualFold(payload[0:readSize], logBody) {
t.Error("Expected log comparison failed")
}
// Ensure the Request body is the same as the original.
reqBody, err := ioutil.ReadAll(r.Body)
if err != nil {
t.Error("Unable to read request body", err)
} else if !bytes.EqualFold(payload, reqBody) {
t.Error("Expected request body comparison failed")
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment