internal/namespaceinpath/url.go (53 lines of code) (raw):
package namespaceinpath
import (
"errors"
"net"
"net/url"
"strings"
)
var (
errURLNotPagesDomain = errors.New("URL does not match pages domain")
errFirstSegmentEmpty = errors.New("can't extract namespace from path because first segment is empty")
errCantExtractNamespace = errors.New("can't extract namespace from host")
)
type customURL struct {
*url.URL
pagesDomain string
}
// convertFromNamespaceInPath: Converts a URL with the namespace in the path to a URL with the namespace in the host.
// This function extracts the namespace from the path and appends it to the host, then removes the namespace from the path.
// For example, it converts "example.com/namespace/a-path" to "namespace.example.com/a-path".
func (u *customURL) convertFromNamespaceInPath() error {
if !u.isPagesDomain() {
return errURLNotPagesDomain
}
segments := strings.Split(strings.TrimPrefix(u.Path, "/"), "/")
if len(segments) == 0 || segments[0] == "" {
return errFirstSegmentEmpty
}
namespace := segments[0]
hostWithNamespace := namespace + "." + u.Host
u.Host = hostWithNamespace
u.URL.Path = strings.TrimPrefix(u.Path, "/"+namespace)
return nil
}
// convertToNamespaceInPath: Converts a URL with the namespace in the host to a URL with the namespace in the path.
// This function extracts the namespace from the host and prepends it to the path, then removes the namespace from the host.
// For example, it converts "namespace.example.com/a-path" to "example.com/namespace/a-path".
func (u *customURL) convertToNamespaceInPath() error {
_, port, _ := net.SplitHostPort(u.Host)
pagesDomainWithPort := u.pagesDomain
if port != "" {
pagesDomainWithPort = u.pagesDomain + ":" + port
}
if strings.HasSuffix(u.Host, pagesDomainWithPort) {
namespace := strings.Trim(strings.TrimSuffix(u.Host, pagesDomainWithPort), ".")
if len(namespace) > 0 {
u.Host = pagesDomainWithPort
u.Path = "/" + namespace + "/" + strings.TrimPrefix(u.Path, "/")
return nil
}
}
return errCantExtractNamespace
}
func (u *customURL) isPagesDomain() bool {
hostWithoutPort, _, err := net.SplitHostPort(u.Host)
if err != nil {
hostWithoutPort = u.Host
}
return hostWithoutPort == u.pagesDomain
}