mirror of
https://github.com/caddyserver/caddy.git
synced 2024-11-25 17:56:34 +08:00
httpserver: give each req context a Replacer that preserves custom values (#1937)
This allows custom replacements to be defined in a way that propagates throughout all plugins.
This commit is contained in:
parent
169ab3acda
commit
9a22cda15d
|
@ -214,6 +214,9 @@ func SameNext(next1, next2 Handler) bool {
|
||||||
|
|
||||||
// Context key constants.
|
// Context key constants.
|
||||||
const (
|
const (
|
||||||
|
// ReplacerCtxKey is the context key for a per-request replacer.
|
||||||
|
ReplacerCtxKey caddy.CtxKey = "replacer"
|
||||||
|
|
||||||
// RemoteUserCtxKey is the key for the remote user of the request, if any (basicauth).
|
// RemoteUserCtxKey is the key for the remote user of the request, if any (basicauth).
|
||||||
RemoteUserCtxKey caddy.CtxKey = "remote_user"
|
RemoteUserCtxKey caddy.CtxKey = "remote_user"
|
||||||
|
|
||||||
|
|
|
@ -102,20 +102,30 @@ func (lw *limitWriter) String() string {
|
||||||
// emptyValue should be the string that is used in place
|
// emptyValue should be the string that is used in place
|
||||||
// of empty string (can still be empty string).
|
// of empty string (can still be empty string).
|
||||||
func NewReplacer(r *http.Request, rr *ResponseRecorder, emptyValue string) Replacer {
|
func NewReplacer(r *http.Request, rr *ResponseRecorder, emptyValue string) Replacer {
|
||||||
rb := newLimitWriter(MaxLogBodySize)
|
repl := &replacer{
|
||||||
if r.Body != nil {
|
request: r,
|
||||||
r.Body = struct {
|
responseRecorder: rr,
|
||||||
io.Reader
|
emptyValue: emptyValue,
|
||||||
io.Closer
|
|
||||||
}{io.TeeReader(r.Body, rb), io.Closer(r.Body)}
|
|
||||||
}
|
}
|
||||||
return &replacer{
|
|
||||||
request: r,
|
// extract customReplacements from a request replacer when present.
|
||||||
requestBody: rb,
|
if existing, ok := r.Context().Value(ReplacerCtxKey).(*replacer); ok {
|
||||||
responseRecorder: rr,
|
repl.requestBody = existing.requestBody
|
||||||
customReplacements: make(map[string]string),
|
repl.customReplacements = existing.customReplacements
|
||||||
emptyValue: emptyValue,
|
} else {
|
||||||
|
// if there is no existing replacer, build one from scratch.
|
||||||
|
rb := newLimitWriter(MaxLogBodySize)
|
||||||
|
if r.Body != nil {
|
||||||
|
r.Body = struct {
|
||||||
|
io.Reader
|
||||||
|
io.Closer
|
||||||
|
}{io.TeeReader(r.Body, rb), io.Closer(r.Body)}
|
||||||
|
}
|
||||||
|
repl.requestBody = rb
|
||||||
|
repl.customReplacements = make(map[string]string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return repl
|
||||||
}
|
}
|
||||||
|
|
||||||
func canLogRequest(r *http.Request) bool {
|
func canLogRequest(r *http.Request) bool {
|
||||||
|
|
|
@ -356,6 +356,12 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
c := context.WithValue(r.Context(), OriginalURLCtxKey, urlCopy)
|
c := context.WithValue(r.Context(), OriginalURLCtxKey, urlCopy)
|
||||||
r = r.WithContext(c)
|
r = r.WithContext(c)
|
||||||
|
|
||||||
|
// Setup a replacer for the request that keeps track of placeholder
|
||||||
|
// values across plugins.
|
||||||
|
replacer := NewReplacer(r, nil, "")
|
||||||
|
c = context.WithValue(r.Context(), ReplacerCtxKey, replacer)
|
||||||
|
r = r.WithContext(c)
|
||||||
|
|
||||||
w.Header().Set("Server", caddy.AppName)
|
w.Header().Set("Server", caddy.AppName)
|
||||||
|
|
||||||
status, _ := s.serveHTTP(w, r)
|
status, _ := s.serveHTTP(w, r)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user