github.com/alexdevranger/node-1.8.27@v0.0.0-20221128213301-aa5841e41d2d/swarm/api/http/middleware.go (about)

     1  package http
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"runtime/debug"
     7  	"strings"
     8  	"time"
     9  
    10  	"github.com/alexdevranger/node-1.8.27/metrics"
    11  	"github.com/alexdevranger/node-1.8.27/swarm/api"
    12  	"github.com/alexdevranger/node-1.8.27/swarm/log"
    13  	"github.com/alexdevranger/node-1.8.27/swarm/sctx"
    14  	"github.com/alexdevranger/node-1.8.27/swarm/spancontext"
    15  	"github.com/pborman/uuid"
    16  )
    17  
    18  // Adapt chains h (main request handler) main handler to adapters (middleware handlers)
    19  // Please note that the order of execution for `adapters` is FIFO (adapters[0] will be executed first)
    20  func Adapt(h http.Handler, adapters ...Adapter) http.Handler {
    21  	for i := range adapters {
    22  		adapter := adapters[len(adapters)-1-i]
    23  		h = adapter(h)
    24  	}
    25  	return h
    26  }
    27  
    28  type Adapter func(http.Handler) http.Handler
    29  
    30  func SetRequestID(h http.Handler) http.Handler {
    31  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    32  		r = r.WithContext(SetRUID(r.Context(), uuid.New()[:8]))
    33  		metrics.GetOrRegisterCounter(fmt.Sprintf("http.request.%s", r.Method), nil).Inc(1)
    34  		log.Info("created ruid for request", "ruid", GetRUID(r.Context()), "method", r.Method, "url", r.RequestURI)
    35  
    36  		h.ServeHTTP(w, r)
    37  	})
    38  }
    39  
    40  func SetRequestHost(h http.Handler) http.Handler {
    41  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    42  		r = r.WithContext(sctx.SetHost(r.Context(), r.Host))
    43  		log.Info("setting request host", "ruid", GetRUID(r.Context()), "host", sctx.GetHost(r.Context()))
    44  
    45  		h.ServeHTTP(w, r)
    46  	})
    47  }
    48  
    49  func ParseURI(h http.Handler) http.Handler {
    50  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    51  		uri, err := api.Parse(strings.TrimLeft(r.URL.Path, "/"))
    52  		if err != nil {
    53  			w.WriteHeader(http.StatusBadRequest)
    54  			respondError(w, r, fmt.Sprintf("invalid URI %q", r.URL.Path), http.StatusBadRequest)
    55  			return
    56  		}
    57  		if uri.Addr != "" && strings.HasPrefix(uri.Addr, "0x") {
    58  			uri.Addr = strings.TrimPrefix(uri.Addr, "0x")
    59  
    60  			msg := fmt.Sprintf(`The requested hash seems to be prefixed with '0x'. You will be redirected to the correct URL within 5 seconds.<br/>
    61  			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())
    62  			w.WriteHeader(http.StatusNotFound)
    63  			w.Write([]byte(msg))
    64  			return
    65  		}
    66  
    67  		ctx := r.Context()
    68  		r = r.WithContext(SetURI(ctx, uri))
    69  		log.Debug("parsed request path", "ruid", GetRUID(r.Context()), "method", r.Method, "uri.Addr", uri.Addr, "uri.Path", uri.Path, "uri.Scheme", uri.Scheme)
    70  
    71  		h.ServeHTTP(w, r)
    72  	})
    73  }
    74  
    75  func InitLoggingResponseWriter(h http.Handler) http.Handler {
    76  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    77  		tn := time.Now()
    78  
    79  		writer := newLoggingResponseWriter(w)
    80  		h.ServeHTTP(writer, r)
    81  
    82  		ts := time.Since(tn)
    83  		log.Info("request served", "ruid", GetRUID(r.Context()), "code", writer.statusCode, "time", ts)
    84  		metrics.GetOrRegisterResettingTimer(fmt.Sprintf("http.request.%s.time", r.Method), nil).Update(ts)
    85  		metrics.GetOrRegisterResettingTimer(fmt.Sprintf("http.request.%s.%d.time", r.Method, writer.statusCode), nil).Update(ts)
    86  	})
    87  }
    88  
    89  func InstrumentOpenTracing(h http.Handler) http.Handler {
    90  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    91  		uri := GetURI(r.Context())
    92  		if uri == nil || r.Method == "" || (uri != nil && uri.Scheme == "") {
    93  			h.ServeHTTP(w, r) // soft fail
    94  			return
    95  		}
    96  		spanName := fmt.Sprintf("http.%s.%s", r.Method, uri.Scheme)
    97  		ctx, sp := spancontext.StartSpan(r.Context(), spanName)
    98  
    99  		defer sp.Finish()
   100  		h.ServeHTTP(w, r.WithContext(ctx))
   101  	})
   102  }
   103  
   104  func RecoverPanic(h http.Handler) http.Handler {
   105  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   106  		defer func() {
   107  			if err := recover(); err != nil {
   108  				log.Error("panic recovery!", "stack trace", string(debug.Stack()), "url", r.URL.String(), "headers", r.Header)
   109  			}
   110  		}()
   111  		h.ServeHTTP(w, r)
   112  	})
   113  }