2021-12-29 20:06:54 +00:00
|
|
|
package domain
|
|
|
|
|
|
|
|
import (
|
2022-01-29 17:50:45 +00:00
|
|
|
"fmt"
|
2021-12-30 00:27:52 +00:00
|
|
|
"net/url"
|
2021-12-29 20:06:54 +00:00
|
|
|
"strconv"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
http "github.com/valyala/fasthttp"
|
|
|
|
)
|
|
|
|
|
2022-01-29 17:50:45 +00:00
|
|
|
// URL describe any valid HTTP URL.
|
2021-12-29 20:06:54 +00:00
|
|
|
type URL struct {
|
|
|
|
*http.URI
|
|
|
|
}
|
|
|
|
|
2022-02-15 20:07:39 +00:00
|
|
|
// ParseURL parse string as URL.
|
2022-01-29 14:57:54 +00:00
|
|
|
func ParseURL(src string) (*URL, error) {
|
|
|
|
u := http.AcquireURI()
|
|
|
|
if err := u.Parse(nil, []byte(src)); err != nil {
|
2022-01-29 17:50:45 +00:00
|
|
|
return nil, fmt.Errorf("cannot parse URL: %w", err)
|
2021-12-29 20:06:54 +00:00
|
|
|
}
|
|
|
|
|
2022-01-29 14:57:54 +00:00
|
|
|
return &URL{URI: u}, nil
|
2021-12-29 20:06:54 +00:00
|
|
|
}
|
|
|
|
|
2022-02-15 20:07:39 +00:00
|
|
|
// MustParseURL parse string as URL or panic.
|
|
|
|
func MustParseURL(src string) *URL {
|
|
|
|
uri, err := ParseURL(src)
|
|
|
|
if err != nil {
|
|
|
|
panic("MustParseURL: " + err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
return uri
|
|
|
|
}
|
|
|
|
|
2022-01-29 17:50:45 +00:00
|
|
|
// TestURL returns URL of provided input for tests.
|
2021-12-29 20:06:54 +00:00
|
|
|
func TestURL(tb testing.TB, src string) *URL {
|
|
|
|
tb.Helper()
|
|
|
|
|
|
|
|
u := http.AcquireURI()
|
|
|
|
u.Update(src)
|
|
|
|
|
|
|
|
return &URL{
|
|
|
|
URI: u,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-29 17:50:45 +00:00
|
|
|
// UnmarshalForm implements custom unmarshler for form values.
|
2021-12-29 20:06:54 +00:00
|
|
|
func (u *URL) UnmarshalForm(v []byte) error {
|
2022-01-29 14:57:54 +00:00
|
|
|
url, err := ParseURL(string(v))
|
2021-12-29 20:06:54 +00:00
|
|
|
if err != nil {
|
2022-02-15 20:07:39 +00:00
|
|
|
return fmt.Errorf("URL: UnmarshalForm: %w", err)
|
2021-12-29 20:06:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*u = *url
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-01-29 17:50:45 +00:00
|
|
|
// UnmarshalJSON implements custom unmarshler for JSON.
|
2021-12-29 20:06:54 +00:00
|
|
|
func (u *URL) UnmarshalJSON(v []byte) error {
|
|
|
|
src, err := strconv.Unquote(string(v))
|
|
|
|
if err != nil {
|
2022-02-15 20:07:39 +00:00
|
|
|
return fmt.Errorf("URL: UnmarshalJSON: %w", err)
|
2021-12-29 20:06:54 +00:00
|
|
|
}
|
|
|
|
|
2022-01-29 14:57:54 +00:00
|
|
|
url, err := ParseURL(src)
|
2021-12-29 20:06:54 +00:00
|
|
|
if err != nil {
|
2022-02-15 20:07:39 +00:00
|
|
|
return fmt.Errorf("URL: UnmarshalJSON: %w", err)
|
2021-12-29 20:06:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*u = *url
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2021-12-30 00:27:52 +00:00
|
|
|
|
2022-02-15 20:07:39 +00:00
|
|
|
func (u URL) MarshalJSON() ([]byte, error) {
|
|
|
|
return []byte(strconv.Quote(u.String())), nil
|
|
|
|
}
|
|
|
|
|
2022-01-29 17:50:45 +00:00
|
|
|
// URL returns url.URL representation of URL.
|
2022-01-12 18:04:40 +00:00
|
|
|
func (u URL) URL() *url.URL {
|
2021-12-30 00:27:52 +00:00
|
|
|
if u.URI == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-02-01 17:27:48 +00:00
|
|
|
result, err := url.ParseRequestURI(u.String())
|
2021-12-30 00:27:52 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|