Added redirects, make one pathBlock able to contain multiple paths

Signed-off-by: arzumify <jliwin98@danwin1210.de>
This commit is contained in:
Tracker-Friendly 2024-11-03 13:20:09 +00:00
parent ac7230c6b5
commit 694f62f238
2 changed files with 55 additions and 30 deletions

View File

@ -68,8 +68,8 @@ routes: [
{ {
# path defines the path to match. They can contain wildcards. # path defines the path to match. They can contain wildcards.
path: "/static/*", path: "/static/*",
# static defines the static file serving settings for this path. This conflicts with proxy. # static defines the static file serving settings for this path. This conflicts with proxy and redirect.
# If both proxy and static are defined, static will take precedence. # static > proxy > redirect in terms of precedence.
static: { static: {
# root defines the root directory to serve static files from. # root defines the root directory to serve static files from.
root: "./static", root: "./static",
@ -81,8 +81,8 @@ routes: [
{ {
# path defines the path to match. They can contain wildcards. # path defines the path to match. They can contain wildcards.
path: "/proxy/*", path: "/proxy/*",
# proxy defines the proxy settings for this path. This conflicts with static. # proxy defines the proxy settings for this path. This conflicts with static and redirect.
# If both proxy and static are defined, static will take precedence. # static > proxy > redirect in terms of precedence.
proxy: { proxy: {
# url defines the URL to proxy requests to. # url defines the URL to proxy requests to.
url: "http://localhost:8000", url: "http://localhost:8000",
@ -92,6 +92,18 @@ routes: [
# TODO: In a future update, forbidding certain headers from being passed will be supported. # TODO: In a future update, forbidding certain headers from being passed will be supported.
# TODO: In a future update, passing X-Powered-By and Server headers will be supported. # TODO: In a future update, passing X-Powered-By and Server headers will be supported.
# TODO: In a future update, passing Host header will be supported. # TODO: In a future update, passing Host header will be supported.
},
{
# path defines the path to match. They can contain wildcards.
path: "/redirect/*",
# redirect defines the redirect settings for this path. This conflicts with proxy and static.
# static > proxy > redirect in terms of precedence.
redirect: {
# url defines the URL to redirect to.
url: "https://www.google.com",
# permanent defines whether the redirect is permanent (301) or temporary (302).
permanent: true
}
} }
} }
] ]

65
main.go
View File

@ -48,7 +48,7 @@ type Config struct {
HTTPS struct { HTTPS struct {
CertificatePath string `yaml:"certificate" validate:"required"` CertificatePath string `yaml:"certificate" validate:"required"`
KeyPath string `yaml:"key" validate:"required"` KeyPath string `yaml:"key" validate:"required"`
} } `yaml:"https"`
Logging struct { Logging struct {
Enabled bool `yaml:"enabled"` Enabled bool `yaml:"enabled"`
File string `yaml:"file" validate:"required_if=Enabled true"` File string `yaml:"file" validate:"required_if=Enabled true"`
@ -63,15 +63,19 @@ type Config struct {
Subdomain string `yaml:"subdomain" validate:"required"` Subdomain string `yaml:"subdomain" validate:"required"`
Services []string `yaml:"services"` Services []string `yaml:"services"`
Paths []struct { Paths []struct {
Path string `yaml:"path" validate:"required"` Paths []string `yaml:"paths" validate:"required"`
Proxy struct { Proxy struct {
URL string `yaml:"url" validate:"required"` URL string `yaml:"url" validate:"required"`
StripPrefix bool `yaml:"stripPrefix"` StripPrefix bool `yaml:"stripPrefix"`
} `yaml:"proxy" validate:"required_without=Static"` } `yaml:"proxy" validate:"required_without=Static Redirect"`
Static struct { Static struct {
Root string `yaml:"root" validate:"required,isDirectory"` Root string `yaml:"root" validate:"required,isDirectory"`
DirectoryListing bool `yaml:"directoryListing"` DirectoryListing bool `yaml:"directoryListing"`
} `yaml:"static" validate:"required_without=Proxy"` } `yaml:"static" validate:"required_without_all=Proxy Redirect"`
Redirect struct {
URL string `yaml:"url" validate:"required"`
Permanent bool `yaml:"permanent"`
} `yaml:"redirect" validate:"required_without_all=Proxy Static"`
} `yaml:"paths"` } `yaml:"paths"`
HTTPS struct { HTTPS struct {
CertificatePath string `yaml:"certificate" validate:"required"` CertificatePath string `yaml:"certificate" validate:"required"`
@ -945,24 +949,35 @@ func iterateThroughSubdomains(globalOutbox chan library.InterServiceMessage) {
} }
// Iterate through the paths // Iterate through the paths
for _, path := range route.Paths { for _, pathBlock := range route.Paths {
if path.Static.Root != "" { for _, path := range pathBlock.Paths {
// Serve the static directory if pathBlock.Static.Root != "" {
rawPath := strings.TrimSuffix(path.Path, "*") // Serve the static directory
subdomainRouter.Handle(path.Path, http.StripPrefix(rawPath, newFileServer(path.Static.Root, path.Static.DirectoryListing, rawPath))) rawPath := strings.TrimSuffix(path, "*")
slog.Info("Serving static directory " + path.Static.Root + " on subdomain " + route.Subdomain + " with pattern " + path.Path) subdomainRouter.Handle(path, http.StripPrefix(rawPath, newFileServer(pathBlock.Static.Root, pathBlock.Static.DirectoryListing, rawPath)))
} else if path.Proxy.URL != "" { slog.Info("Serving static directory " + pathBlock.Static.Root + " on subdomain " + route.Subdomain + " with pattern " + path)
// Parse the URL } else if pathBlock.Proxy.URL != "" {
proxyUrl, err := url.Parse(path.Proxy.URL) // Parse the URL
if err != nil { proxyUrl, err := url.Parse(pathBlock.Proxy.URL)
slog.Error("Error parsing URL: " + err.Error()) if err != nil {
os.Exit(1) slog.Error("Error parsing URL: " + err.Error())
} os.Exit(1)
// Create the proxy }
if path.Proxy.StripPrefix { // Create the proxy
subdomainRouter.Handle(path.Path, http.StripPrefix(strings.TrimSuffix(path.Path, "*"), httputil.NewSingleHostReverseProxy(proxyUrl))) if pathBlock.Proxy.StripPrefix {
} else { subdomainRouter.Handle(path, http.StripPrefix(strings.TrimSuffix(path, "*"), httputil.NewSingleHostReverseProxy(proxyUrl)))
subdomainRouter.Handle(path.Path, httputil.NewSingleHostReverseProxy(proxyUrl)) } else {
subdomainRouter.Handle(path, httputil.NewSingleHostReverseProxy(proxyUrl))
}
} else if pathBlock.Redirect.URL != "" {
// Set the code
code := http.StatusFound
if pathBlock.Redirect.Permanent {
code = http.StatusMovedPermanently
}
// Create the redirect
subdomainRouter.Handle(path, http.RedirectHandler(pathBlock.Redirect.URL, code))
} }
} }
} }
@ -971,8 +986,7 @@ func iterateThroughSubdomains(globalOutbox chan library.InterServiceMessage) {
if route.HTTPS.CertificatePath != "" && route.HTTPS.KeyPath != "" { if route.HTTPS.CertificatePath != "" && route.HTTPS.KeyPath != "" {
certificate, err := loadTLSCertificate(route.HTTPS.CertificatePath, route.HTTPS.KeyPath) certificate, err := loadTLSCertificate(route.HTTPS.CertificatePath, route.HTTPS.KeyPath)
if err != nil { if err != nil {
slog.Error("Error loading TLS certificate: " + err.Error()) slog.Error("Error loading TLS certificate: " + err.Error() + ", TLS will not be available for subdomain " + route.Subdomain)
os.Exit(1)
} }
certificates[route.Subdomain] = certificate certificates[route.Subdomain] = certificate
} }
@ -1093,8 +1107,7 @@ func main() {
if config.Global.HTTPS.CertificatePath != "" && config.Global.HTTPS.KeyPath != "" { if config.Global.HTTPS.CertificatePath != "" && config.Global.HTTPS.KeyPath != "" {
certificate, err := loadTLSCertificate(config.Global.HTTPS.CertificatePath, config.Global.HTTPS.KeyPath) certificate, err := loadTLSCertificate(config.Global.HTTPS.CertificatePath, config.Global.HTTPS.KeyPath)
if err != nil { if err != nil {
slog.Error("Error loading TLS certificate: " + err.Error()) slog.Error("Error loading TLS certificate: " + err.Error() + ", TLS will not be available unless specified in the subdomains")
os.Exit(1)
} }
certificates["none"] = certificate certificates["none"] = certificate