70 lines
2.1 KiB
Go
70 lines
2.1 KiB
Go
package utils
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
)
|
|
|
|
const restURLPatternHeaderKey = "Owncast-Resturl-Pattern"
|
|
|
|
// takes the segment pattern of an Url string and returns the segment before the first dynamic REST parameter.
|
|
func getPatternForRestEndpoint(pattern string) string {
|
|
firstIndex := strings.Index(pattern, "/{")
|
|
if firstIndex == -1 {
|
|
return pattern
|
|
}
|
|
|
|
return strings.TrimRight(pattern[:firstIndex], "/") + "/"
|
|
}
|
|
|
|
func zip2D(iterable1 *[]string, iterable2 *[]string) map[string]string {
|
|
dict := make(map[string]string)
|
|
for index, key := range *iterable1 {
|
|
dict[key] = (*iterable2)[index]
|
|
}
|
|
return dict
|
|
}
|
|
|
|
func mapPatternWithRequestURL(pattern string, requestURL string) (map[string]string, error) {
|
|
patternSplit := strings.Split(pattern, "/")
|
|
requestURLSplit := strings.Split(requestURL, "/")
|
|
|
|
if len(patternSplit) == len(requestURLSplit) {
|
|
return zip2D(&patternSplit, &requestURLSplit), nil
|
|
}
|
|
return nil, errors.New("the length of pattern and request Url does not match")
|
|
}
|
|
|
|
func readParameter(pattern string, requestURL string, paramName string) (string, error) {
|
|
all, err := mapPatternWithRequestURL(pattern, requestURL)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
if value, exists := all[fmt.Sprintf("{%s}", paramName)]; exists {
|
|
return value, nil
|
|
}
|
|
return "", fmt.Errorf("parameter with name %s not found", paramName)
|
|
}
|
|
|
|
// ReadRestURLParameter will return the parameter from the request of the requested name.
|
|
func ReadRestURLParameter(r *http.Request, parameterName string) (string, error) {
|
|
pattern, found := r.Header[restURLPatternHeaderKey]
|
|
if !found {
|
|
return "", fmt.Errorf("this HandlerFunc is not marked as REST-Endpoint. Cannot read Parameter '%s' from Request", parameterName)
|
|
}
|
|
|
|
return readParameter(pattern[0], r.URL.Path, parameterName)
|
|
}
|
|
|
|
// RestEndpoint wraps a handler to use the rest endpoint helper.
|
|
func RestEndpoint(pattern string, handler http.HandlerFunc) (string, http.HandlerFunc) {
|
|
baseURL := getPatternForRestEndpoint(pattern)
|
|
return baseURL, func(w http.ResponseWriter, r *http.Request) {
|
|
r.Header[restURLPatternHeaderKey] = []string{pattern}
|
|
handler(w, r)
|
|
}
|
|
}
|