History

fix(claude): preserve legacy user agent overrides

tpob committed 7 months ago

Commit c7b59071 parent f36a5792 files · +40 −4Browse files

Unified · Split

2 files
  1. internal/runtime/executor/claude_device_profile.go +8 −4
  2. internal/runtime/executor/claude_executor_test.go +32 −0
internal/runtime/executor/claude_device_profile.go+8−4
@@ -308,15 +308,19 @@ func applyClaudeLegacyDeviceHeaders(r *http.Request, ginHeaders http.Header, cfg · 307 unmodified lines
308 miscEnsure("X-Stainless-Os", mapStainlessOS())308 miscEnsure("X-Stainless-Os", mapStainlessOS())
309 miscEnsure("X-Stainless-Arch", mapStainlessArch())309 miscEnsure("X-Stainless-Arch", mapStainlessArch())
310 310
311 // Legacy mode preserves per-auth custom header overrides. By the time we get
312 // here, ApplyCustomHeadersFromAttrs has already populated r.Header.
313 if strings.TrimSpace(r.Header.Get("User-Agent")) != "" {
314 return
315 }
316
311 clientUA := ""317 clientUA := ""
312 if ginHeaders != nil {318 if ginHeaders != nil {
313 clientUA = ginHeaders.Get("User-Agent")319 clientUA = strings.TrimSpace(ginHeaders.Get("User-Agent"))
314 }320 }
315 if isClaudeCodeClient(clientUA) {321 if isClaudeCodeClient(clientUA) {
316 r.Header.Set("User-Agent", clientUA)322 r.Header.Set("User-Agent", clientUA)
317 return323 return
318 }324 }
319 if strings.TrimSpace(r.Header.Get("User-Agent")) == "" {325 r.Header.Set("User-Agent", profile.UserAgent)
320 r.Header.Set("User-Agent", profile.UserAgent)
321 }
322}326}
internal/runtime/executor/claude_executor_test.go+32−0
@@ -216,6 +216,38 @@ func TestApplyClaudeHeaders_DisableDeviceProfileStabilization(t *testing.T) { · 215 unmodified lines
216 assertClaudeFingerprint(t, lowerReq.Header, "claude-cli/2.1.61 (external, cli)", "0.73.0", "v24.2.0", "Windows", "x64")216 assertClaudeFingerprint(t, lowerReq.Header, "claude-cli/2.1.61 (external, cli)", "0.73.0", "v24.2.0", "Windows", "x64")
217}217}
218 218
219func TestApplyClaudeHeaders_LegacyModePreservesConfiguredUserAgentOverrideForClaudeClients(t *testing.T) {
220 resetClaudeDeviceProfileCache()
221
222 stabilize := false
223 cfg := &config.Config{
224 ClaudeHeaderDefaults: config.ClaudeHeaderDefaults{
225 UserAgent: "claude-cli/2.1.60 (external, cli)",
226 PackageVersion: "0.70.0",
227 RuntimeVersion: "v22.0.0",
228 StabilizeDeviceProfile: &stabilize,
229 },
230 }
231 auth := &cliproxyauth.Auth{
232 ID: "auth-legacy-ua-override",
233 Attributes: map[string]string{
234 "api_key": "key-legacy-ua-override",
235 "header:User-Agent": "config-ua/1.0",
236 },
237 }
238
239 req := newClaudeHeaderTestRequest(t, http.Header{
240 "User-Agent": []string{"claude-cli/2.1.62 (external, cli)"},
241 "X-Stainless-Package-Version": []string{"0.74.0"},
242 "X-Stainless-Runtime-Version": []string{"v24.3.0"},
243 "X-Stainless-Os": []string{"Linux"},
244 "X-Stainless-Arch": []string{"x64"},
245 })
246 applyClaudeHeaders(req, auth, "key-legacy-ua-override", false, nil, cfg)
247
248 assertClaudeFingerprint(t, req.Header, "config-ua/1.0", "0.74.0", "v24.3.0", "Linux", "x64")
249}
250
219func TestApplyClaudeHeaders_LegacyModeFallsBackToRuntimeOSArchWhenMissing(t *testing.T) {251func TestApplyClaudeHeaders_LegacyModeFallsBackToRuntimeOSArchWhenMissing(t *testing.T) {
220 resetClaudeDeviceProfileCache()252 resetClaudeDeviceProfileCache()
221 253