Instrumentation: Proxy status code correction and various improvements (#47473)
For a proxied request, e.g. Grafana's datasource or plugin proxy: If the request is cancelled, e.g. from the browser, the HTTP status code is now 499 Client closed request instead of 502 Bad gateway. If the request times out, e.g. takes longer time than allowed, the HTTP status code is now 504 Gateway timeout instead of 502 Bad gateway. This also means that request metrics and logs will get their status codes adjusted according to above. Fixes #46337 Fixes #46338
This commit is contained in:
committed by
GitHub
parent
c0104db72d
commit
4bc582570e
@@ -1,7 +1,9 @@
|
||||
package pluginproxy
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
@@ -22,7 +24,18 @@ type templateData struct {
|
||||
|
||||
// NewApiPluginProxy create a plugin proxy
|
||||
func NewApiPluginProxy(ctx *models.ReqContext, proxyPath string, route *plugins.Route,
|
||||
appID string, cfg *setting.Cfg, pluginSettingsService pluginsettings.Service, secretsService secrets.Service) *httputil.ReverseProxy {
|
||||
appID string, cfg *setting.Cfg, pluginSettingsService pluginsettings.Service,
|
||||
secretsService secrets.Service) *httputil.ReverseProxy {
|
||||
appProxyLogger := logger.New(
|
||||
"userId", ctx.UserId,
|
||||
"orgId", ctx.OrgId,
|
||||
"uname", ctx.Login,
|
||||
"app", appID,
|
||||
"path", ctx.Req.URL.Path,
|
||||
"remote_addr", ctx.RemoteAddr(),
|
||||
"referer", ctx.Req.Referer(),
|
||||
)
|
||||
|
||||
director := func(req *http.Request) {
|
||||
query := pluginsettings.GetByPluginIDArgs{OrgID: ctx.OrgId, PluginID: appID}
|
||||
ps, err := pluginSettingsService.GetPluginSettingByPluginID(ctx.Req.Context(), &query)
|
||||
@@ -61,8 +74,6 @@ func NewApiPluginProxy(ctx *models.ReqContext, proxyPath string, route *plugins.
|
||||
req.Header.Del("Cookie")
|
||||
req.Header.Del("Set-Cookie")
|
||||
|
||||
proxyutil.PrepareProxyRequest(req)
|
||||
|
||||
// Create a HTTP header with the context in it.
|
||||
ctxJSON, err := json.Marshal(ctx.SignedInUser)
|
||||
if err != nil {
|
||||
@@ -80,15 +91,35 @@ func NewApiPluginProxy(ctx *models.ReqContext, proxyPath string, route *plugins.
|
||||
}
|
||||
|
||||
if err := setBodyContent(req, route, data); err != nil {
|
||||
logger.Error("Failed to set plugin route body content", "error", err)
|
||||
appProxyLogger.Error("Failed to set plugin route body content", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
return &httputil.ReverseProxy{Director: director, ModifyResponse: modifyResponse}
|
||||
logAppPluginProxyRequest(appID, cfg, ctx)
|
||||
|
||||
return proxyutil.NewReverseProxy(appProxyLogger, director)
|
||||
}
|
||||
|
||||
func modifyResponse(resp *http.Response) error {
|
||||
proxyutil.SetProxyResponseHeaders(resp.Header)
|
||||
func logAppPluginProxyRequest(appID string, cfg *setting.Cfg, c *models.ReqContext) {
|
||||
if !cfg.DataProxyLogging {
|
||||
return
|
||||
}
|
||||
|
||||
return nil
|
||||
var body string
|
||||
if c.Req.Body != nil {
|
||||
buffer, err := ioutil.ReadAll(c.Req.Body)
|
||||
if err == nil {
|
||||
c.Req.Body = ioutil.NopCloser(bytes.NewBuffer(buffer))
|
||||
body = string(buffer)
|
||||
}
|
||||
}
|
||||
|
||||
logger.Info("Proxying incoming request",
|
||||
"userid", c.UserId,
|
||||
"orgid", c.OrgId,
|
||||
"username", c.Login,
|
||||
"app", appID,
|
||||
"uri", c.Req.RequestURI,
|
||||
"method", c.Req.Method,
|
||||
"body", body)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user