| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- package http
- import (
- "fmt"
- "net/http"
- "runtime/debug"
- "strings"
- "github.com/ethereum/go-ethereum/metrics"
- "github.com/ethereum/go-ethereum/swarm/api"
- "github.com/ethereum/go-ethereum/swarm/log"
- "github.com/ethereum/go-ethereum/swarm/spancontext"
- "github.com/pborman/uuid"
- )
- // Adapt chains h (main request handler) main handler to adapters (middleware handlers)
- // Please note that the order of execution for `adapters` is FIFO (adapters[0] will be executed first)
- func Adapt(h http.Handler, adapters ...Adapter) http.Handler {
- for i := range adapters {
- adapter := adapters[len(adapters)-1-i]
- h = adapter(h)
- }
- return h
- }
- type Adapter func(http.Handler) http.Handler
- func SetRequestID(h http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- r = r.WithContext(SetRUID(r.Context(), uuid.New()[:8]))
- metrics.GetOrRegisterCounter(fmt.Sprintf("http.request.%s", r.Method), nil).Inc(1)
- log.Info("created ruid for request", "ruid", GetRUID(r.Context()), "method", r.Method, "url", r.RequestURI)
- h.ServeHTTP(w, r)
- })
- }
- func ParseURI(h http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- uri, err := api.Parse(strings.TrimLeft(r.URL.Path, "/"))
- if err != nil {
- w.WriteHeader(http.StatusBadRequest)
- RespondError(w, r, fmt.Sprintf("invalid URI %q", r.URL.Path), http.StatusBadRequest)
- return
- }
- if uri.Addr != "" && strings.HasPrefix(uri.Addr, "0x") {
- uri.Addr = strings.TrimPrefix(uri.Addr, "0x")
- msg := fmt.Sprintf(`The requested hash seems to be prefixed with '0x'. You will be redirected to the correct URL within 5 seconds.<br/>
- 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())
- w.WriteHeader(http.StatusNotFound)
- w.Write([]byte(msg))
- return
- }
- ctx := r.Context()
- r = r.WithContext(SetURI(ctx, uri))
- log.Debug("parsed request path", "ruid", GetRUID(r.Context()), "method", r.Method, "uri.Addr", uri.Addr, "uri.Path", uri.Path, "uri.Scheme", uri.Scheme)
- h.ServeHTTP(w, r)
- })
- }
- func InitLoggingResponseWriter(h http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- writer := newLoggingResponseWriter(w)
- h.ServeHTTP(writer, r)
- log.Debug("request served", "ruid", GetRUID(r.Context()), "code", writer.statusCode)
- })
- }
- func InstrumentOpenTracing(h http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- uri := GetURI(r.Context())
- if uri == nil || r.Method == "" || (uri != nil && uri.Scheme == "") {
- h.ServeHTTP(w, r) // soft fail
- return
- }
- spanName := fmt.Sprintf("http.%s.%s", r.Method, uri.Scheme)
- ctx, sp := spancontext.StartSpan(r.Context(), spanName)
- defer sp.Finish()
- h.ServeHTTP(w, r.WithContext(ctx))
- })
- }
- func RecoverPanic(h http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- defer func() {
- if err := recover(); err != nil {
- log.Error("panic recovery!", "stack trace", debug.Stack(), "url", r.URL.String(), "headers", r.Header)
- }
- }()
- h.ServeHTTP(w, r)
- })
- }
|