69 lines
3.2 KiB
Go
69 lines
3.2 KiB
Go
package http
|
||
|
||
import (
|
||
"net/http/httptest"
|
||
"strings"
|
||
"testing"
|
||
|
||
"hyapp/services/gateway-service/internal/transport/http/httpkit"
|
||
)
|
||
|
||
// 设备资料头是 App 全局注入的,两个 meta builder(httpkit 通用版与 auth 专用版)都必须透传,
|
||
// 否则登录链路与业务链路的设备档案会出现来源分叉。
|
||
func TestRequestMetaBuildersCarryDeviceProfileHeaders(t *testing.T) {
|
||
request := httptest.NewRequest("POST", "/api/v1/auth/login", nil)
|
||
request.Header.Set("X-Device-Model", "Redmi Note 8 Pro")
|
||
request.Header.Set("X-Device-Manufacturer", "Xiaomi")
|
||
request.Header.Set("X-OS-Version", "13")
|
||
request.Header.Set("X-Device-IMEI", "123456789012345")
|
||
|
||
authMeta := authRequestMetaWithLoginContext(request, "dev-1", "android", "en", "Asia/Riyadh", "", "")
|
||
if authMeta.GetDeviceModel() != "Redmi Note 8 Pro" || authMeta.GetDeviceManufacturer() != "Xiaomi" ||
|
||
authMeta.GetOsVersion() != "13" || authMeta.GetImei() != "123456789012345" {
|
||
t.Fatalf("auth meta must carry device profile headers: %+v", authMeta)
|
||
}
|
||
|
||
userMeta := httpkit.UserMeta(request, "dev-1")
|
||
if userMeta.GetDeviceModel() != "Redmi Note 8 Pro" || userMeta.GetDeviceManufacturer() != "Xiaomi" ||
|
||
userMeta.GetOsVersion() != "13" || userMeta.GetImei() != "123456789012345" {
|
||
t.Fatalf("httpkit user meta must carry device profile headers: %+v", userMeta)
|
||
}
|
||
|
||
// 头缺失时保持空串:user-service 端“非空覆盖”依赖空值不参与合并。
|
||
bare := httptest.NewRequest("POST", "/api/v1/auth/refresh", nil)
|
||
bareMeta := authRequestMetaWithLoginContext(bare, "dev-1", "", "", "", "", "")
|
||
if bareMeta.GetDeviceModel() != "" || bareMeta.GetImei() != "" {
|
||
t.Fatalf("missing headers must map to empty meta fields: %+v", bareMeta)
|
||
}
|
||
}
|
||
|
||
// body device/os_version 属于旧协议;标准客户端只发设备头,回退逻辑保证 register 快照不再为空,
|
||
// 同时 body 显式值仍优先,旧客户端行为不变。
|
||
func TestDeviceFieldsWithHeaderFallback(t *testing.T) {
|
||
request := httptest.NewRequest("POST", "/api/v1/auth/register", nil)
|
||
request.Header.Set("X-Device-Model", "iPhone17,2")
|
||
request.Header.Set("X-OS-Version", "18.1")
|
||
meta := authRequestMetaWithLoginContext(request, "dev-2", "ios", "", "", "", "")
|
||
|
||
device, osVersion := deviceFieldsWithHeaderFallback("", " ", meta)
|
||
if device != "iPhone17,2" || osVersion != "18.1" {
|
||
t.Fatalf("empty body fields must fall back to headers: device=%q os=%q", device, osVersion)
|
||
}
|
||
|
||
device, osVersion = deviceFieldsWithHeaderFallback("Pixel 8", "14", meta)
|
||
if device != "Pixel 8" || osVersion != "14" {
|
||
t.Fatalf("body fields must win over headers: device=%q os=%q", device, osVersion)
|
||
}
|
||
}
|
||
|
||
// H5 与原生共用设备上报协议,新设备头必须落进默认 CORS 允许集,否则浏览器 preflight 直接拦掉。
|
||
func TestCORSDefaultHeadersAllowDeviceProfile(t *testing.T) {
|
||
config := normalizeCORSConfig(CORSConfig{})
|
||
allowedHeaders := "," + strings.ToLower(strings.Join(config.AllowedHeaders, ",")) + ","
|
||
for _, header := range []string{"X-Device-Model", "X-Device-Manufacturer", "X-OS-Version", "X-Device-IMEI"} {
|
||
if !strings.Contains(allowedHeaders, ","+strings.ToLower(header)+",") {
|
||
t.Fatalf("default CORS headers must allow device profile header %q: %+v", header, config.AllowedHeaders)
|
||
}
|
||
}
|
||
}
|