github.com/filecoin-project/bacalhau@v0.3.23-0.20230228154132-45c989550ace/pkg/publicapi/handlerwrapper/http_handler.go (about) 1 package handlerwrapper 2 3 import ( 4 "net/http" 5 "strings" 6 7 "github.com/felixge/httpsnoop" 8 ) 9 10 type HTTPHandlerWrapper struct { 11 nodeID string 12 httpHandler http.Handler 13 requestInfoHandler RequestInfoHandler 14 } 15 16 func NewHTTPHandlerWrapper( 17 nodeID string, 18 httpHandler http.Handler, 19 requestInfoHandler RequestInfoHandler) *HTTPHandlerWrapper { 20 return &HTTPHandlerWrapper{ 21 nodeID: nodeID, 22 httpHandler: httpHandler, 23 requestInfoHandler: requestInfoHandler, 24 } 25 } 26 27 // An HTTP handler that triggers another handler, capturs info about the request and calls request info handler. 28 func (wrapper *HTTPHandlerWrapper) ServeHTTP(w http.ResponseWriter, r *http.Request) { 29 ri := &HTTPRequestInfo{ 30 Method: r.Method, 31 URI: r.URL.String(), 32 Referer: r.Header.Get("Referer"), 33 UserAgent: r.Header.Get("User-Agent"), 34 NodeID: wrapper.nodeID, 35 } 36 37 ri.Ipaddr = requestGetRemoteAddress(r) 38 39 // this runs http handler and captures information about HTTP request 40 m := httpsnoop.CaptureMetrics(wrapper.httpHandler, w, r) 41 42 ri.StatusCode = m.Code 43 ri.Size = m.Written 44 ri.Duration = m.Duration.Milliseconds() 45 ri.ClientID = w.Header().Get(HTTPHeaderClientID) 46 ri.JobID = w.Header().Get(HTTPHeaderJobID) 47 wrapper.requestInfoHandler.Handle(r.Context(), ri) 48 } 49 50 // Request.RemoteAddress contains port, which we want to remove i.e.: 51 // "[::1]:58292" => "[::1]" 52 func ipAddrFromRemoteAddr(s string) string { 53 idx := strings.LastIndex(s, ":") 54 if idx == -1 { 55 return s 56 } 57 return s[:idx] 58 } 59 60 // requestGetRemoteAddress returns ip address of the client making the request, 61 // taking into account http proxies 62 func requestGetRemoteAddress(r *http.Request) string { 63 hdr := r.Header 64 hdrRealIP := hdr.Get("X-Real-Ip") 65 hdrForwardedFor := hdr.Get("X-Forwarded-For") 66 if hdrRealIP == "" && hdrForwardedFor == "" { 67 return ipAddrFromRemoteAddr(r.RemoteAddr) 68 } 69 if hdrForwardedFor != "" { 70 // X-Forwarded-For is potentially a list of addresses separated with "," 71 parts := strings.Split(hdrForwardedFor, ",") 72 for i, p := range parts { 73 parts[i] = strings.TrimSpace(p) 74 } 75 // TODO: should return first non-local address 76 return parts[0] 77 } 78 return hdrRealIP 79 }