You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
69 lines
2.1 KiB
69 lines
2.1 KiB
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) |
|
} |
|
}
|
|
|