-
Notifications
You must be signed in to change notification settings - Fork 11.1k
feats:add custom headers override #1644
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -13,6 +13,7 @@ import ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "one-api/relay/helper" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "one-api/service" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "one-api/setting/operation_setting" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "one-api/types" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "sync" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "time" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -47,7 +48,19 @@ func DoApiRequest(a Adaptor, c *gin.Context, info *common.RelayInfo, requestBody | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, fmt.Errorf("new request failed: %w", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err = a.SetupRequestHeader(c, &req.Header, info) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| headers := req.Header | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| headerOverride := make(map[string]string) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for k, v := range info.HeadersOverride { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if str, ok := v.(string); ok { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| headerOverride[k] = str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, types.NewError(err, types.ErrorCodeChannelHeaderOverrideInvalid) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for key, value := range headerOverride { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| headers.Set(key, value) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err = a.SetupRequestHeader(c, &headers, info) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+51
to
+63
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Header overrides may be clobbered by SetupRequestHeader; also passing a nil err into types.NewError
Apply this diff: -headers := req.Header
-headerOverride := make(map[string]string)
-for k, v := range info.HeadersOverride {
- if str, ok := v.(string); ok {
- headerOverride[k] = str
- } else {
- return nil, types.NewError(err, types.ErrorCodeChannelHeaderOverrideInvalid)
- }
-}
-for key, value := range headerOverride {
- headers.Set(key, value)
-}
-err = a.SetupRequestHeader(c, &headers, info)
+headers := req.Header
+// First, let adaptor set its defaults (auth, content-type, etc.).
+if err = a.SetupRequestHeader(c, &headers, info); err != nil {
+ return nil, fmt.Errorf("setup request header failed: %w", err)
+}
+// Then apply channel overrides so they take precedence.
+for k, v := range info.HeadersOverride {
+ s, ok := v.(string)
+ if !ok {
+ return nil, types.NewError(
+ fmt.Errorf("header_override %q must be string, got %T", k, v),
+ types.ErrorCodeChannelHeaderOverrideInvalid,
+ )
+ }
+ headers.Set(k, s)
+}Optional hardening: filter disallowed headers (Host, Content-Length, Transfer-Encoding, Connection, TE, Trailer, Upgrade, Expect) or CR/LF in values before Set. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, fmt.Errorf("setup request header failed: %w", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -72,8 +85,19 @@ func DoFormRequest(a Adaptor, c *gin.Context, info *common.RelayInfo, requestBod | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // set form data | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| req.Header.Set("Content-Type", c.Request.Header.Get("Content-Type")) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err = a.SetupRequestHeader(c, &req.Header, info) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| headers := req.Header | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| headerOverride := make(map[string]string) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for k, v := range info.HeadersOverride { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if str, ok := v.(string); ok { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| headerOverride[k] = str | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, types.NewError(err, types.ErrorCodeChannelHeaderOverrideInvalid) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for key, value := range headerOverride { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| headers.Set(key, value) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err = a.SetupRequestHeader(c, &headers, info) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
86
to
101
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Same two issues in DoFormRequest: override order and nil err passed to NewError Replicate the fix used for DoApiRequest so that:
Apply this diff: -// set form data
-req.Header.Set("Content-Type", c.Request.Header.Get("Content-Type"))
-headers := req.Header
-headerOverride := make(map[string]string)
-for k, v := range info.HeadersOverride {
- if str, ok := v.(string); ok {
- headerOverride[k] = str
- } else {
- return nil, types.NewError(err, types.ErrorCodeChannelHeaderOverrideInvalid)
- }
-}
-for key, value := range headerOverride {
- headers.Set(key, value)
-}
-err = a.SetupRequestHeader(c, &headers, info)
+// Preserve incoming content-type for form uploads
+req.Header.Set("Content-Type", c.Request.Header.Get("Content-Type"))
+headers := req.Header
+// First set adaptor defaults
+if err = a.SetupRequestHeader(c, &headers, info); err != nil {
+ return nil, fmt.Errorf("setup request header failed: %w", err)
+}
+// Then apply overrides so they win
+for k, v := range info.HeadersOverride {
+ s, ok := v.(string)
+ if !ok {
+ return nil, types.NewError(
+ fmt.Errorf("header_override %q must be string, got %T", k, v),
+ types.ErrorCodeChannelHeaderOverrideInvalid,
+ )
+ }
+ headers.Set(k, s)
+}If you add disallowed header filtering in DoApiRequest, mirror it here for consistency. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil, fmt.Errorf("setup request header failed: %w", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Adding HeaderOverride column — ensure DB migration and add field comment
The new GORM field is fine. Please:
header_overrideto the channels table in all supported DBs.Run this script to confirm migrations/auto-migrate cover the new column and to locate usages:
🏁 Script executed:
Length of output: 9291
Add DB migration for
header_overrideand document its JSON structurePlease ensure the new
HeaderOverridefield inmodel/channel.gois fully supported:Database migration
No existing migration or
AutoMigratecall adds theheader_overridecolumn to thechannelstable. Add a migration (or update your auto-migrate logic) for all supported dialects. For example:• If you use a versioned migrations folder (e.g.
migrations/), add a new up/down SQL file.• If you rely on GORM’s
AutoMigrate, locate whereAutoMigrate(&Channel{})is invoked and confirm it’s applied in your deployment flow.Field comment in Go model
Explain the expected JSON format (flat map of header names to values). For example, above the field in
model/channel.go:// HeaderOverride holds a JSON-encoded map of HTTP header names to override values. // Example: {"User-Agent":"MyApp/1.0","Accept":"application/json"} HeaderOverride *string `json:"header_override" gorm:"type:text"`Locations to update:
model/channel.go(line 49) – add the above Go doc comment.header_overrideis added to thechannelstable schema.