github.com/Tyktechnologies/tyk@v2.9.5+incompatible/gateway/mw_request_size_limit.go (about) 1 package gateway 2 3 import ( 4 "errors" 5 "net/http" 6 "strconv" 7 8 "github.com/sirupsen/logrus" 9 10 "github.com/TykTechnologies/tyk/apidef" 11 "github.com/TykTechnologies/tyk/headers" 12 ) 13 14 // TransformMiddleware is a middleware that will apply a template to a request body to transform it's contents ready for an upstream API 15 type RequestSizeLimitMiddleware struct { 16 BaseMiddleware 17 } 18 19 func (t *RequestSizeLimitMiddleware) Name() string { 20 return "RequestSizeLimitMiddleware" 21 } 22 23 func (t *RequestSizeLimitMiddleware) EnabledForSpec() bool { 24 for _, version := range t.Spec.VersionData.Versions { 25 if len(version.ExtendedPaths.SizeLimit) > 0 { 26 return true 27 } 28 } 29 return false 30 } 31 32 func (t *RequestSizeLimitMiddleware) checkRequestLimit(r *http.Request, sizeLimit int64) (error, int) { 33 statedCL := r.Header.Get(headers.ContentLength) 34 if statedCL == "" { 35 return errors.New("Content length is required for this request"), 411 36 } 37 38 size, err := strconv.ParseInt(statedCL, 0, 64) 39 if err != nil { 40 t.Logger().WithError(err).Error("String conversion for content length failed") 41 return errors.New("content length is not a valid Integer"), http.StatusBadRequest 42 } 43 if r.ContentLength > size { 44 size = r.ContentLength 45 } 46 47 // Check stated size 48 if size > sizeLimit { 49 t.Logger().WithFields(logrus.Fields{"size": size, "limit": sizeLimit}).Info("Attempted access with large request size, blocked.") 50 51 return errors.New("Request is too large"), http.StatusBadRequest 52 } 53 54 return nil, http.StatusOK 55 } 56 57 // RequestSizeLimit will check a request for maximum request size, this can be a global limit or a matched limit. 58 func (t *RequestSizeLimitMiddleware) ProcessRequest(w http.ResponseWriter, r *http.Request, _ interface{}) (error, int) { 59 logger := t.Logger() 60 logger.Debug("Request size limiter active") 61 62 vInfo, versionPaths, _, _ := t.Spec.Version(r) 63 64 logger.Debug("Global limit is: ", vInfo.GlobalSizeLimit) 65 // Manage global headers first 66 if vInfo.GlobalSizeLimit > 0 { 67 logger.Debug("Checking global limit") 68 err, code := t.checkRequestLimit(r, vInfo.GlobalSizeLimit) 69 // If not OK, block 70 if code != http.StatusOK { 71 return err, code 72 } 73 } 74 75 // if there's no paths at all path check 76 if len(vInfo.ExtendedPaths.SizeLimit) == 0 { 77 return nil, http.StatusOK 78 } 79 80 // If there's a potential match, try to match 81 found, meta := t.Spec.CheckSpecMatchesStatus(r, versionPaths, RequestSizeLimit) 82 if found { 83 logger.Debug("Request size limit matched for this URL, checking...") 84 rmeta := meta.(*apidef.RequestSizeMeta) 85 return t.checkRequestLimit(r, rmeta.SizeLimit) 86 } 87 88 return nil, http.StatusOK 89 }