pluginproxy.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. package pluginproxy
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "net/http"
  8. "net/http/httputil"
  9. "net/url"
  10. "text/template"
  11. "github.com/grafana/grafana/pkg/bus"
  12. "github.com/grafana/grafana/pkg/log"
  13. "github.com/grafana/grafana/pkg/middleware"
  14. m "github.com/grafana/grafana/pkg/models"
  15. "github.com/grafana/grafana/pkg/plugins"
  16. "github.com/grafana/grafana/pkg/util"
  17. )
  18. type templateData struct {
  19. JsonData map[string]interface{}
  20. SecureJsonData map[string]string
  21. }
  22. func getHeaders(route *plugins.AppPluginRoute, orgId int64, appId string) (http.Header, error) {
  23. result := http.Header{}
  24. query := m.GetAppSettingByAppIdQuery{OrgId: orgId, AppId: appId}
  25. if err := bus.Dispatch(&query); err != nil {
  26. return nil, err
  27. }
  28. data := templateData{
  29. JsonData: query.Result.JsonData,
  30. SecureJsonData: query.Result.SecureJsonData.Decrypt(),
  31. }
  32. for _, header := range route.Headers {
  33. var contentBuf bytes.Buffer
  34. t, err := template.New("content").Parse(header.Content)
  35. if err != nil {
  36. return nil, errors.New(fmt.Sprintf("could not parse header content template for header %s.", header.Name))
  37. }
  38. err = t.Execute(&contentBuf, data)
  39. if err != nil {
  40. return nil, errors.New(fmt.Sprintf("failed to execute header content template for header %s.", header.Name))
  41. }
  42. log.Trace("Adding header to proxy request. %s: %s", header.Name, contentBuf.String())
  43. result.Add(header.Name, contentBuf.String())
  44. }
  45. return result, nil
  46. }
  47. func NewApiPluginProxy(ctx *middleware.Context, proxyPath string, route *plugins.AppPluginRoute, appId string) *httputil.ReverseProxy {
  48. targetUrl, _ := url.Parse(route.Url)
  49. director := func(req *http.Request) {
  50. req.URL.Scheme = targetUrl.Scheme
  51. req.URL.Host = targetUrl.Host
  52. req.Host = targetUrl.Host
  53. req.URL.Path = util.JoinUrlFragments(targetUrl.Path, proxyPath)
  54. // clear cookie headers
  55. req.Header.Del("Cookie")
  56. req.Header.Del("Set-Cookie")
  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.Info("setting key %v value %v", key, value[0])
  72. req.Header.Set(key, value[0])
  73. }
  74. }
  75. }
  76. return &httputil.ReverseProxy{Director: director}
  77. }