| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- package service
- import (
- "net/http"
- "strings"
- "unicode/utf8"
- infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
- "golang.org/x/net/http/httpguts"
- )
- // AccountExtraUpstreamRequestIDHeader 是账户 extra 中的键,值为直接上游声明请求标识的响应头名。
- // 未指定时不记录上游请求标识。
- const AccountExtraUpstreamRequestIDHeader = "upstream_request_id_header"
- const (
- maxUpstreamRequestIDHeaderNameLen = 64
- // maxUsageUpstreamRequestIDLen 与 usage_logs.upstream_request_id VARCHAR(128) 对齐。
- maxUsageUpstreamRequestIDLen = 128
- )
- // UpstreamRequestIDHeaderName 返回账户指定的上游请求标识头名,未指定时为空串。
- func UpstreamRequestIDHeaderName(account *Account) string {
- if account == nil {
- return ""
- }
- return strings.TrimSpace(account.GetExtraString(AccountExtraUpstreamRequestIDHeader))
- }
- // UpstreamRequestIDFromHeaders 从直接上游的响应头解析请求标识。
- // 只读账户指定的头;账户未指定头名时恒为空串。
- func UpstreamRequestIDFromHeaders(account *Account, h http.Header) string {
- if len(h) == 0 {
- return ""
- }
- name := UpstreamRequestIDHeaderName(account)
- if name == "" {
- return ""
- }
- return strings.TrimSpace(h.Get(name))
- }
- // usageUpstreamRequestIDPtr 生成落库到 usage_logs.upstream_request_id 的值。
- // WS 轮次没有 HTTP 响应头,保持 nil;超长时截断到列宽而不是让整条用量行失败。
- func usageUpstreamRequestIDPtr(account *Account, h http.Header, wsMode bool) *string {
- if wsMode {
- return nil
- }
- id := UpstreamRequestIDFromHeaders(account, h)
- if id == "" {
- return nil
- }
- if len(id) > maxUsageUpstreamRequestIDLen {
- id = id[:maxUsageUpstreamRequestIDLen]
- for len(id) > 0 && !utf8.ValidString(id) {
- id = id[:len(id)-1]
- }
- }
- if id == "" {
- return nil
- }
- return &id
- }
- // ValidateUpstreamRequestIDHeaderExtra 校验并规范化 extra 中的上游请求标识头名:
- // 必须是合法的 HTTP 头字段名且不超过 64 字节;空白值视为未指定并从 extra 中移除。
- func ValidateUpstreamRequestIDHeaderExtra(extra map[string]any) error {
- if extra == nil {
- return nil
- }
- raw, ok := extra[AccountExtraUpstreamRequestIDHeader]
- if !ok || raw == nil {
- return nil
- }
- name, ok := raw.(string)
- if !ok {
- return infraerrors.BadRequest("INVALID_UPSTREAM_REQUEST_ID_HEADER",
- "upstream_request_id_header must be a string")
- }
- name = strings.TrimSpace(name)
- if name == "" {
- delete(extra, AccountExtraUpstreamRequestIDHeader)
- return nil
- }
- if len(name) > maxUpstreamRequestIDHeaderNameLen || !httpguts.ValidHeaderFieldName(name) {
- return infraerrors.BadRequest("INVALID_UPSTREAM_REQUEST_ID_HEADER",
- "upstream_request_id_header must be a valid HTTP header name of at most 64 bytes")
- }
- extra[AccountExtraUpstreamRequestIDHeader] = name
- return nil
- }
|