common

package
v0.25.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 1, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

Documentation

Overview

* @Author: kamalyes 501893067@qq.com * @Date: 2025-11-12 15:05:00 * @LastEditors: kamalyes 501893067@qq.com * @LastEditTime: 2025-11-12 15:05:00 * @FilePath: \go-config\pkg\common\attribute_source.go * @Description: * * Copyright (c) 2025 by kamalyes, All Rights Reserved.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ExtractAttribute

func ExtractAttribute(r *http.Request, sources []AttributeSource) string

ExtractAttribute 从请求中按优先级提取属性

取单个属性时用这个就够了。要取多个属性请改用 NewAttributeExtractor: 这里每次调用都会重建提取器,于是查询串与 Cookie 头在每次调用里各解析一次, 调 28 次就解析 28 次 [EN] Enough for a single attribute. For several attributes use NewAttributeExtractor instead: this rebuilds the extractor per call, so the query string is parsed once per call

func ExtractFromSource

func ExtractFromSource(r *http.Request, source AttributeSource) string

ExtractFromSource 从指定来源提取值

Types

type AttributeExtractor

type AttributeExtractor struct {
	// contains filtered or unexported fields
}

AttributeExtractor 请求级的属性提取器:把一次请求里重复的解析各收敛成一次

为什么需要它:query 与 cookie 的提取在标准库里都是「每次调用重新解析」——

r.URL.Query() 每次都跑一遍 url.ParseQuery(RawQuery) 并新建一个 url.Values
r.Cookie(name) 每次都重解一遍整个 Cookie 头

单看一次调用没问题,但真实调用方是「一个属性一次 ExtractAttribute」: 网关要取 28 个属性,默认来源清单里有 43 个 query 来源与 25 个 cookie 来源, 于是同一个查询串每请求被解析几十遍

实测(go-config/pkg/gateway 的 BenchmarkExtractAttribute_DefaultSources, 按真实默认配置取齐 28 个属性):带查询串时 14.2 微秒、327 次分配, 其中 url.ParseQuery 占调用方那条中间件全部分配对象的 57%

用法:一次请求建一个提取器,28 个属性共用它

e := common.NewAttributeExtractor(r)
traceID := e.Extract(cfg.TraceIDSources)
userID  := e.Extract(cfg.UserIDSources)

语义与 ExtractAttribute 完全一致:按顺序取第一个非空值

并发:提取器是请求级的,不做加锁,不要跨 goroutine 共享

[EN] A request-scoped extractor that collapses the repeated parsing into one pass each. Both r.URL.Query() and r.Cookie(name) re-parse from scratch on every call, which is fine for one call but not for the real usage pattern of one ExtractAttribute call per attribute: a gateway reads 28 attributes while the default source lists hold 43 query and 25 cookie sources, so the same query string is parsed dozens of times per request. Semantics are unchanged -- the first non-empty source wins. The extractor is request-scoped and unsynchronized

func NewAttributeExtractor

func NewAttributeExtractor(r *http.Request) *AttributeExtractor

NewAttributeExtractor 为一次请求创建提取器,跨多个属性复用

func (*AttributeExtractor) Extract

func (e *AttributeExtractor) Extract(sources []AttributeSource) string

Extract 按优先级提取属性:顺序取第一个非空值

func (*AttributeExtractor) FromSource

func (e *AttributeExtractor) FromSource(source AttributeSource) string

FromSource 从指定来源提取值

type AttributeSource

type AttributeSource struct {
	Type AttributeSourceType `mapstructure:"type" yaml:"type" json:"type" validate:"required,oneof=query header cookie"` // 来源类型: query, header, cookie
	Key  string              `mapstructure:"key" yaml:"key" json:"key" validate:"required"`                              // 提取的字段名
}

AttributeSource 属性提取来源配置

func (*AttributeSource) NormalizeKey

func (a *AttributeSource) NormalizeKey()

NormalizeKey 把 header 来源的 Key 归一成 HTTP 规范形式(x-user-id -> X-User-Id)

为什么要在加载后做一次:Header.Get 每次查找都会对 key 调 CanonicalMIMEHeaderKey, key 本来就是规范形式时它原样返回、不分配;不是的话每次查找都要现算并分配一个新字符串 配置是加载一次、查找千万次,所以这笔归一化该在加载时付一次,而不是让每次查找各付一遍

两种拼法的查找结果完全一样(都归到同一个 header),所以这是纯粹的削减

实测:提取器修掉重复解析之后,canonicalMIMEHeaderKey 占了 header 路径剩余分配的 100%; key 归一之后该路径降到零分配

非 header 来源不动:query 与 cookie 的键名是大小写敏感的,规范化会改变语义

[EN] Canonicalizes a header source's key once after load. Header.Get canonicalizes on every lookup and returns the key untouched only when it is already canonical, so this cost belongs at load time rather than on every one of millions of lookups. Both spellings resolve to the same header, making this a pure saving. Query and cookie keys are left alone because they are case-sensitive and normalizing them would change meaning

func (*AttributeSource) Validate

func (a *AttributeSource) Validate() error

Validate 验证属性来源配置

type AttributeSourceType

type AttributeSourceType string

AttributeSourceType 属性提取来源类型

const (
	// SourceTypeQuery 从 URL 查询参数提取
	SourceTypeQuery AttributeSourceType = "query"
	// SourceTypeHeader 从 HTTP Header 提取
	SourceTypeHeader AttributeSourceType = "header"
	// SourceTypeCookie 从 Cookie 提取
	SourceTypeCookie AttributeSourceType = "cookie"
)

func (AttributeSourceType) IsValid

func (t AttributeSourceType) IsValid() bool

IsValid 验证来源类型是否有效

func (AttributeSourceType) String

func (t AttributeSourceType) String() string

String 返回字符串表示

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL