Skip to content

Commit 0d0dfd9

Browse files
committed
cookie support
1 parent e116875 commit 0d0dfd9

File tree

7 files changed

+137
-47
lines changed

7 files changed

+137
-47
lines changed

src/browser/ScriptManager.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ pub fn addFromElement(self: *ScriptManager, element: *parser.Element) !void {
222222
.url = remote_url.?,
223223
.ctx = pending_script,
224224
.method = .GET,
225+
.cookie = page.requestCookie(.{}),
225226
.start_callback = if (log.enabled(.http, .debug)) startCallback else null,
226227
.header_done_callback = headerCallback,
227228
.data_callback = dataCallback,
@@ -274,6 +275,7 @@ pub fn blockingGet(self: *ScriptManager, url: [:0]const u8) !BlockingResult {
274275
.url = url,
275276
.method = .GET,
276277
.ctx = &blocking,
278+
.cookie = self.page.requestCookie(.{}),
277279
.start_callback = if (log.enabled(.http, .debug)) Blocking.startCallback else null,
278280
.header_done_callback = Blocking.headerCallback,
279281
.data_callback = Blocking.dataCallback,

src/browser/html/document.zig

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,10 @@ pub const HTMLDocument = struct {
8585

8686
pub fn get_cookie(_: *parser.DocumentHTML, page: *Page) ![]const u8 {
8787
var buf: std.ArrayListUnmanaged(u8) = .{};
88-
try page.cookie_jar.forRequest(&page.url.uri, buf.writer(page.arena), .{ .navigation = true, .is_http = false });
88+
try page.cookie_jar.forRequest(&page.url.uri, buf.writer(page.arena), .{
89+
.is_http = false,
90+
.is_navigation = true,
91+
});
8992
return buf.items;
9093
}
9194

src/browser/page.zig

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,19 @@ pub const Page = struct {
392392
return arr.items;
393393
}
394394

395+
const RequestCookieOpts = struct {
396+
is_http: bool = true,
397+
is_navigation: bool = false,
398+
};
399+
pub fn requestCookie(self: *const Page, opts: RequestCookieOpts) HttpClient.RequestCookie {
400+
return .{
401+
.jar = self.cookie_jar,
402+
.origin = &self.url.uri,
403+
.is_http = opts.is_http,
404+
.is_navigation = opts.is_navigation,
405+
};
406+
}
407+
395408
// spec reference: https://html.spec.whatwg.org/#document-lifecycle
396409
pub fn navigate(self: *Page, request_url: []const u8, opts: NavigateOpts) !void {
397410
if (self.mode != .pre) {
@@ -419,17 +432,22 @@ pub const Page = struct {
419432
}
420433

421434
const owned_url = try self.arena.dupeZ(u8, request_url);
435+
self.url = try URL.parse(owned_url, null);
422436

423-
try self.http_client.request(.{
437+
self.http_client.request(.{
424438
.ctx = self,
425439
.url = owned_url,
426440
.method = opts.method,
427441
.body = opts.body,
442+
.cookie = self.requestCookie(.{ .is_navigation = true }),
428443
.header_done_callback = pageHeaderDoneCallback,
429444
.data_callback = pageDataCallback,
430445
.done_callback = pageDoneCallback,
431446
.error_callback = pageErrorCallback,
432-
});
447+
}) catch |err| {
448+
log.err(.http, "navigate request", .{ .url = owned_url, .err = err });
449+
return err;
450+
};
433451

434452
self.session.browser.notification.dispatch(.page_navigate, &.{
435453
.opts = opts,

src/browser/storage/cookie.zig

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ const public_suffix_list = @import("../../data/public_suffix_list.zig").lookup;
1010
pub const LookupOpts = struct {
1111
request_time: ?i64 = null,
1212
origin_uri: ?*const Uri = null,
13-
navigation: bool = true,
1413
is_http: bool,
14+
is_navigation: bool = true,
1515
};
1616

1717
pub const Jar = struct {
@@ -91,7 +91,7 @@ pub const Jar = struct {
9191

9292
var first = true;
9393
for (self.cookies.items) |*cookie| {
94-
if (!cookie.appliesTo(&target, same_site, opts.navigation, opts.is_http)) continue;
94+
if (!cookie.appliesTo(&target, same_site, opts.is_navigation, opts.is_http)) continue;
9595

9696
// we have a match!
9797
if (first) {
@@ -103,18 +103,15 @@ pub const Jar = struct {
103103
}
104104
}
105105

106-
// @newhttp
107-
// pub fn populateFromResponse(self: *Jar, uri: *const Uri, header: *const http.ResponseHeader) !void {
108-
// const now = std.time.timestamp();
109-
// var it = header.iterate("set-cookie");
110-
// while (it.next()) |set_cookie| {
111-
// const c = Cookie.parse(self.allocator, uri, set_cookie) catch |err| {
112-
// log.warn(.web_api, "cookie parse failed", .{ .raw = set_cookie, .err = err });
113-
// continue;
114-
// };
115-
// try self.add(c, now);
116-
// }
117-
// }
106+
pub fn populateFromResponse(self: *Jar, uri: *const Uri, set_cookie: []const u8) !void {
107+
const c = Cookie.parse(self.allocator, uri, set_cookie) catch |err| {
108+
log.warn(.web_api, "cookie parse failed", .{ .raw = set_cookie, .err = err });
109+
return;
110+
};
111+
112+
const now = std.time.timestamp();
113+
try self.add(c, now);
114+
}
118115

119116
fn writeCookie(cookie: *const Cookie, writer: anytype) !void {
120117
if (cookie.name.len > 0) {
@@ -429,7 +426,7 @@ pub const Cookie = struct {
429426
return .{ name, value, rest };
430427
}
431428

432-
pub fn appliesTo(self: *const Cookie, url: *const PreparedUri, same_site: bool, navigation: bool, is_http: bool) bool {
429+
pub fn appliesTo(self: *const Cookie, url: *const PreparedUri, same_site: bool, is_navigation: bool, is_http: bool) bool {
433430
if (self.http_only and is_http == false) {
434431
// http only cookies can be accessed from Javascript
435432
return false;
@@ -448,7 +445,7 @@ pub const Cookie = struct {
448445
// and cookie.same_site == .lax
449446
switch (self.same_site) {
450447
.strict => return false,
451-
.lax => if (navigation == false) return false,
448+
.lax => if (is_navigation == false) return false,
452449
.none => {},
453450
}
454451
}
@@ -619,7 +616,7 @@ test "Jar: forRequest" {
619616

620617
// nothing fancy here
621618
try expectCookies("global1=1; global2=2", &jar, test_uri, .{ .is_http = true });
622-
try expectCookies("global1=1; global2=2", &jar, test_uri, .{ .origin_uri = &test_uri, .navigation = false, .is_http = true });
619+
try expectCookies("global1=1; global2=2", &jar, test_uri, .{ .origin_uri = &test_uri, .is_navigation = false, .is_http = true });
623620

624621
// We have a cookie where Domain=lightpanda.io
625622
// This should _not_ match xyxlightpanda.io
@@ -685,22 +682,22 @@ test "Jar: forRequest" {
685682
// non-navigational cross domain, insecure
686683
try expectCookies("", &jar, try std.Uri.parse("http://lightpanda.io/x/"), .{
687684
.origin_uri = &(try std.Uri.parse("https://example.com/")),
688-
.navigation = false,
689685
.is_http = true,
686+
.is_navigation = false,
690687
});
691688

692689
// non-navigational cross domain, secure
693690
try expectCookies("sitenone=6", &jar, try std.Uri.parse("https://lightpanda.io/x/"), .{
694691
.origin_uri = &(try std.Uri.parse("https://example.com/")),
695-
.navigation = false,
696692
.is_http = true,
693+
.is_navigation = false,
697694
});
698695

699696
// non-navigational same origin
700697
try expectCookies("global1=1; global2=2; sitelax=7; sitestrict=8", &jar, try std.Uri.parse("http://lightpanda.io/x/"), .{
701698
.origin_uri = &(try std.Uri.parse("https://lightpanda.io/")),
702-
.navigation = false,
703699
.is_http = true,
700+
.is_navigation = false,
704701
});
705702

706703
// exact domain match + suffix

src/browser/xhr/xhr.zig

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ pub const XMLHttpRequest = struct {
8181
proto: XMLHttpRequestEventTarget = XMLHttpRequestEventTarget{},
8282
arena: Allocator,
8383
transfer: ?*HttpClient.Transfer = null,
84-
cookie_jar: *CookieJar,
8584
err: ?anyerror = null,
8685
last_dispatch: i64 = 0,
8786
send_flag: bool = false,
@@ -169,7 +168,6 @@ pub const XMLHttpRequest = struct {
169168
.headers = .{},
170169
.method = undefined,
171170
.state = .unsent,
172-
.cookie_jar = page.cookie_jar,
173171
};
174172
}
175173

@@ -378,6 +376,7 @@ pub const XMLHttpRequest = struct {
378376
.method = self.method,
379377
.body = self.request_body,
380378
.content_type = "Content-Type: text/plain; charset=UTF-8", // @newhttp TODO
379+
.cookie = page.requestCookie(.{}),
381380
.start_callback = httpStartCallback,
382381
.header_callback = httpHeaderCallback,
383382
.header_done_callback = httpHeaderDoneCallback,
@@ -395,20 +394,6 @@ pub const XMLHttpRequest = struct {
395394
}
396395

397396
log.debug(.http, "request start", .{ .method = self.method, .url = self.url, .source = "xhr" });
398-
399-
// @newhttp
400-
// {
401-
// var arr: std.ArrayListUnmanaged(u8) = .{};
402-
// try self.cookie_jar.forRequest(&self.url.?.uri, arr.writer(self.arena), .{
403-
// .navigation = false,
404-
// .origin_uri = &self.origin_url.uri,
405-
// .is_http = true,
406-
// });
407-
408-
// if (arr.items.len > 0) {
409-
// try request.addHeader("Cookie", arr.items, .{});
410-
// }
411-
// }
412397
self.transfer = transfer;
413398
}
414399

@@ -445,9 +430,6 @@ pub const XMLHttpRequest = struct {
445430

446431
self.state = .loading;
447432
self.dispatchEvt("readystatechange");
448-
449-
// @newhttp
450-
// try self.cookie_jar.populateFromResponse(self.request.?.request_uri, &header);
451433
}
452434

453435
fn httpDataCallback(transfer: *HttpClient.Transfer, data: []const u8) !void {

src/data/public_suffix_list.zig

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ pub fn lookup(value: []const u8) bool {
88
const public_suffix_list = std.StaticStringMap(void).initComptime(entries);
99

1010
const entries: []const struct { []const u8, void } =
11-
// @newhttp
12-
if (builtin.is_test or true) &.{
11+
if (builtin.is_test) &.{
1312
.{ "api.gov.uk", {} },
1413
.{ "gov.uk", {} },
1514
} else &.{

0 commit comments

Comments
 (0)