Rendering: Add support for rate limiter (#103987)

* Rendering: Add support for rate limiter

* remove unnecessary golint exception

* add lint exception back
pull/104470/head
Agnès Toulet 4 weeks ago committed by GitHub
parent f0c841b9bc
commit e7b800f35a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 5
      pkg/api/render.go
  2. 6
      pkg/services/rendering/http_mode.go
  3. 1
      pkg/services/rendering/interface.go

@ -98,6 +98,11 @@ func (hs *HTTPServer) RenderHandler(c *contextmodel.ReqContext) {
Theme: themeModel, Theme: themeModel,
}, nil) }, nil)
if err != nil { if err != nil {
if errors.Is(err, rendering.ErrTooManyRequests) {
c.JsonApiErr(http.StatusTooManyRequests, "Too many rendering requests", err)
return
}
if errors.Is(err, rendering.ErrTimeout) { if errors.Is(err, rendering.ErrTimeout) {
c.Handle(hs.Cfg, http.StatusInternalServerError, err.Error(), err) c.Handle(hs.Cfg, http.StatusInternalServerError, err.Error(), err)
return return

@ -31,6 +31,7 @@ var netClient = &http.Client{
} }
const authTokenHeader = "X-Auth-Token" //#nosec G101 -- This is a false positive const authTokenHeader = "X-Auth-Token" //#nosec G101 -- This is a false positive
const rateLimiterHeader = "X-Tenant-ID"
var ( var (
remoteVersionFetchInterval time.Duration = time.Second * 15 remoteVersionFetchInterval time.Duration = time.Second * 15
@ -160,6 +161,7 @@ func (rs *RenderingService) doRequest(ctx context.Context, u *url.URL, headers m
} }
req.Header.Set(authTokenHeader, rs.Cfg.RendererAuthToken) req.Header.Set(authTokenHeader, rs.Cfg.RendererAuthToken)
req.Header.Set(rateLimiterHeader, rs.domain)
req.Header.Set("User-Agent", fmt.Sprintf("Grafana/%s", rs.Cfg.BuildVersion)) req.Header.Set("User-Agent", fmt.Sprintf("Grafana/%s", rs.Cfg.BuildVersion))
for k, v := range headers { for k, v := range headers {
req.Header[k] = v req.Header[k] = v
@ -180,6 +182,10 @@ func (rs *RenderingService) doRequest(ctx context.Context, u *url.URL, headers m
return nil, fmt.Errorf("failed to send request to remote rendering service: %w", err) return nil, fmt.Errorf("failed to send request to remote rendering service: %w", err)
} }
if resp.StatusCode == http.StatusTooManyRequests {
return nil, ErrTooManyRequests
}
return resp, nil return resp, nil
} }

@ -14,6 +14,7 @@ var ErrTimeout = errors.New("timeout error - you can set timeout in seconds with
var ErrConcurrentLimitReached = errors.New("rendering concurrent limit reached") var ErrConcurrentLimitReached = errors.New("rendering concurrent limit reached")
var ErrRenderUnavailable = errors.New("rendering plugin not available") var ErrRenderUnavailable = errors.New("rendering plugin not available")
var ErrServerTimeout = errutil.NewBase(errutil.StatusUnknown, "rendering.serverTimeout", errutil.WithPublicMessage("error trying to connect to image-renderer service")) var ErrServerTimeout = errutil.NewBase(errutil.StatusUnknown, "rendering.serverTimeout", errutil.WithPublicMessage("error trying to connect to image-renderer service"))
var ErrTooManyRequests = errutil.NewBase(errutil.StatusTooManyRequests, "rendering.tooManyRequests", errutil.WithPublicMessage("trying to send too many requests to image-renderer service"))
type RenderType string type RenderType string

Loading…
Cancel
Save