Files
gogwapi/app/proxy/reverse.go
2025-11-29 03:09:40 +01:00

104 lines
2.5 KiB
Go

package proxy
import (
"fmt"
"net/http"
"net/http/httputil"
"net/url"
"strings"
"git.secnex.io/secnex/gogwapi/config"
"git.secnex.io/secnex/masterlog"
)
type ReverseProxy struct {
config *config.YAMLConfig
}
func NewReverseProxy(cfg *config.YAMLConfig) *ReverseProxy {
return &ReverseProxy{
config: cfg,
}
}
type TargetMatch struct {
URL *url.URL
Endpoint *config.Endpoint
}
func (rp *ReverseProxy) findTarget(host string, path string) (*TargetMatch, error) {
for _, target := range rp.config.Targets {
for _, record := range target.Records {
expectedHost := fmt.Sprintf("%s.%s", record.Record, target.Name)
if host == expectedHost {
for _, endpoint := range record.Endpoints {
if endpoint.Path == "/" {
targetURL, err := url.Parse(endpoint.URL)
if err != nil {
return nil, err
}
return &TargetMatch{URL: targetURL, Endpoint: &endpoint}, nil
}
if strings.HasPrefix(path, endpoint.Path) {
targetURL, err := url.Parse(endpoint.URL)
if err != nil {
return nil, err
}
return &TargetMatch{URL: targetURL, Endpoint: &endpoint}, nil
}
}
}
}
}
return nil, fmt.Errorf("no target found for host: %s, path: %s", host, path)
}
func (rp *ReverseProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
host := r.Host
path := r.URL.Path
targetMatch, err := rp.findTarget(host, path)
if err != nil {
masterlog.Error("target not found", map[string]interface{}{
"host": host,
"path": path,
"error": err.Error(),
})
http.Error(w, "Service not found", http.StatusNotFound)
return
}
targetURL := targetMatch.URL
endpoint := targetMatch.Endpoint
// Transform the path: remove the endpoint prefix if it's not "/"
var transformedPath string
if endpoint.Path == "/" {
transformedPath = path
} else {
transformedPath = strings.TrimPrefix(path, endpoint.Path)
if transformedPath == "" {
transformedPath = "/"
}
}
masterlog.Info("proxying request", map[string]interface{}{
"host": host,
"original_path": path,
"transformed_path": transformedPath,
"endpoint_prefix": endpoint.Path,
"target": targetURL.String(),
})
proxy := httputil.NewSingleHostReverseProxy(targetURL)
// Create a new request with the transformed path
r.URL.Host = targetURL.Host
r.URL.Scheme = targetURL.Scheme
r.URL.Path = transformedPath
r.Header.Set("X-Forwarded-Host", host)
r.Header.Set("X-Forwarded-For", r.RemoteAddr)
r.Header.Set("X-Forwarded-Path", path) // Original path for debugging
proxy.ServeHTTP(w, r)
}