@@ -29,6 +29,79 @@ func TestDo(t *testing.T) {
2929 })
3030}
3131
32+ func TestSetCustomHeaders (t * testing.T ) {
33+ h := & HTTPX {Options : & Options {}}
34+
35+ t .Run ("duplicate values preserved in order" , func (t * testing.T ) {
36+ req , err := retryablehttp .NewRequest (http .MethodGet , "https://example.com" , nil )
37+ require .NoError (t , err )
38+ h .SetCustomHeaders (req , map [string ][]string {"X-Test" : {"one" , "two" }})
39+ require .Equal (t , []string {"one" , "two" }, req .Header .Values ("X-Test" ))
40+ })
41+
42+ t .Run ("case-variant duplicates are coalesced" , func (t * testing.T ) {
43+ req , err := retryablehttp .NewRequest (http .MethodGet , "https://example.com" , nil )
44+ require .NoError (t , err )
45+ h .SetCustomHeaders (req , map [string ][]string {"X-Test" : {"one" }, "x-test" : {"two" }})
46+ require .ElementsMatch (t , []string {"one" , "two" }, req .Header .Values ("X-Test" ))
47+ })
48+
49+ t .Run ("custom header replaces existing value" , func (t * testing.T ) {
50+ req , err := retryablehttp .NewRequest (http .MethodGet , "https://example.com" , nil )
51+ require .NoError (t , err )
52+ req .Header .Set ("User-Agent" , "default-agent" )
53+ h .SetCustomHeaders (req , map [string ][]string {"User-Agent" : {"custom-agent" }})
54+ require .Equal (t , []string {"custom-agent" }, req .Header .Values ("User-Agent" ))
55+ })
56+
57+ t .Run ("host header sets request host" , func (t * testing.T ) {
58+ req , err := retryablehttp .NewRequest (http .MethodGet , "https://example.com" , nil )
59+ require .NoError (t , err )
60+ h .SetCustomHeaders (req , map [string ][]string {"Host" : {"custom.host" }})
61+ require .Equal (t , "custom.host" , req .Host )
62+ require .Empty (t , req .Header .Values ("Host" ))
63+ })
64+
65+ t .Run ("multiple distinct headers preserved" , func (t * testing.T ) {
66+ req , err := retryablehttp .NewRequest (http .MethodGet , "https://example.com" , nil )
67+ require .NoError (t , err )
68+ h .SetCustomHeaders (req , map [string ][]string {"X-One" : {"1" }, "X-Two" : {"2" }})
69+ require .Equal (t , []string {"1" }, req .Header .Values ("X-One" ))
70+ require .Equal (t , []string {"2" }, req .Header .Values ("X-Two" ))
71+ })
72+
73+ t .Run ("multiple cookie values preserved" , func (t * testing.T ) {
74+ req , err := retryablehttp .NewRequest (http .MethodGet , "https://example.com" , nil )
75+ require .NoError (t , err )
76+ h .SetCustomHeaders (req , map [string ][]string {"Cookie" : {"a=1" , "b=2" }})
77+ require .Equal (t , []string {"a=1" , "b=2" }, req .Header .Values ("Cookie" ))
78+ })
79+
80+ t .Run ("empty value applied as-is" , func (t * testing.T ) {
81+ req , err := retryablehttp .NewRequest (http .MethodGet , "https://example.com" , nil )
82+ require .NoError (t , err )
83+ h .SetCustomHeaders (req , map [string ][]string {"X-Empty" : {"" }})
84+ require .Equal (t , []string {"" }, req .Header .Values ("X-Empty" ))
85+ })
86+
87+ t .Run ("unsafe raw header line stored verbatim as key" , func (t * testing.T ) {
88+ hu := & HTTPX {Options : & Options {Unsafe : true }}
89+ req , err := retryablehttp .NewRequest (http .MethodGet , "https://example.com" , nil )
90+ require .NoError (t , err )
91+ // in unsafe mode the runner stores the whole raw header line as the key
92+ // with an empty value; it must survive canonicalization untouched
93+ hu .SetCustomHeaders (req , map [string ][]string {"X-Test: one" : {"" }})
94+ require .Equal (t , []string {"" }, req .Header .Values ("X-Test: one" ))
95+ })
96+ }
97+
98+ func TestParseCustomCookies (t * testing.T ) {
99+ options := & Options {CustomHeaders : map [string ][]string {"Cookie" : {"a=1" , "b=2" }}}
100+ options .parseCustomCookies ()
101+ require .True (t , options .hasCustomCookies ())
102+ require .Len (t , options .customCookies , 2 )
103+ }
104+
32105func TestHTTP11DisablesRetryableHTTP2FallbackClient (t * testing.T ) {
33106 options := DefaultOptions
34107 options .Protocol = HTTP11
0 commit comments