Fix panic when using complex dynamic URLs in app plugin routes (#27977)

* remove unused function to interpolate URLs

* share function to add headers between ds/plugin proxies

* stop performing unnecessary plugin setting lookup

* fix bug causing runtime errors when using complex templated URLs

* lower case util functions not used outside of pluginproxy package

* change test URL to a (valid) dummy URL to make intent clearer

Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com>
This commit is contained in:
Victor Cinaglia
2020-11-17 04:56:42 -05:00
committed by GitHub
parent 0f3bebb38d
commit 967e9b39e8
8 changed files with 104 additions and 152 deletions

View File

@ -4,15 +4,14 @@ import (
"bytes"
"fmt"
"net/http"
"net/url"
"text/template"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
)
// InterpolateString accepts template data and return a string with substitutions
func InterpolateString(text string, data templateData) (string, error) {
// interpolateString accepts template data and return a string with substitutions
func interpolateString(text string, data templateData) (string, error) {
t, err := template.New("content").Parse(text)
if err != nil {
return "", fmt.Errorf("could not parse template %s", text)
@ -27,26 +26,38 @@ func InterpolateString(text string, data templateData) (string, error) {
return contentBuf.String(), nil
}
// InterpolateURL accepts template data and return a string with substitutions
func InterpolateURL(anURL *url.URL, route *plugins.AppPluginRoute, orgID int64, appID string) (*url.URL, error) {
query := models.GetPluginSettingByIdQuery{OrgId: orgID, PluginId: appID}
result, err := url.Parse(anURL.String())
if query.Result != nil {
if len(query.Result.JsonData) > 0 {
data := templateData{
JsonData: query.Result.JsonData,
}
interpolatedResult, err := InterpolateString(anURL.String(), data)
if err == nil {
result, err = url.Parse(interpolatedResult)
if err != nil {
return nil, fmt.Errorf("error parsing plugin route URL: %w", err)
}
}
// addHeaders interpolates route headers and injects them into the request headers
func addHeaders(reqHeaders *http.Header, route *plugins.AppPluginRoute, data templateData) error {
for _, header := range route.Headers {
interpolated, err := interpolateString(header.Content, data)
if err != nil {
return err
}
reqHeaders.Set(header.Name, interpolated)
}
return result, err
return nil
}
// addQueryString interpolates route params and injects them into the request object
func addQueryString(req *http.Request, route *plugins.AppPluginRoute, data templateData) error {
q := req.URL.Query()
for _, param := range route.URLParams {
interpolatedName, err := interpolateString(param.Name, data)
if err != nil {
return err
}
interpolatedContent, err := interpolateString(param.Content, data)
if err != nil {
return err
}
q.Add(interpolatedName, interpolatedContent)
}
req.URL.RawQuery = q.Encode()
return nil
}
// Set the X-Grafana-User header if needed (and remove if not)