1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768 |
- package common
- import (
- "net/url"
- "strings"
- "github.com/imgproxy/imgproxy/v3/config"
- )
- func EscapeURL(u string) string {
- // Non-http(s) URLs may contain percent symbol outside of the percent-encoded sequences.
- // Parsing such URLs will fail with an error.
- // To prevent this, we replace all percent symbols with %25.
- //
- // Also, such URLs may contain a hash symbol (a fragment identifier) or a question mark
- // (a query string).
- // We replace them with %23 and %3F to make `url.Parse` treat them as a part of the path.
- // Since we already replaced all percent symbols, we won't mix up %23/%3F that were in the
- // original URL and %23/%3F that appeared after the replacement.
- //
- // We will revert these replacements in `GetBucketAndKey`.
- if !strings.HasPrefix(u, "http://") && !strings.HasPrefix(u, "https://") {
- u = strings.ReplaceAll(u, "%", "%25")
- u = strings.ReplaceAll(u, "?", "%3F")
- u = strings.ReplaceAll(u, "#", "%23")
- }
- return u
- }
- func GetBucketAndKey(u *url.URL) (bucket, key, query string) {
- bucket = u.Host
- // We can't use u.Path here because `url.Parse` unescapes the original URL's path.
- // So we have to use `u.RawPath` if it's available.
- // If it is not available, then `u.EscapedPath()` is the same as the original URL's path
- // before `url.Parse`.
- // See: https://cs.opensource.google/go/go/+/refs/tags/go1.22.4:src/net/url/url.go;l=680
- if len(u.RawPath) > 0 {
- key = u.RawPath
- } else {
- key = u.EscapedPath()
- }
- key = strings.TrimLeft(key, "/")
- // We percent-encoded `%`, `#`, and `?` in `EscapeURL` to prevent parsing errors.
- // Now we need to revert these replacements.
- //
- // It's important to revert %25 last because %23/%3F may appear in the original URL and
- // we don't want to mix them up.
- bucket = strings.ReplaceAll(bucket, "%23", "#")
- bucket = strings.ReplaceAll(bucket, "%3F", "?")
- bucket = strings.ReplaceAll(bucket, "%25", "%")
- key = strings.ReplaceAll(key, "%23", "#")
- key = strings.ReplaceAll(key, "%3F", "?")
- key = strings.ReplaceAll(key, "%25", "%")
- // Cut the query string if it's present.
- // Since we replaced `?` with `%3F` in `EscapeURL`, `url.Parse` will treat query
- // string as a part of the path.
- // Also, query string separator may be different from `?`, so we can't rely on `url.URL.RawQuery`.
- if len(config.SourceURLQuerySeparator) > 0 {
- key, query, _ = strings.Cut(key, config.SourceURLQuerySeparator)
- }
- return
- }
|