pluginproxy.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package pluginproxy
  2. import (
  3. "encoding/json"
  4. "github.com/grafana/grafana/pkg/setting"
  5. "net"
  6. "net/http"
  7. "net/http/httputil"
  8. "net/url"
  9. "github.com/grafana/grafana/pkg/bus"
  10. "github.com/grafana/grafana/pkg/log"
  11. m "github.com/grafana/grafana/pkg/models"
  12. "github.com/grafana/grafana/pkg/plugins"
  13. "github.com/grafana/grafana/pkg/util"
  14. )
  15. type templateData struct {
  16. JsonData map[string]interface{}
  17. SecureJsonData map[string]string
  18. }
  19. func getHeaders(route *plugins.AppPluginRoute, orgId int64, appID string) (http.Header, error) {
  20. result := http.Header{}
  21. query := m.GetPluginSettingByIdQuery{OrgId: orgId, PluginId: appID}
  22. if err := bus.Dispatch(&query); err != nil {
  23. return nil, err
  24. }
  25. data := templateData{
  26. JsonData: query.Result.JsonData,
  27. SecureJsonData: query.Result.SecureJsonData.Decrypt(),
  28. }
  29. err := addHeaders(&result, route, data)
  30. return result, err
  31. }
  32. func NewApiPluginProxy(ctx *m.ReqContext, proxyPath string, route *plugins.AppPluginRoute, appID string, cfg *setting.Cfg) *httputil.ReverseProxy {
  33. targetURL, _ := url.Parse(route.Url)
  34. director := func(req *http.Request) {
  35. req.URL.Scheme = targetURL.Scheme
  36. req.URL.Host = targetURL.Host
  37. req.Host = targetURL.Host
  38. req.URL.Path = util.JoinURLFragments(targetURL.Path, proxyPath)
  39. // clear cookie headers
  40. req.Header.Del("Cookie")
  41. req.Header.Del("Set-Cookie")
  42. // clear X-Forwarded Host/Port/Proto headers
  43. req.Header.Del("X-Forwarded-Host")
  44. req.Header.Del("X-Forwarded-Port")
  45. req.Header.Del("X-Forwarded-Proto")
  46. // set X-Forwarded-For header
  47. if req.RemoteAddr != "" {
  48. remoteAddr, _, err := net.SplitHostPort(req.RemoteAddr)
  49. if err != nil {
  50. remoteAddr = req.RemoteAddr
  51. }
  52. if req.Header.Get("X-Forwarded-For") != "" {
  53. req.Header.Set("X-Forwarded-For", req.Header.Get("X-Forwarded-For")+", "+remoteAddr)
  54. } else {
  55. req.Header.Set("X-Forwarded-For", remoteAddr)
  56. }
  57. }
  58. // Create a HTTP header with the context in it.
  59. ctxJson, err := json.Marshal(ctx.SignedInUser)
  60. if err != nil {
  61. ctx.JsonApiErr(500, "failed to marshal context to json.", err)
  62. return
  63. }
  64. req.Header.Add("X-Grafana-Context", string(ctxJson))
  65. if cfg.SendUserHeader && !ctx.SignedInUser.IsAnonymous {
  66. req.Header.Add("X-Grafana-User", ctx.SignedInUser.Login)
  67. }
  68. if len(route.Headers) > 0 {
  69. headers, err := getHeaders(route, ctx.OrgId, appID)
  70. if err != nil {
  71. ctx.JsonApiErr(500, "Could not generate plugin route header", err)
  72. return
  73. }
  74. for key, value := range headers {
  75. log.Trace("setting key %v value <redacted>", key)
  76. req.Header.Set(key, value[0])
  77. }
  78. }
  79. // reqBytes, _ := httputil.DumpRequestOut(req, true);
  80. // log.Trace("Proxying plugin request: %s", string(reqBytes))
  81. }
  82. return &httputil.ReverseProxy{Director: director}
  83. }