| 
									
										
										
										
											2019-05-08 00:55:39 +08:00
										 |  |  | package pluginproxy | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2021-03-31 22:38:35 +08:00
										 |  |  | 	"io/ioutil" | 
					
						
							| 
									
										
										
										
											2020-06-12 03:15:17 +08:00
										 |  |  | 	"net/http" | 
					
						
							| 
									
										
										
										
											2021-03-31 22:38:35 +08:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2019-05-08 00:55:39 +08:00
										 |  |  | 	"text/template" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-04 19:57:20 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/models" | 
					
						
							| 
									
										
										
										
											2019-05-08 00:55:39 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/plugins" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-17 17:56:42 +08:00
										 |  |  | // interpolateString accepts template data and return a string with substitutions
 | 
					
						
							|  |  |  | func interpolateString(text string, data templateData) (string, error) { | 
					
						
							| 
									
										
										
										
											2021-05-18 21:36:58 +08:00
										 |  |  | 	extraFuncs := map[string]interface{}{ | 
					
						
							|  |  |  | 		"orEmpty": func(v interface{}) interface{} { | 
					
						
							|  |  |  | 			if v == nil { | 
					
						
							|  |  |  | 				return "" | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return v | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	t, err := template.New("content").Funcs(extraFuncs).Parse(text) | 
					
						
							| 
									
										
										
										
											2019-05-08 00:55:39 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return "", fmt.Errorf("could not parse template %s", text) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var contentBuf bytes.Buffer | 
					
						
							|  |  |  | 	err = t.Execute(&contentBuf, data) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return "", fmt.Errorf("failed to execute template %s", text) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return contentBuf.String(), nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-17 17:56:42 +08:00
										 |  |  | // addHeaders interpolates route headers and injects them into the request headers
 | 
					
						
							| 
									
										
										
										
											2021-11-01 17:53:33 +08:00
										 |  |  | func addHeaders(reqHeaders *http.Header, route *plugins.Route, data templateData) error { | 
					
						
							| 
									
										
										
										
											2020-11-17 17:56:42 +08:00
										 |  |  | 	for _, header := range route.Headers { | 
					
						
							|  |  |  | 		interpolated, err := interpolateString(header.Content, data) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							| 
									
										
										
										
											2019-05-08 00:55:39 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-11-17 17:56:42 +08:00
										 |  |  | 		reqHeaders.Set(header.Name, interpolated) | 
					
						
							| 
									
										
										
										
											2019-05-08 00:55:39 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-17 17:56:42 +08:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // addQueryString interpolates route params and injects them into the request object
 | 
					
						
							| 
									
										
										
										
											2021-11-01 17:53:33 +08:00
										 |  |  | func addQueryString(req *http.Request, route *plugins.Route, data templateData) error { | 
					
						
							| 
									
										
										
										
											2020-11-17 17:56:42 +08:00
										 |  |  | 	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 | 
					
						
							| 
									
										
										
										
											2019-05-08 00:55:39 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2020-06-12 03:15:17 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-01 17:53:33 +08:00
										 |  |  | func setBodyContent(req *http.Request, route *plugins.Route, data templateData) error { | 
					
						
							| 
									
										
										
										
											2021-03-31 22:38:35 +08:00
										 |  |  | 	if route.Body != nil { | 
					
						
							|  |  |  | 		interpolatedBody, err := interpolateString(string(route.Body), data) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		req.Body = ioutil.NopCloser(strings.NewReader(interpolatedBody)) | 
					
						
							|  |  |  | 		req.ContentLength = int64(len(interpolatedBody)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-06-12 03:15:17 +08:00
										 |  |  | // Set the X-Grafana-User header if needed (and remove if not)
 | 
					
						
							|  |  |  | func applyUserHeader(sendUserHeader bool, req *http.Request, user *models.SignedInUser) { | 
					
						
							|  |  |  | 	req.Header.Del("X-Grafana-User") | 
					
						
							|  |  |  | 	if sendUserHeader && !user.IsAnonymous { | 
					
						
							|  |  |  | 		req.Header.Set("X-Grafana-User", user.Login) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |