feat(docker): Add Dockerfile and compose file
This commit is contained in:
104
app/proxy/reverse.go
Normal file
104
app/proxy/reverse.go
Normal file
@@ -0,0 +1,104 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user