mirror of
https://github.com/karust/openserp.git
synced 2026-08-05 16:53:54 +08:00
168 lines
4.8 KiB
Go
168 lines
4.8 KiB
Go
package core
|
|
|
|
import (
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
)
|
|
|
|
func TestStatusText(t *testing.T) {
|
|
tests := []struct {
|
|
code int
|
|
expected string
|
|
}{
|
|
{400, "bad_request"},
|
|
{404, "not_found"},
|
|
{429, "rate_limited"},
|
|
{503, "service_unavailable"},
|
|
{401, "client_error"},
|
|
{500, "server_error"},
|
|
{200, "error"},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
result := statusText(tt.code)
|
|
if result != tt.expected {
|
|
t.Errorf("statusText(%d) = %s, want %s", tt.code, result, tt.expected)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Middleware unit tests validate CORS behavior itself (header composition and preflight semantics).
|
|
func TestCORSMiddleware_UsesConfiguredHeaders(t *testing.T) {
|
|
app := fiber.New()
|
|
app.Use(CORSMiddleware(CORSConfig{
|
|
AllowOrigins: "https://example.com",
|
|
AllowMethods: "GET,OPTIONS",
|
|
AllowHeaders: "Authorization,Content-Type",
|
|
MaxAge: 1200,
|
|
}))
|
|
app.Get("/ping", func(c *fiber.Ctx) error {
|
|
return c.SendStatus(fiber.StatusOK)
|
|
})
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/ping", nil)
|
|
resp, err := app.Test(req, -1)
|
|
if err != nil {
|
|
t.Fatalf("request failed: %v", err)
|
|
}
|
|
|
|
if got := resp.Header.Get("Access-Control-Allow-Origin"); got != "https://example.com" {
|
|
t.Fatalf("unexpected allow-origin: %q", got)
|
|
}
|
|
if got := resp.Header.Get("Access-Control-Allow-Methods"); got != "GET,OPTIONS" {
|
|
t.Fatalf("unexpected allow-methods: %q", got)
|
|
}
|
|
if got := resp.Header.Get("Access-Control-Allow-Headers"); got != "Authorization,Content-Type" {
|
|
t.Fatalf("unexpected allow-headers: %q", got)
|
|
}
|
|
if got := resp.Header.Get("Access-Control-Max-Age"); got != "1200" {
|
|
t.Fatalf("unexpected max-age: %q", got)
|
|
}
|
|
if got := resp.Header.Get("Access-Control-Expose-Headers"); !strings.Contains(got, "X-Network-Bytes") || !strings.Contains(got, "X-Browser-Profile-Id") || !strings.Contains(got, "X-Proxy-Attempts") {
|
|
t.Fatalf("expected exposed headers to include network, browser profile, and proxy-attempts headers, got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestCORSMiddleware_OPTIONSReturnsNoContent(t *testing.T) {
|
|
app := fiber.New()
|
|
app.Use(CORSMiddleware(DefaultCORSConfig()))
|
|
app.Get("/ping", func(c *fiber.Ctx) error {
|
|
return c.SendStatus(fiber.StatusOK)
|
|
})
|
|
|
|
req := httptest.NewRequest(http.MethodOptions, "/ping", nil)
|
|
resp, err := app.Test(req, -1)
|
|
if err != nil {
|
|
t.Fatalf("request failed: %v", err)
|
|
}
|
|
if resp.StatusCode != fiber.StatusNoContent {
|
|
t.Fatalf("expected 204 for OPTIONS, got %d", resp.StatusCode)
|
|
}
|
|
}
|
|
|
|
func TestNormalizeCORSConfig_FillsMissingValues(t *testing.T) {
|
|
cfg := normalizeCORSConfig(CORSConfig{
|
|
AllowOrigins: "https://example.com",
|
|
})
|
|
def := DefaultCORSConfig()
|
|
|
|
if cfg.AllowOrigins != "https://example.com" {
|
|
t.Fatalf("expected custom allow_origins preserved, got %q", cfg.AllowOrigins)
|
|
}
|
|
if cfg.AllowMethods != def.AllowMethods {
|
|
t.Fatalf("expected default allow_methods, got %q", cfg.AllowMethods)
|
|
}
|
|
if cfg.AllowHeaders != def.AllowHeaders {
|
|
t.Fatalf("expected default allow_headers, got %q", cfg.AllowHeaders)
|
|
}
|
|
if cfg.MaxAge != def.MaxAge {
|
|
t.Fatalf("expected default max_age, got %d", cfg.MaxAge)
|
|
}
|
|
}
|
|
|
|
func TestDefaultCORSConfig_IncludesProxyOverrideHeader(t *testing.T) {
|
|
cfg := DefaultCORSConfig()
|
|
if got := cfg.AllowHeaders; !strings.Contains(got, "X-Use-Proxy") {
|
|
t.Fatalf("expected allow_headers to include X-Use-Proxy, got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestRequestContextMiddleware_EchoesProvidedRequestID(t *testing.T) {
|
|
app := fiber.New()
|
|
app.Use(RequestContextMiddleware())
|
|
app.Get("/id", func(c *fiber.Ctx) error {
|
|
return c.SendString(RequestIDFromContext(c.UserContext()))
|
|
})
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/id", nil)
|
|
req.Header.Set("X-Request-ID", "foo")
|
|
resp, err := app.Test(req, -1)
|
|
if err != nil {
|
|
t.Fatalf("request failed: %v", err)
|
|
}
|
|
|
|
if got := resp.Header.Get("X-Request-ID"); got != "foo" {
|
|
t.Fatalf("expected response X-Request-ID=foo, got %q", got)
|
|
}
|
|
if got := readBody(t, resp); got != "foo" {
|
|
t.Fatalf("expected context request id to be echoed, got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestRequestContextMiddleware_GeneratesRequestID(t *testing.T) {
|
|
app := fiber.New()
|
|
app.Use(RequestContextMiddleware())
|
|
app.Get("/id", func(c *fiber.Ctx) error {
|
|
return c.SendString(RequestIDFromContext(c.UserContext()))
|
|
})
|
|
|
|
req := httptest.NewRequest(http.MethodGet, "/id", nil)
|
|
resp, err := app.Test(req, -1)
|
|
if err != nil {
|
|
t.Fatalf("request failed: %v", err)
|
|
}
|
|
|
|
requestID := resp.Header.Get("X-Request-ID")
|
|
if requestID == "" {
|
|
t.Fatal("expected generated X-Request-ID")
|
|
}
|
|
if got := readBody(t, resp); got != requestID {
|
|
t.Fatalf("expected request id in context to match header: body=%q header=%q", got, requestID)
|
|
}
|
|
}
|
|
|
|
func readBody(t *testing.T, resp *http.Response) string {
|
|
t.Helper()
|
|
defer resp.Body.Close()
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
t.Fatalf("read body failed: %v", err)
|
|
}
|
|
return string(body)
|
|
}
|