pluginproxy.go 2.6 KB

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