Skip to content

Commit d9ed4cf

Browse files
authored
Merge pull request #940 from lightpanda-io/redirect-cookies
enable curl cookie engine
2 parents 6a29d67 + 7d0e4b6 commit d9ed4cf

File tree

2 files changed

+56
-15
lines changed

2 files changed

+56
-15
lines changed

src/http/Client.zig

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,14 @@ fn makeRequest(self: *Client, handle: *Handle, transfer: *Transfer) !void {
319319
var header_list = req.headers;
320320
try conn.secretHeaders(&header_list); // Add headers that must be hidden from intercepts
321321
try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_HTTPHEADER, header_list.headers));
322+
323+
// Add cookies.
324+
// Clear cookies from Curl's engine.
325+
try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_COOKIELIST, "ALL"));
326+
if (header_list.cookies) |cookies| {
327+
try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_COOKIE, cookies));
328+
}
329+
322330
try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_PRIVATE, transfer));
323331
}
324332

@@ -506,12 +514,11 @@ pub const RequestCookie = struct {
506514
.is_http = self.is_http,
507515
.is_navigation = self.is_navigation,
508516
.origin_uri = self.origin,
509-
.prefix = "Cookie: ",
510517
});
511518

512519
if (arr.items.len > 0) {
513520
try arr.append(temp, 0); //null terminate
514-
try headers.add(@ptrCast(arr.items.ptr));
521+
headers.cookies = @ptrCast(arr.items.ptr);
515522
}
516523
}
517524
};
@@ -603,6 +610,22 @@ pub const Transfer = struct {
603610
const header = buffer[0 .. buf_len - 2];
604611

605612
if (transfer.response_header == null) {
613+
if (transfer._redirecting and buf_len == 2) {
614+
// retrieve cookies from the redirect's response.
615+
var i: usize = 0;
616+
while (true) {
617+
const ct = getResponseHeader(easy, "set-cookie", i);
618+
if (ct == null) break;
619+
transfer.req.cookie_jar.populateFromResponse(&transfer.uri, ct.?.value) catch |err| {
620+
log.err(.http, "set cookie", .{ .err = err, .req = transfer });
621+
};
622+
i += 1;
623+
if (i >= ct.?.amount) break;
624+
}
625+
626+
return buf_len;
627+
}
628+
606629
if (buf_len < 13 or std.mem.startsWith(u8, header, "HTTP/") == false) {
607630
if (transfer._redirecting) {
608631
return buf_len;
@@ -641,18 +664,6 @@ pub const Transfer = struct {
641664
return buf_len;
642665
}
643666

644-
{
645-
const SET_COOKIE_LEN = "set-cookie:".len;
646-
if (header.len > SET_COOKIE_LEN) {
647-
if (std.ascii.eqlIgnoreCase(header[0..SET_COOKIE_LEN], "set-cookie:")) {
648-
const value = std.mem.trimLeft(u8, header[SET_COOKIE_LEN..], " ");
649-
transfer.req.cookie_jar.populateFromResponse(&transfer.uri, value) catch |err| {
650-
log.err(.http, "set cookie", .{ .err = err, .req = transfer });
651-
};
652-
}
653-
}
654-
}
655-
656667
if (buf_len == 2) {
657668
if (getResponseHeader(easy, "content-type", 0)) |ct| {
658669
var hdr = &transfer.response_header.?;
@@ -662,6 +673,17 @@ pub const Transfer = struct {
662673
@memcpy(hdr._content_type[0..len], value[0..len]);
663674
}
664675

676+
var i: usize = 0;
677+
while (true) {
678+
const ct = getResponseHeader(easy, "set-cookie", i);
679+
if (ct == null) break;
680+
transfer.req.cookie_jar.populateFromResponse(&transfer.uri, ct.?.value) catch |err| {
681+
log.err(.http, "set cookie", .{ .err = err, .req = transfer });
682+
};
683+
i += 1;
684+
if (i >= ct.?.amount) break;
685+
}
686+
665687
transfer.req.header_done_callback(transfer) catch |err| {
666688
log.err(.http, "header_done_callback", .{ .err = err, .req = transfer });
667689
// returning < buf_len terminates the request

src/http/Http.zig

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ pub const Connection = struct {
110110
try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_FOLLOWLOCATION, @as(c_long, 2)));
111111
try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_REDIR_PROTOCOLS_STR, "HTTP,HTTPS")); // remove FTP and FTPS from the default
112112

113+
// enable cookie engine for redirections handled directly by Curl.
114+
try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_COOKIEFILE, ""));
115+
113116
// proxy
114117
if (opts.http_proxy) |proxy| {
115118
try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_PROXY, proxy.ptr));
@@ -201,6 +204,13 @@ pub const Connection = struct {
201204
try self.secretHeaders(&header_list);
202205
try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_HTTPHEADER, header_list.headers));
203206

207+
// Add cookies.
208+
// Clear cookies from Curl's engine.
209+
try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_COOKIELIST, "ALL"));
210+
if (header_list.cookies) |cookies| {
211+
try errorCheck(c.curl_easy_setopt(easy, c.CURLOPT_COOKIE, cookies));
212+
}
213+
204214
try errorCheck(c.curl_easy_perform(easy));
205215
var http_code: c_long = undefined;
206216
try errorCheck(c.curl_easy_getinfo(easy, c.CURLINFO_RESPONSE_CODE, &http_code));
@@ -213,11 +223,12 @@ pub const Connection = struct {
213223

214224
pub const Headers = struct {
215225
headers: *c.curl_slist,
226+
cookies: ?[*c]const u8,
216227

217228
pub fn init() !Headers {
218229
const header_list = c.curl_slist_append(null, "User-Agent: Lightpanda/1.0");
219230
if (header_list == null) return error.OutOfMemory;
220-
return .{ .headers = header_list };
231+
return .{ .headers = header_list, .cookies = null };
221232
}
222233

223234
pub fn deinit(self: *const Headers) void {
@@ -242,6 +253,10 @@ pub const Headers = struct {
242253
list.putAssumeCapacity(header.name, header.value);
243254
current = node.*.next;
244255
}
256+
// special case for cookies
257+
if (self.cookies) |v| {
258+
list.putAssumeCapacity("Cookie", std.mem.span(@as([*:0]const u8, @ptrCast(v))));
259+
}
245260
return list;
246261
}
247262

@@ -261,6 +276,10 @@ pub const Headers = struct {
261276
num += 1;
262277
current = node.*.next;
263278
}
279+
// special case for cookies
280+
if (self.cookies != null) {
281+
num += 1;
282+
}
264283
return num;
265284
}
266285
};

0 commit comments

Comments
 (0)