mirror of https://github.com/grafana/grafana.git
				
				
				
			
		
			
				
	
	
		
			88 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			88 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
| package pluginproxy
 | |
| 
 | |
| import (
 | |
| 	"encoding/json"
 | |
| 	"net/http"
 | |
| 	"net/http/httputil"
 | |
| 	"net/url"
 | |
| 
 | |
| 	"github.com/grafana/grafana/pkg/models"
 | |
| 	"github.com/grafana/grafana/pkg/plugins"
 | |
| 	"github.com/grafana/grafana/pkg/services/secrets"
 | |
| 	"github.com/grafana/grafana/pkg/services/sqlstore"
 | |
| 	"github.com/grafana/grafana/pkg/setting"
 | |
| 	"github.com/grafana/grafana/pkg/util"
 | |
| 	"github.com/grafana/grafana/pkg/util/proxyutil"
 | |
| )
 | |
| 
 | |
| type templateData struct {
 | |
| 	JsonData       map[string]interface{}
 | |
| 	SecureJsonData map[string]string
 | |
| }
 | |
| 
 | |
| // NewApiPluginProxy create a plugin proxy
 | |
| func NewApiPluginProxy(ctx *models.ReqContext, proxyPath string, route *plugins.Route,
 | |
| 	appID string, cfg *setting.Cfg, store sqlstore.Store, secretsService secrets.Service) *httputil.ReverseProxy {
 | |
| 	director := func(req *http.Request) {
 | |
| 		query := models.GetPluginSettingByIdQuery{OrgId: ctx.OrgId, PluginId: appID}
 | |
| 		if err := store.GetPluginSettingById(ctx.Req.Context(), &query); err != nil {
 | |
| 			ctx.JsonApiErr(500, "Failed to fetch plugin settings", err)
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		secureJsonData, err := secretsService.DecryptJsonData(ctx.Req.Context(), query.Result.SecureJsonData)
 | |
| 		if err != nil {
 | |
| 			ctx.JsonApiErr(500, "Failed to decrypt plugin settings", err)
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		data := templateData{
 | |
| 			JsonData:       query.Result.JsonData,
 | |
| 			SecureJsonData: secureJsonData,
 | |
| 		}
 | |
| 
 | |
| 		interpolatedURL, err := interpolateString(route.URL, data)
 | |
| 		if err != nil {
 | |
| 			ctx.JsonApiErr(500, "Could not interpolate plugin route url", err)
 | |
| 			return
 | |
| 		}
 | |
| 		targetURL, err := url.Parse(interpolatedURL)
 | |
| 		if err != nil {
 | |
| 			ctx.JsonApiErr(500, "Could not parse url", err)
 | |
| 			return
 | |
| 		}
 | |
| 		req.URL.Scheme = targetURL.Scheme
 | |
| 		req.URL.Host = targetURL.Host
 | |
| 		req.Host = targetURL.Host
 | |
| 		req.URL.Path = util.JoinURLFragments(targetURL.Path, proxyPath)
 | |
| 
 | |
| 		// clear cookie headers
 | |
| 		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 {
 | |
| 			ctx.JsonApiErr(500, "failed to marshal context to json.", err)
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		req.Header.Set("X-Grafana-Context", string(ctxJSON))
 | |
| 
 | |
| 		applyUserHeader(cfg.SendUserHeader, req, ctx.SignedInUser)
 | |
| 
 | |
| 		if err := addHeaders(&req.Header, route, data); err != nil {
 | |
| 			ctx.JsonApiErr(500, "Failed to render plugin headers", err)
 | |
| 			return
 | |
| 		}
 | |
| 
 | |
| 		if err := setBodyContent(req, route, data); err != nil {
 | |
| 			logger.Error("Failed to set plugin route body content", "error", err)
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return &httputil.ReverseProxy{Director: director}
 | |
| }
 |