1
0

path.go 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. package handlers
  2. import (
  3. "fmt"
  4. "net/http"
  5. "regexp"
  6. "strings"
  7. "github.com/imgproxy/imgproxy/v3/ierrors"
  8. )
  9. // fixPathRe is used in path re-denormalization
  10. var fixPathRe = regexp.MustCompile(`/plain/(\S+)\:/([^/])`)
  11. // SplitPathSignature splits signature and path components from the request URI
  12. func SplitPathSignature(r *http.Request) (string, string, error) {
  13. uri := r.RequestURI
  14. // cut query params
  15. uri, _, _ = strings.Cut(uri, "?")
  16. // Cut path prefix.
  17. // r.Pattern is set by the router and contains both global and route-specific prefixes combined.
  18. if len(r.Pattern) > 0 {
  19. uri = strings.TrimPrefix(uri, r.Pattern)
  20. }
  21. // cut leading slash
  22. uri = strings.TrimPrefix(uri, "/")
  23. signature, path, _ := strings.Cut(uri, "/")
  24. if len(signature) == 0 || len(path) == 0 {
  25. return "", "", ierrors.Wrap(
  26. NewInvalidURLErrorf(http.StatusNotFound, "Invalid path: %s", path), 0,
  27. ierrors.WithCategory(CategoryPathParsing),
  28. )
  29. }
  30. // restore broken slashes in the path
  31. path = redenormalizePath(path)
  32. return path, signature, nil
  33. }
  34. // redenormalizePath undoes path normalization done by some browsers and revers proxies
  35. func redenormalizePath(path string) string {
  36. for _, match := range fixPathRe.FindAllStringSubmatch(path, -1) {
  37. repl := fmt.Sprintf("/plain/%s://", match[1])
  38. if match[1] == "local" {
  39. repl += "/"
  40. }
  41. repl += match[2]
  42. path = strings.Replace(path, match[0], repl, 1)
  43. }
  44. return path
  45. }