Simplify duplicate code

This commit is contained in:
2025-01-16 13:58:14 +02:00
parent 63adf73ef9
commit b30b7274ec
3 changed files with 15 additions and 38 deletions

View File

@@ -28,7 +28,7 @@ func (u *URL) Scan(value interface{}) error {
if !ok {
return fmt.Errorf("%w: expected string, got %T", ErrDatabaseScan, value)
}
parsedURL, err := ParseURLNoNormalize(b, "")
parsedURL, err := ParseURL(b, "", false)
if err != nil {
err = fmt.Errorf("%w: failed to scan GeminiUrl %s: %v", ErrDatabaseScan, b, err)
return err
@@ -55,38 +55,14 @@ func (u URL) Value() (driver.Value, error) {
return u.Full, nil
}
func ParseURLNoNormalize(input string, descr string) (*URL, error) {
u, err := url.Parse(input)
if err != nil {
return nil, fmt.Errorf("%w: Input %s URL Parse Error: %w", ErrURLParse, input, err)
func ParseURL(input string, descr string, normalize bool) (*URL, error) {
var u *url.URL
var err error
if normalize {
u, err = NormalizeURL(input)
} else {
u, err = url.Parse(input)
}
if u.Scheme != "gemini" {
return nil, fmt.Errorf("%w: URL scheme '%s' is not supported", ErrURLNotGemini, u.Scheme)
}
protocol := u.Scheme
hostname := u.Hostname()
strPort := u.Port()
urlPath := u.Path
if strPort == "" {
strPort = "1965"
}
port, err := strconv.Atoi(strPort)
if err != nil {
return nil, fmt.Errorf("%w: Input %s GeminiError %w", ErrURLParse, input, err)
}
full := fmt.Sprintf("%s://%s:%d%s", protocol, hostname, port, urlPath)
// full field should also contain query params and url fragments
if u.RawQuery != "" {
full += "?" + u.RawQuery
}
if u.Fragment != "" {
full += "#" + u.Fragment
}
return &URL{Protocol: protocol, Hostname: hostname, Port: port, Path: urlPath, Descr: descr, Full: full}, nil
}
func ParseURL(input string, descr string) (*URL, error) {
u, err := NormalizeURL(input)
if err != nil {
return nil, fmt.Errorf("%w: Input %s URL Parse Error: %w", ErrURLParse, input, err)
}
@@ -121,7 +97,7 @@ func ParseURL(input string, descr string) (*URL, error) {
func DeriveAbsoluteURL(currentURL URL, input string) (*URL, error) {
// If target URL is absolute, return just it
if strings.Contains(input, "://") {
return ParseURL(input, "")
return ParseURL(input, "", true)
}
// input is a relative path. Clean it and construct absolute.
var newPath string
@@ -134,7 +110,7 @@ func DeriveAbsoluteURL(currentURL URL, input string) (*URL, error) {
newPath = path.Join(currentURL.Path, "/", path.Clean(input))
}
strURL := fmt.Sprintf("%s://%s:%d%s", currentURL.Protocol, currentURL.Hostname, currentURL.Port, newPath)
return ParseURL(strURL, "")
return ParseURL(strURL, "", true)
}
// NormalizeURL takes a URL string and returns a normalized version.

View File

@@ -1,15 +1,16 @@
package common_test
import (
"gemini-grc/common"
"reflect"
"testing"
"gemini-grc/common"
)
func TestParseURL(t *testing.T) {
t.Parallel()
input := "gemini://caolan.uk/cgi-bin/weather.py/wxfcs/3162"
parsed, err := common.ParseURL(input, "")
parsed, err := common.ParseURL(input, "", true)
value, _ := parsed.Value()
if err != nil || !(value == "gemini://caolan.uk:1965/cgi-bin/weather.py/wxfcs/3162") {
t.Errorf("fail: %s", parsed)

View File

@@ -77,8 +77,8 @@ func ParseGeminiLinkLine(linkLine string, currentURL string) (*common.URL, error
if len(description) > 0 && description[0] == ' ' {
description = description[1:]
}
finalURL, err := common.ParseURL(parsedURL.String(), description)
finalURL, err := common.ParseURL(parsedURL.String(), description, true)
if err != nil {
// If URL parsing fails, return an error
return nil, fmt.Errorf("%w: %w", common.ErrURLParse, err)