Files
phishingclub/backend/vo/http.go
2025-08-21 16:14:09 +02:00

183 lines
4.0 KiB
Go

package vo
import (
"encoding/json"
"fmt"
"net/url"
"strings"
"github.com/phishingclub/phishingclub/validate"
)
var validHTTPMethods = []string{"GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS", "HEAD", "TRACE", "CONNECT"}
// HTTPMethod is an http method
type HTTPMethod struct {
inner string
}
// NewHTTPMethod creates a new http method
func NewHTTPMethod(s string) (*HTTPMethod, error) {
s = strings.TrimSpace(s)
s = strings.ToUpper(s)
if err := validate.ErrorIfNotContains(validHTTPMethods, s); err != nil {
return nil, validate.WrapErrorWithField(
fmt.Errorf("invalid http method: %s", s),
"HTTPMethod",
)
}
return &HTTPMethod{
inner: s,
}, nil
}
// NewHTTPMethodMust creates a new http method, panicking if the input is invalid
func NewHTTPMethodMust(s string) *HTTPMethod {
ss, err := NewHTTPMethod(s)
if err != nil {
panic(err)
}
return ss
}
// MarshalJSON implements the json.Marshaler interface
func (s HTTPMethod) MarshalJSON() ([]byte, error) {
return json.Marshal(s.inner)
}
// UnmarshalJSON unmarshals the json into a string
func (s *HTTPMethod) UnmarshalJSON(data []byte) error {
var str string
if err := json.Unmarshal(data, &str); err != nil {
return err
}
ss, err := NewHTTPMethod(str)
if err != nil {
return unwrapError(err)
}
s.inner = ss.inner
return nil
}
// String returns the string representation of the http method
func (s HTTPMethod) String() string {
return s.inner
}
// HTTPHeader is an http header
type HTTPHeader struct {
key string
value string
}
// NewHTTPHeader creates a new http header
func NewHTTPHeader(key, val string) (*HTTPHeader, error) {
key = strings.TrimSpace(key)
val = strings.TrimSpace(val)
if validate.ErrorIfStringEqual(key, "") != nil {
return nil, validate.WrapErrorWithField(
fmt.Errorf("invalid http header key: %s", key),
"HTTPHeader",
)
}
if validate.ErrorIfStringEqual(val, "") != nil {
return nil, validate.WrapErrorWithField(
fmt.Errorf("invalid http header value: %s", val),
"HTTPHeader",
)
}
return &HTTPHeader{
key: key,
value: val,
}, nil
}
// Key returns the key of the header
func (h *HTTPHeader) Key() string {
return h.key
}
// Value returns the value of the header
func (h *HTTPHeader) Value() string {
return h.value
}
// MarshalJSON implements the json.Marshaler interface
func (s HTTPHeader) MarshalJSON() ([]byte, error) {
return json.Marshal(s)
}
// UnmarshalJSON unmarshals the json into a string
func (s *HTTPHeader) UnmarshalJSON(data []byte) error {
var header *HTTPHeader
if err := json.Unmarshal(data, &header); err != nil {
return err
}
// create instance to validate data
ss, err := NewHTTPHeader(header.key, header.value)
if err != nil {
return unwrapError(err)
}
s.key = ss.key
s.value = ss.value
return nil
}
// String returns the string representation of the header
func (h HTTPHeader) String() string {
return fmt.Sprintf("%s: %s", h.key, h.value)
}
// URLPath is the path in a URL (e.g. /api/v1/users)
type URLPath struct {
inner string
}
// NewURLPath creates a new URL path
func NewURLPath(s string) (*URLPath, error) {
s = strings.TrimSpace(s)
p, err := url.Parse(s)
if err != nil {
return nil, validate.WrapErrorWithField(
fmt.Errorf("invalid url path: %s", s),
"URLPath",
)
}
return &URLPath{
inner: p.Path,
}, nil
}
// NewURLPathMust creates a new URL path, panicking if the input is invalid
func NewURLPathMust(s string) *URLPath {
ss, err := NewURLPath(s)
if err != nil {
panic(err)
}
return ss
}
// MarshalJSON implements the json.Marshaler interface
func (s URLPath) MarshalJSON() ([]byte, error) {
return json.Marshal(s.inner)
}
// UnmarshalJSON unmarshals the json into a string
func (s *URLPath) UnmarshalJSON(data []byte) error {
var str string
if err := json.Unmarshal(data, &str); err != nil {
return err
}
ss, err := NewURLPath(str)
if err != nil {
return unwrapError(err)
}
s.inner = ss.inner
return nil
}
// String returns the string representation of the URL path
func (s URLPath) String() string {
return s.inner
}