package connectsrv import "net/http" // nativeWebViewOrigins are the browser Origins of the packaged native apps. Capacitor serves the // bundled SPA from a localhost scheme, so its Connect calls to the gateway are cross-origin; the web // app is same-origin and needs no entry. Requests carry Authorization, so the allowlist reflects the // exact origin rather than "*". var nativeWebViewOrigins = map[string]bool{ "https://localhost": true, // Capacitor Android (default https scheme) "http://localhost": true, // Capacitor with the http scheme "capacitor://localhost": true, // Capacitor iOS default scheme } // withNativeCORS answers the CORS preflight and adds the CORS response headers for the packaged // native apps' cross-origin calls to the Connect edge. Without it the WebView blocks every RPC on the // preflight (the gateway otherwise returns 405 with no Access-Control-Allow-Origin), so a native // build can never reach the gateway and stays stuck offline. Same-origin (web) and any non-native // origin are untouched. func withNativeCORS(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { origin := r.Header.Get("Origin") if nativeWebViewOrigins[origin] { h := w.Header() h.Set("Access-Control-Allow-Origin", origin) h.Add("Vary", "Origin") h.Set("Access-Control-Allow-Credentials", "true") // The client interceptor reads the soft-tier update signal off the response. h.Set("Access-Control-Expose-Headers", "X-Update-Recommended") if r.Method == http.MethodOptions { h.Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS") // Reflect the requested headers (the origin is already allowlisted): the Connect client // sends Connect-Protocol-Version / Connect-Timeout-Ms plus X-Client-Version and // Authorization, and the exact set varies by call. if reqHeaders := r.Header.Get("Access-Control-Request-Headers"); reqHeaders != "" { h.Set("Access-Control-Allow-Headers", reqHeaders) } else { h.Set("Access-Control-Allow-Headers", "Content-Type, Connect-Protocol-Version, X-Client-Version, Authorization") } h.Set("Access-Control-Max-Age", "86400") w.WriteHeader(http.StatusNoContent) return } } next.ServeHTTP(w, r) }) }