Files
heicode-mananger/heicode/controller/heicode_auth_proxy.go
T

69 lines
2.1 KiB
Go

package controller
import (
"io"
"net/http"
"strings"
"time"
"github.com/gin-gonic/gin"
)
// HeicodeAuthProxy transparently forwards browser calls to the upstream Heicode
// identity service (APIM). The frontend cannot call APIM directly because that
// host does not include code.xinghanlab.com in its CORS allow-list, so we
// terminate the request same-origin and re-emit it server-side.
//
// Mounted at /api/heicode-auth/*proxyPath. The trailing path (everything after
// /api/heicode-auth/) is appended verbatim to HEICODE_AUTH_BASE_URL. Request
// method, query string, body, and the Authorization header are preserved.
func HeicodeAuthProxy(c *gin.Context) {
tail := strings.TrimPrefix(c.Param("proxyPath"), "/")
if tail == "" {
c.JSON(http.StatusNotFound, gin.H{"success": false, "message": "missing upstream path"})
return
}
baseURL := defaultHeicodeAuthBaseURL()
target := baseURL + "/" + tail
if raw := c.Request.URL.RawQuery; raw != "" {
target += "?" + raw
}
var body io.Reader
if c.Request.Body != nil {
body = c.Request.Body
}
req, err := http.NewRequestWithContext(c.Request.Context(), c.Request.Method, target, body)
if err != nil {
c.JSON(http.StatusBadGateway, gin.H{"success": false, "message": "upstream request build failed"})
return
}
// Forward only headers that matter for the upstream call. We intentionally
// drop Cookie, Host, Origin, Referer so APIM does not see browser context.
if auth := strings.TrimSpace(c.GetHeader("Authorization")); auth != "" {
req.Header.Set("Authorization", auth)
}
if ct := strings.TrimSpace(c.GetHeader("Content-Type")); ct != "" {
req.Header.Set("Content-Type", ct)
}
if accept := strings.TrimSpace(c.GetHeader("Accept")); accept != "" {
req.Header.Set("Accept", accept)
}
client := &http.Client{Timeout: 20 * time.Second}
resp, err := client.Do(req)
if err != nil {
c.JSON(http.StatusBadGateway, gin.H{"success": false, "message": "upstream request failed"})
return
}
defer resp.Body.Close()
if ct := resp.Header.Get("Content-Type"); ct != "" {
c.Writer.Header().Set("Content-Type", ct)
}
c.Writer.WriteHeader(resp.StatusCode)
_, _ = io.Copy(c.Writer, resp.Body)
}