github.com/decred/politeia@v1.4.0/politeiad/middleware.go (about) 1 // Copyright (c) 2021 The Decred developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "fmt" 9 "net/http" 10 "net/http/httputil" 11 "runtime/debug" 12 "time" 13 14 v2 "github.com/decred/politeia/politeiad/api/v2" 15 "github.com/decred/politeia/util" 16 ) 17 18 // closeBodyMiddleware closes the request body. 19 func closeBodyMiddleware(next http.Handler) http.Handler { 20 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 21 next.ServeHTTP(w, r) 22 r.Body.Close() 23 }) 24 } 25 26 // loggingMiddleware logs all incoming commands before calling the next 27 // function. 28 func loggingMiddleware(next http.Handler) http.Handler { 29 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 30 // Trace incoming request 31 log.Tracef("%v", newLogClosure(func() string { 32 trace, err := httputil.DumpRequest(r, true) 33 if err != nil { 34 trace = []byte(fmt.Sprintf("logging: "+ 35 "DumpRequest %v", err)) 36 } 37 return string(trace) 38 })) 39 40 // Log incoming connection 41 log.Infof("%v %v %v %v", util.RemoteAddr(r), r.Method, r.URL, r.Proto) 42 43 // Call next handler 44 next.ServeHTTP(w, r) 45 }) 46 } 47 48 // recoverMiddleware recovers from any panics by logging the panic and 49 // returning a 500 response. 50 func recoverMiddleware(next http.Handler) http.Handler { 51 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 52 // Defer the function so that it gets executed when the request 53 // is being closed out, not when its being opened. 54 defer func() { 55 if err := recover(); err != nil { 56 errorCode := time.Now().Unix() 57 log.Criticalf("%v %v %v %v Internal error %v: %v", 58 util.RemoteAddr(r), r.Method, r.URL, r.Proto, errorCode, err) 59 60 log.Criticalf("Stacktrace (THIS IS AN ACTUAL PANIC): %s", 61 debug.Stack()) 62 63 util.RespondWithJSON(w, http.StatusInternalServerError, 64 v2.ServerErrorReply{ 65 ErrorCode: errorCode, 66 }) 67 } 68 }() 69 70 next.ServeHTTP(w, r) 71 }) 72 } 73 74 // middleware contains the middleware that use configurable settings. 75 type middleware struct { 76 reqBodySizeLimit int64 // In bytes 77 } 78 79 // reqBodySizeLimitMiddleware applies a maximum request body size limit to 80 // requests. 81 // 82 // NOTE: This will only cause an error if the request body is read by the 83 // request handler, e.g. the JSON from a POST request is decoded into a struct. 84 func (m *middleware) reqBodySizeLimitMiddleware(next http.Handler) http.Handler { 85 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 86 log.Tracef("Applying a max body size of %v bytes to the request body", 87 m.reqBodySizeLimit) 88 89 r.Body = http.MaxBytesReader(w, r.Body, m.reqBodySizeLimit) 90 next.ServeHTTP(w, r) 91 }) 92 }