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