@@ -185,20 +185,20 @@ pub const Connection = struct {
185185 try errorCheck (c .curl_easy_setopt (easy , c .CURLOPT_POSTFIELDS , body .ptr ));
186186 }
187187
188- pub fn commonHeaders ( self : * const Connection ) * c.curl_slist {
189- var header_list = c . curl_slist_append ( null , "User-Agent: Lightpanda/1.0" );
188+ // These are headers that may not be send to the users for inteception.
189+ pub fn secretHeaders ( self : * const Connection , headers : * Headers ) ! void {
190190 if (self .opts .proxy_bearer_token ) | hdr | {
191- header_list = c . curl_slist_append ( header_list , hdr );
191+ try headers . add ( hdr );
192192 }
193- return header_list ;
194193 }
195194
196195 pub fn request (self : * const Connection ) ! u16 {
197196 const easy = self .easy ;
198197
199- const header_list = self .commonHeaders ();
200- defer c .curl_slist_free_all (header_list );
201- try errorCheck (c .curl_easy_setopt (easy , c .CURLOPT_HTTPHEADER , header_list ));
198+ const header_list = try Headers .init ();
199+ defer header_list .deinit ();
200+ try self .secretHeaders (& header_list );
201+ try errorCheck (c .curl_easy_setopt (easy , c .CURLOPT_HTTPHEADER , header_list .headers ));
202202
203203 try errorCheck (c .curl_easy_perform (easy ));
204204 var http_code : c_long = undefined ;
@@ -210,6 +210,59 @@ pub const Connection = struct {
210210 }
211211};
212212
213+ pub const Headers = struct {
214+ headers : * c.curl_slist ,
215+
216+ pub fn init () ! Headers {
217+ const header_list = c .curl_slist_append (null , "User-Agent: Lightpanda/1.0" );
218+ if (header_list == null ) return error .OutOfMemory ;
219+ return .{ .headers = header_list };
220+ }
221+
222+ pub fn deinit (self : * Headers ) void {
223+ c .curl_slist_free_all (self .headers );
224+ }
225+
226+ pub fn add (self : * Headers , header : [* c ]const u8 ) ! void {
227+ const updated_headers = c .curl_slist_append (self .headers , header );
228+ if (updated_headers == null ) return error .OutOfMemory ;
229+ self .headers = updated_headers ;
230+ }
231+
232+ pub fn asHashMap (self : * const Headers , allocator : Allocator ) ! std. StringArrayHashMapUnmanaged ([]const u8 ) {
233+ var list : std .StringArrayHashMapUnmanaged ([]const u8 ) = .empty ;
234+ try list .ensureTotalCapacity (allocator , self .count ());
235+
236+ var current : [* c ]c.curl_slist = self .headers ;
237+ while (current ) | node | {
238+ const str = std .mem .span (@as ([* :0 ]const u8 , @ptrCast (node .* .data )));
239+ const header = parseHeader (str ) orelse return error .InvalidHeader ;
240+ list .putAssumeCapacity (header .name , header .value );
241+ current = node .* .next ;
242+ }
243+ return list ;
244+ }
245+
246+ fn parseHeader (header_str : []const u8 ) ? struct { name : []const u8 , value : []const u8 } {
247+ const colon_pos = std .mem .indexOf (u8 , header_str , ":" ) orelse return null ;
248+
249+ const name = std .mem .trim (u8 , header_str [0.. colon_pos ], " \t " );
250+ const value = std .mem .trim (u8 , header_str [colon_pos + 1 .. ], " \t " );
251+
252+ return .{ .name = name , .value = value };
253+ }
254+
255+ pub fn count (self : * const Headers ) usize {
256+ var current : [* c ]c.curl_slist = self .headers ;
257+ var num : usize = 0 ;
258+ while (current ) | node | {
259+ num += 1 ;
260+ current = node .* .next ;
261+ }
262+ return num ;
263+ }
264+ };
265+
213266pub fn errorCheck (code : c.CURLcode ) errors.Error ! void {
214267 if (code == c .CURLE_OK ) {
215268 return ;
0 commit comments