Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

[bug]: Replayer splits comma-separated request headers, causing duplicate-name fields that break dict(**request.headers) middlewares

Aperta
#4,164 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
25/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Ferma
Stack tecnologico
go
Ambito
api, testing-qa

Direzione di ricerca

Inizia in pkg/util.go, su ToHTTPHeader intorno alla riga 206, quindi confrontalo con ToYamlHTTPHeader intorno alla riga 153 e rivedi PR #4163. Riproduci il replay in stile axios descritto nell'issue e verifica che gli header della richiesta separati da virgole non vengano suddivisi in campi duplicati, mentre Set-Cookie rimane invariato.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug
👀 Is there an existing issue for this?

I have searched and didn't find a similar issue.

👍 Current behavior

pkg.ToHTTPHeader (pkg/util.go) splits every recorded header value on commas:

header[i] = strings.Split(j, ",")

Go's http.Client then writes one wire header per slice element. A request the original client sent as one header with comma-separated values fans out into multiple duplicate-name fields during replay.

For axios-style traffic, the recorded YAML carries:

header:
  Accept: application/json, text/plain, */*
  Accept-Encoding: gzip, compress, deflate, br

…which is axios's default. At replay time the wire is:

Accept: application/json
Accept: text/plain
Accept: */*
Accept-Encoding: gzip
Accept-Encoding: compress
Accept-Encoding: deflate
Accept-Encoding: br

Strict server middlewares that build a response via Response(headers=dict(**request.headers), ...) raise:

TypeError: dict() got multiple values for keyword argument 'accept'

…on duplicate field names. This is a known FastAPI / Starlette failure mode — any service with a metrics / observability middleware using that pattern returns HTTP 500 with Content-Type: text/plain body Internal Server Error during replay, even though the original request was well-formed.

👟 Steps to Replicate
  1. Stand up a FastAPI app with a custom middleware that does:
    class MetricsMiddleware(BaseHTTPMiddleware):
        async def dispatch(self, request, call_next):
            response = await call_next(request)
            Response(headers=dict(**request.headers), status_code=response.status_code)
            return response
    
  2. Record a single GET to any endpoint using axios (or any client that sets Accept: application/json, text/plain, */*).
  3. keploy test against the recording.
  4. Observe 500 status, Content-Type: text/plain, body Internal Server Error. The app log shows TypeError: dict() got multiple values for keyword argument 'accept'.

A minimal reproduction with both the buggy and fixed middleware variants is available locally on request — runs in ~10 seconds via Docker.

📜 Logs (if any)

App side (uvicorn fallback page):

[ERROR] Exception in ASGI application
  File ".../glo_fastapi/metrics/middleware.py", line 55, in __call__
    response = Response(headers=dict(**request.headers), status_code=status_code)
TypeError: dict() got multiple values for keyword argument 'accept'

Keploy proxy log showing the wire-level fan-out (Accept is a 3-element slice, Accept-Encoding is 4):

Sending request to user app:&{GET ... HTTP/1.1 1 1
  map[Accept:[application/json  text/plain  */*]
      Accept-Encoding:[gzip  compress  deflate  br]
      ...
🌎 Where it happens

pkg/util.go:206 ToHTTPHeader. The companion ToYamlHTTPHeader (pkg/util.go:153) collapses repeated same-name headers to a single comma-folded string at record time, so the replay-side split is lossy by design — the YAML cannot distinguish "one header with internal commas" from "N repeated headers" and currently always picks the latter on replay.

Expected

Per RFC 7230 §3.2.2, a comma-folded single header is the canonical form for list-valued headers (Accept, Accept-Encoding, Baggage, Forwarded, Via, ...) and is semantically equivalent at the receiver to repeated same-name fields. Replaying the recorded value as one wire header per YAML key matches what most clients (axios, requests, fetch) actually emit and avoids the strict-middleware fan-out crash.

🔗 Fix

PR #4163 (fix(replay): fold comma-separated request headers into a single wire field) — keeps Set-Cookie (a response header, not built by this helper) untouched.

Lingua principale
Go
Stelle
18.5k
Fork
2.4k
Merge medio
19h 24m
PR unite (30g)
71

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di keploy/keploy

Tutte le issue di keploy/keploy

Issue simili

Altre issue su Go

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.