github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/swarm/api/http/middleware.go (about)

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