github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/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 19:16:43</date>
    10  //</624450111744774144>
    11  
    12  package http
    13  
    14  import (
    15  	"fmt"
    16  	"net/http"
    17  	"runtime/debug"
    18  	"strings"
    19  	"time"
    20  
    21  	"github.com/ethereum/go-ethereum/metrics"
    22  	"github.com/ethereum/go-ethereum/swarm/api"
    23  	"github.com/ethereum/go-ethereum/swarm/log"
    24  	"github.com/ethereum/go-ethereum/swarm/sctx"
    25  	"github.com/ethereum/go-ethereum/swarm/spancontext"
    26  	"github.com/pborman/uuid"
    27  )
    28  
    29  //将链h(主请求处理程序)主处理程序适配到适配器(中间件处理程序)
    30  //请注意,“adapters”的执行顺序是FIFO(适配器[0]将首先执行)
    31  func Adapt(h http.Handler, adapters ...Adapter) http.Handler {
    32  	for i := range adapters {
    33  		adapter := adapters[len(adapters)-1-i]
    34  		h = adapter(h)
    35  	}
    36  	return h
    37  }
    38  
    39  type Adapter func(http.Handler) http.Handler
    40  
    41  func SetRequestID(h http.Handler) http.Handler {
    42  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    43  		r = r.WithContext(SetRUID(r.Context(), uuid.New()[:8]))
    44  		metrics.GetOrRegisterCounter(fmt.Sprintf("http.request.%s", r.Method), nil).Inc(1)
    45  		log.Info("created ruid for request", "ruid", GetRUID(r.Context()), "method", r.Method, "url", r.RequestURI)
    46  
    47  		h.ServeHTTP(w, r)
    48  	})
    49  }
    50  
    51  func SetRequestHost(h http.Handler) http.Handler {
    52  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    53  		r = r.WithContext(sctx.SetHost(r.Context(), r.Host))
    54  		log.Info("setting request host", "ruid", GetRUID(r.Context()), "host", sctx.GetHost(r.Context()))
    55  
    56  		h.ServeHTTP(w, r)
    57  	})
    58  }
    59  
    60  func ParseURI(h http.Handler) http.Handler {
    61  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    62  		uri, err := api.Parse(strings.TrimLeft(r.URL.Path, "/"))
    63  		if err != nil {
    64  			w.WriteHeader(http.StatusBadRequest)
    65  			respondError(w, r, fmt.Sprintf("invalid URI %q", r.URL.Path), http.StatusBadRequest)
    66  			return
    67  		}
    68  		if uri.Addr != "" && strings.HasPrefix(uri.Addr, "0x") {
    69  			uri.Addr = strings.TrimPrefix(uri.Addr, "0x")
    70  
    71  			msg := fmt.Sprintf(`The requested hash seems to be prefixed with '0x'. You will be redirected to the correct URL within 5 seconds.<br/>
    72  			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())
    73  			w.WriteHeader(http.StatusNotFound)
    74  			w.Write([]byte(msg))
    75  			return
    76  		}
    77  
    78  		ctx := r.Context()
    79  		r = r.WithContext(SetURI(ctx, uri))
    80  		log.Debug("parsed request path", "ruid", GetRUID(r.Context()), "method", r.Method, "uri.Addr", uri.Addr, "uri.Path", uri.Path, "uri.Scheme", uri.Scheme)
    81  
    82  		h.ServeHTTP(w, r)
    83  	})
    84  }
    85  
    86  func InitLoggingResponseWriter(h http.Handler) http.Handler {
    87  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    88  		tn := time.Now()
    89  
    90  		writer := newLoggingResponseWriter(w)
    91  		h.ServeHTTP(writer, r)
    92  
    93  		ts := time.Since(tn)
    94  		log.Info("request served", "ruid", GetRUID(r.Context()), "code", writer.statusCode, "time", ts)
    95  		metrics.GetOrRegisterResettingTimer(fmt.Sprintf("http.request.%s.time", r.Method), nil).Update(ts)
    96  		metrics.GetOrRegisterResettingTimer(fmt.Sprintf("http.request.%s.%d.time", r.Method, writer.statusCode), nil).Update(ts)
    97  	})
    98  }
    99  
   100  func InstrumentOpenTracing(h http.Handler) http.Handler {
   101  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   102  		uri := GetURI(r.Context())
   103  		if uri == nil || r.Method == "" || (uri != nil && uri.Scheme == "") {
   104  h.ServeHTTP(w, r) //软故障
   105  			return
   106  		}
   107  		spanName := fmt.Sprintf("http.%s.%s", r.Method, uri.Scheme)
   108  		ctx, sp := spancontext.StartSpan(r.Context(), spanName)
   109  
   110  		defer sp.Finish()
   111  		h.ServeHTTP(w, r.WithContext(ctx))
   112  	})
   113  }
   114  
   115  func RecoverPanic(h http.Handler) http.Handler {
   116  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   117  		defer func() {
   118  			if err := recover(); err != nil {
   119  				log.Error("panic recovery!", "stack trace", string(debug.Stack()), "url", r.URL.String(), "headers", r.Header)
   120  			}
   121  		}()
   122  		h.ServeHTTP(w, r)
   123  	})
   124  }
   125