github.com/GuanceCloud/cliutils@v1.1.21/network/http/api_wrap.go (about)

     1  // Unless explicitly stated otherwise all files in this repository are licensed
     2  // under the MIT License.
     3  // This product includes software developed at Guance Cloud (https://www.guance.com/).
     4  // Copyright 2021-present Guance, Inc.
     5  
     6  package http
     7  
     8  import (
     9  	"errors"
    10  	"net/http"
    11  	"time"
    12  
    13  	"github.com/gin-gonic/gin"
    14  )
    15  
    16  var (
    17  	ErrTooManyRequest = NewErr(errors.New("reach max API rate limit"), http.StatusTooManyRequests)
    18  	HTTPOK            = NewErr(nil, http.StatusOK) //nolint:errname
    19  	EnableTracing     bool
    20  )
    21  
    22  type WrapPlugins struct {
    23  	Limiter  APIRateLimiter
    24  	Reporter APIMetricReporter
    25  }
    26  
    27  type apiHandler func(http.ResponseWriter, *http.Request, ...interface{}) (interface{}, error)
    28  
    29  func HTTPAPIWrapper(p *WrapPlugins, next apiHandler, args ...interface{}) func(*gin.Context) {
    30  	return func(c *gin.Context) {
    31  		var start time.Time
    32  		var m *APIMetric
    33  
    34  		if p != nil && p.Reporter != nil {
    35  			start = time.Now()
    36  			m = &APIMetric{
    37  				API: c.Request.URL.Path + "@" + c.Request.Method,
    38  			}
    39  		}
    40  
    41  		if p != nil && p.Limiter != nil {
    42  			if p.Limiter.RequestLimited(c.Request) {
    43  				HttpErr(c, ErrTooManyRequest)
    44  				p.Limiter.LimitReadchedCallback(c.Request)
    45  				if m != nil {
    46  					m.StatusCode = ErrTooManyRequest.HttpCode
    47  					m.Limited = true
    48  				}
    49  				c.Abort()
    50  				goto feed
    51  			}
    52  		}
    53  
    54  		if res, err := next(c.Writer, c.Request, args...); err != nil {
    55  			HttpErr(c, err)
    56  		} else {
    57  			HTTPOK.WriteBody(c, res)
    58  		}
    59  
    60  		if m != nil {
    61  			m.StatusCode = c.Writer.Status()
    62  			m.Latency = time.Since(start)
    63  		}
    64  
    65  	feed:
    66  		if p != nil && m != nil {
    67  			p.Reporter.Report(m)
    68  		}
    69  	}
    70  }