mirror of
				https://github.com/containers/podman.git
				synced 2025-11-04 17:07:20 +08:00 
			
		
		
		
	When the service is running with trace log level it wraps the `http.ResponseWriter` to log extra information. The problem is that the new type does not keep all the functions from the embedded type. Instead we have to implement them ourselves, however only Write() was implemented. Thus `Hijack()`could not be called on the writer. To prevent these issues we would implement all the interfaces that the inner type supports (Header, WriteHeader, Flush, Hijack). Fixes #17749 Signed-off-by: Paul Holzinger <pholzing@redhat.com>
		
			
				
	
	
		
			76 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			76 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package server
 | 
						|
 | 
						|
import (
 | 
						|
	"bufio"
 | 
						|
	"errors"
 | 
						|
	"io"
 | 
						|
	"net"
 | 
						|
	"net/http"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/gorilla/mux"
 | 
						|
	"github.com/sirupsen/logrus"
 | 
						|
)
 | 
						|
 | 
						|
type responseWriter struct {
 | 
						|
	http.ResponseWriter
 | 
						|
}
 | 
						|
 | 
						|
var apiLogger = &logrus.Logger{
 | 
						|
	Formatter: &logrus.TextFormatter{
 | 
						|
		DisableColors:          true,
 | 
						|
		DisableLevelTruncation: true,
 | 
						|
		FullTimestamp:          true,
 | 
						|
		QuoteEmptyFields:       true,
 | 
						|
		TimestampFormat:        time.RFC3339,
 | 
						|
	},
 | 
						|
	Level: logrus.TraceLevel,
 | 
						|
	Out:   logrus.StandardLogger().Out,
 | 
						|
}
 | 
						|
 | 
						|
func (l responseWriter) Write(b []byte) (int, error) {
 | 
						|
	apiLogger.WithFields(logrus.Fields{
 | 
						|
		"API":            "response",
 | 
						|
		"X-Reference-Id": l.Header().Get("X-Reference-Id"),
 | 
						|
	}).Trace(string(b))
 | 
						|
	return l.ResponseWriter.Write(b)
 | 
						|
}
 | 
						|
 | 
						|
func (l responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
 | 
						|
	if wrapped, ok := l.ResponseWriter.(http.Hijacker); ok {
 | 
						|
		return wrapped.Hijack()
 | 
						|
	}
 | 
						|
 | 
						|
	return nil, nil, errors.New("ResponseWriter does not support hijacking")
 | 
						|
}
 | 
						|
 | 
						|
func (l responseWriter) Header() http.Header {
 | 
						|
	return l.ResponseWriter.Header()
 | 
						|
}
 | 
						|
 | 
						|
func (l responseWriter) WriteHeader(statusCode int) {
 | 
						|
	l.ResponseWriter.WriteHeader(statusCode)
 | 
						|
}
 | 
						|
 | 
						|
func (l responseWriter) Flush() {
 | 
						|
	if wrapped, ok := l.ResponseWriter.(http.Flusher); ok {
 | 
						|
		wrapped.Flush()
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func loggingHandler() mux.MiddlewareFunc {
 | 
						|
	return func(h http.Handler) http.Handler {
 | 
						|
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 | 
						|
			annotated := apiLogger.WithFields(logrus.Fields{
 | 
						|
				"API":            "request",
 | 
						|
				"X-Reference-Id": r.Header.Get("X-Reference-Id"),
 | 
						|
			})
 | 
						|
			r.Body = io.NopCloser(
 | 
						|
				io.TeeReader(r.Body, annotated.WriterLevel(logrus.TraceLevel)))
 | 
						|
 | 
						|
			w = responseWriter{ResponseWriter: w}
 | 
						|
			h.ServeHTTP(w, r)
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 |