github.com/daragao/go-ethereum@v1.8.14-0.20180809141559-45eaef243198/swarm/api/http/middleware.go (about) 1 package http 2 3 import ( 4 "fmt" 5 "net/http" 6 "runtime/debug" 7 "strings" 8 9 "github.com/ethereum/go-ethereum/metrics" 10 "github.com/ethereum/go-ethereum/swarm/api" 11 "github.com/ethereum/go-ethereum/swarm/log" 12 "github.com/ethereum/go-ethereum/swarm/spancontext" 13 "github.com/pborman/uuid" 14 ) 15 16 // Adapt chains h (main request handler) main handler to adapters (middleware handlers) 17 // Please note that the order of execution for `adapters` is FIFO (adapters[0] will be executed first) 18 func Adapt(h http.Handler, adapters ...Adapter) http.Handler { 19 for i := range adapters { 20 adapter := adapters[len(adapters)-1-i] 21 h = adapter(h) 22 } 23 return h 24 } 25 26 type Adapter func(http.Handler) http.Handler 27 28 func SetRequestID(h http.Handler) http.Handler { 29 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 30 r = r.WithContext(SetRUID(r.Context(), uuid.New()[:8])) 31 metrics.GetOrRegisterCounter(fmt.Sprintf("http.request.%s", r.Method), nil).Inc(1) 32 log.Info("created ruid for request", "ruid", GetRUID(r.Context()), "method", r.Method, "url", r.RequestURI) 33 34 h.ServeHTTP(w, r) 35 }) 36 } 37 38 func ParseURI(h http.Handler) http.Handler { 39 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 40 uri, err := api.Parse(strings.TrimLeft(r.URL.Path, "/")) 41 if err != nil { 42 w.WriteHeader(http.StatusBadRequest) 43 RespondError(w, r, fmt.Sprintf("invalid URI %q", r.URL.Path), http.StatusBadRequest) 44 return 45 } 46 if uri.Addr != "" && strings.HasPrefix(uri.Addr, "0x") { 47 uri.Addr = strings.TrimPrefix(uri.Addr, "0x") 48 49 msg := fmt.Sprintf(`The requested hash seems to be prefixed with '0x'. You will be redirected to the correct URL within 5 seconds.<br/> 50 Please click <a href='%[1]s'>here</a> if your browser does not redirect you within 5 seconds.<script>setTimeout("location.href='%[1]s';",5000);</script>`, "/"+uri.String()) 51 w.WriteHeader(http.StatusNotFound) 52 w.Write([]byte(msg)) 53 return 54 } 55 56 ctx := r.Context() 57 r = r.WithContext(SetURI(ctx, uri)) 58 log.Debug("parsed request path", "ruid", GetRUID(r.Context()), "method", r.Method, "uri.Addr", uri.Addr, "uri.Path", uri.Path, "uri.Scheme", uri.Scheme) 59 60 h.ServeHTTP(w, r) 61 }) 62 } 63 64 func InitLoggingResponseWriter(h http.Handler) http.Handler { 65 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 66 writer := newLoggingResponseWriter(w) 67 68 h.ServeHTTP(writer, r) 69 }) 70 } 71 72 func InstrumentOpenTracing(h http.Handler) http.Handler { 73 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 74 uri := GetURI(r.Context()) 75 if uri == nil || r.Method == "" || (uri != nil && uri.Scheme == "") { 76 h.ServeHTTP(w, r) // soft fail 77 return 78 } 79 spanName := fmt.Sprintf("http.%s.%s", r.Method, uri.Scheme) 80 ctx, sp := spancontext.StartSpan(r.Context(), spanName) 81 defer sp.Finish() 82 h.ServeHTTP(w, r.WithContext(ctx)) 83 }) 84 } 85 86 func RecoverPanic(h http.Handler) http.Handler { 87 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 88 defer func() { 89 if err := recover(); err != nil { 90 log.Error("panic recovery!", "stack trace", debug.Stack(), "url", r.URL.String(), "headers", r.Header) 91 } 92 }() 93 h.ServeHTTP(w, r) 94 }) 95 }