diff options
-rw-r--r-- | deploy_host.example.env | 3 | ||||
-rw-r--r-- | dev_host.example.env | 2 | ||||
-rw-r--r-- | justfile | 6 | ||||
-rw-r--r-- | main.go | 34 |
4 files changed, 42 insertions, 3 deletions
diff --git a/deploy_host.example.env b/deploy_host.example.env new file mode 100644 index 0000000..3d33eb8 --- /dev/null +++ b/deploy_host.example.env @@ -0,0 +1,3 @@ +NATS_CREDS_FILE=/root/web-proxy.creds +NATS_URL=tls://apex.zambito.xyz +NATS_INBOX_PREFIX=_INBOX_web-proxy
\ No newline at end of file diff --git a/dev_host.example.env b/dev_host.example.env new file mode 100644 index 0000000..705670e --- /dev/null +++ b/dev_host.example.env @@ -0,0 +1,2 @@ +DEPLOY_HOST=root@alpha.apex +DEPLOY_DIR=src/http-nats-proxy
\ No newline at end of file @@ -1,11 +1,17 @@ set dotenv-load := true +@default: + just --list + clean: rm -rf bin/ build: go build -o bin/http-nats-proxy main.go +run: clean build + ./bin/http-nats-proxy + deploy: ssh -t {{env('DEPLOY_HOST')}} "\ cd {{env('DEPLOY_DIR')}} && \ @@ -10,6 +10,7 @@ import ( "os" "strings" "time" + "net/url" "github.com/nats-io/nats.go" ) @@ -29,6 +30,28 @@ func printHelp() { fmt.Println(" HTTP_PORT - HTTP port to listen on (default: 8080)") } + +// URL to NATS subject conversion +func URLToNATS(urlPath string) (string, error) { + segments := strings.Split(strings.Trim(urlPath, "/"), "/") + for i, seg := range segments { + // Decode existing encoding first to prevent double-encoding + unescaped, err := url.PathUnescape(seg) + if err != nil { + return "", fmt.Errorf("failed to unescape segment: %w", err) + } + + // Encode special NATS-sensitive characters + encoded := url.PathEscape(unescaped) + encoded = strings.ReplaceAll(encoded, ".", "%2E") // Critical for token separation + encoded = strings.ReplaceAll(encoded, "*", "%2A") // Wildcard protection + encoded = strings.ReplaceAll(encoded, ">", "%3E") // Wildcard protection + + segments[i] = encoded + } + return strings.Join(segments, "."), nil +} + func main() { helpFlag := flag.Bool("help", false, "Display help information about available environment variables") flag.Parse() @@ -103,9 +126,14 @@ func main() { domainParts := strings.ReplaceAll(host, ".", "_") // Process path component - path := strings.TrimPrefix(r.URL.Path, "/") - // Replace all "." with "_" and then all "/" with ".". - subjectPath := strings.ReplaceAll(strings.ReplaceAll(path, ".", "_"), "/", ".") + path := strings.TrimSuffix(strings.TrimPrefix(r.URL.Path, "/"), "/") + subjectPath, err := URLToNATS(path) + if err != nil { + http.Error(w, "Error converting endpoint to NATS subject", http.StatusInternalServerError) + log.Println("Could not convert endpoint to NATS subject", err) + return + + } // Build final subject subjectBase := "http" |