mirror of
https://github.com/miniflux/v2.git
synced 2025-06-27 16:36:00 +00:00
Calls to urllib.AbsoluteURL take a bit less than 10% of the time spent in parser.ParseFeed, completely parsing an url only to check if it's absolute, and if not, to make it so. Checking if it starts with `https://` or `http://` is usually enough to find if an url is absolute, and if is doesn't, it's always possible to fall back to urllib.AbsoluteURL. This also comes with the advantage of reducing heap allocations, as most of the time spent in urllib.AbsoluteURL is heap-related (de)allocations.
107 lines
2.3 KiB
Go
107 lines
2.3 KiB
Go
// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package urllib // import "miniflux.app/v2/internal/urllib"
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"strings"
|
|
)
|
|
|
|
// IsAbsoluteURL returns true if the link is absolute.
|
|
func IsAbsoluteURL(link string) bool {
|
|
u, err := url.Parse(link)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
return u.IsAbs()
|
|
}
|
|
|
|
// AbsoluteURL converts the input URL as absolute URL if necessary.
|
|
func AbsoluteURL(baseURL, input string) (string, error) {
|
|
if strings.HasPrefix(input, "//") {
|
|
return "https:" + input, nil
|
|
}
|
|
if strings.HasPrefix(input, "https://") || strings.HasPrefix(input, "http://") {
|
|
return input, nil
|
|
}
|
|
|
|
u, err := url.Parse(input)
|
|
if err != nil {
|
|
return "", fmt.Errorf("unable to parse input URL: %v", err)
|
|
}
|
|
|
|
if u.IsAbs() {
|
|
return u.String(), nil
|
|
}
|
|
|
|
base, err := url.Parse(baseURL)
|
|
if err != nil {
|
|
return "", fmt.Errorf("unable to parse base URL: %v", err)
|
|
}
|
|
|
|
return base.ResolveReference(u).String(), nil
|
|
}
|
|
|
|
// RootURL returns absolute URL without the path.
|
|
func RootURL(websiteURL string) string {
|
|
if strings.HasPrefix(websiteURL, "//") {
|
|
websiteURL = "https://" + websiteURL[2:]
|
|
}
|
|
|
|
absoluteURL, err := AbsoluteURL(websiteURL, "")
|
|
if err != nil {
|
|
return websiteURL
|
|
}
|
|
|
|
u, err := url.Parse(absoluteURL)
|
|
if err != nil {
|
|
return absoluteURL
|
|
}
|
|
|
|
return u.Scheme + "://" + u.Host + "/"
|
|
}
|
|
|
|
// IsHTTPS returns true if the URL is using HTTPS.
|
|
func IsHTTPS(websiteURL string) bool {
|
|
parsedURL, err := url.Parse(websiteURL)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
return strings.EqualFold(parsedURL.Scheme, "https")
|
|
}
|
|
|
|
// Domain returns only the domain part of the given URL.
|
|
func Domain(websiteURL string) string {
|
|
parsedURL, err := url.Parse(websiteURL)
|
|
if err != nil {
|
|
return websiteURL
|
|
}
|
|
|
|
return parsedURL.Host
|
|
}
|
|
|
|
// JoinBaseURLAndPath returns a URL string with the provided path elements joined together.
|
|
func JoinBaseURLAndPath(baseURL, path string) (string, error) {
|
|
if baseURL == "" {
|
|
return "", fmt.Errorf("empty base URL")
|
|
}
|
|
|
|
if path == "" {
|
|
return "", fmt.Errorf("empty path")
|
|
}
|
|
|
|
_, err := url.Parse(baseURL)
|
|
if err != nil {
|
|
return "", fmt.Errorf("invalid base URL: %w", err)
|
|
}
|
|
|
|
finalURL, err := url.JoinPath(baseURL, path)
|
|
if err != nil {
|
|
return "", fmt.Errorf("unable to join base URL %s and path %s: %w", baseURL, path, err)
|
|
}
|
|
|
|
return finalURL, nil
|
|
}
|