mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-02-04 06:23:45 +00:00
Handle scripts that don't return a 200 status code
This was already being handled for async scripts, but for sync scripts, we'd log the error then proceed to try and execute the body (which would be some error message). This allows the header_callback to return a boolean to indicate whether or not the http client should continue to process the request or abort it.
This commit is contained in:
@@ -590,7 +590,7 @@ fn _documentIsComplete(self: *Page) !void {
|
||||
);
|
||||
}
|
||||
|
||||
fn pageHeaderDoneCallback(transfer: *Http.Transfer) !void {
|
||||
fn pageHeaderDoneCallback(transfer: *Http.Transfer) !bool {
|
||||
var self: *Page = @ptrCast(@alignCast(transfer.ctx));
|
||||
|
||||
// would be different than self.url in the case of a redirect
|
||||
@@ -607,6 +607,8 @@ fn pageHeaderDoneCallback(transfer: *Http.Transfer) !void {
|
||||
.content_type = header.contentType(),
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
fn pageDataCallback(transfer: *Http.Transfer, data: []const u8) !void {
|
||||
|
||||
@@ -663,7 +663,7 @@ pub const Script = struct {
|
||||
log.debug(.http, "script fetch start", .{ .req = transfer });
|
||||
}
|
||||
|
||||
fn headerCallback(transfer: *Http.Transfer) !void {
|
||||
fn headerCallback(transfer: *Http.Transfer) !bool {
|
||||
const self: *Script = @ptrCast(@alignCast(transfer.ctx));
|
||||
const header = &transfer.response_header.?;
|
||||
self.status = header.status;
|
||||
@@ -673,7 +673,7 @@ pub const Script = struct {
|
||||
.status = header.status,
|
||||
.content_type = header.contentType(),
|
||||
});
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (comptime IS_DEBUG) {
|
||||
@@ -694,6 +694,7 @@ pub const Script = struct {
|
||||
try buffer.ensureTotalCapacity(self.manager.allocator, cl);
|
||||
}
|
||||
self.source = .{ .remote = buffer };
|
||||
return true;
|
||||
}
|
||||
|
||||
fn dataCallback(transfer: *Http.Transfer, data: []const u8) !void {
|
||||
@@ -733,7 +734,7 @@ pub const Script = struct {
|
||||
log.warn(.http, "script fetch error", .{
|
||||
.err = err,
|
||||
.req = self.url,
|
||||
.mode = self.mode,
|
||||
.mode = std.meta.activeTag(self.mode),
|
||||
.kind = self.kind,
|
||||
.status = self.status,
|
||||
});
|
||||
@@ -753,9 +754,13 @@ pub const Script = struct {
|
||||
return;
|
||||
}
|
||||
|
||||
if (self.mode == .import) {
|
||||
const entry = self.manager.imported_modules.getPtr(self.url).?;
|
||||
switch (self.mode) {
|
||||
.import_async => |ia| ia.callback(ia.data, error.FailedToLoad),
|
||||
.import => {
|
||||
const entry = manager.imported_modules.getPtr(self.url).?;
|
||||
entry.state = .err;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
self.deinit(true);
|
||||
manager.evaluate();
|
||||
|
||||
@@ -89,7 +89,7 @@ pub fn deinit(self: *Fetch) void {
|
||||
}
|
||||
}
|
||||
|
||||
fn httpHeaderDoneCallback(transfer: *Http.Transfer) !void {
|
||||
fn httpHeaderDoneCallback(transfer: *Http.Transfer) !bool {
|
||||
const self: *Fetch = @ptrCast(@alignCast(transfer.ctx));
|
||||
|
||||
if (transfer.getContentLength()) |cl| {
|
||||
@@ -133,6 +133,8 @@ fn httpHeaderDoneCallback(transfer: *Http.Transfer) !void {
|
||||
while (it.next()) |hdr| {
|
||||
try res._headers.append(hdr.name, hdr.value, self._page);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
fn httpDataCallback(transfer: *Http.Transfer, data: []const u8) !void {
|
||||
|
||||
@@ -290,7 +290,7 @@ fn httpHeaderCallback(transfer: *Http.Transfer, header: Http.Header) !void {
|
||||
try self._response_headers.append(self._arena, joined);
|
||||
}
|
||||
|
||||
fn httpHeaderDoneCallback(transfer: *Http.Transfer) !void {
|
||||
fn httpHeaderDoneCallback(transfer: *Http.Transfer) !bool {
|
||||
const self: *XMLHttpRequest = @ptrCast(@alignCast(transfer.ctx));
|
||||
|
||||
const header = &transfer.response_header.?;
|
||||
@@ -305,7 +305,8 @@ fn httpHeaderDoneCallback(transfer: *Http.Transfer) !void {
|
||||
|
||||
if (header.contentType()) |ct| {
|
||||
self._response_mime = Mime.parse(ct) catch |e| {
|
||||
return self.handleError(e);
|
||||
log.info(.http, "invalid content type", .{.content_Type = ct, .err = e, .url = self._url,});
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -332,6 +333,8 @@ fn httpHeaderDoneCallback(transfer: *Http.Transfer) !void {
|
||||
try self.stateChanged(.headers_received, local, page);
|
||||
try self._proto.dispatch(.load_start, .{ .loaded = 0, .total = self._response_len orelse 0 }, local, page);
|
||||
try self.stateChanged(.loading, local, page);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
fn httpDataCallback(transfer: *Http.Transfer, data: []const u8) !void {
|
||||
|
||||
@@ -594,15 +594,19 @@ fn processMessages(self: *Client) !bool {
|
||||
|
||||
defer transfer.deinit();
|
||||
|
||||
if (errorCheck(msg.data.result)) {
|
||||
if (errorCheck(msg.data.result)) blk: {
|
||||
// In case of request w/o data, we need to call the header done
|
||||
// callback now.
|
||||
if (!transfer._header_done_called) {
|
||||
transfer.headerDoneCallback(easy) catch |err| {
|
||||
const proceed = transfer.headerDoneCallback(easy) catch |err| {
|
||||
log.err(.http, "header_done_callback", .{ .err = err });
|
||||
self.requestFailed(transfer, err);
|
||||
continue;
|
||||
};
|
||||
if (!proceed) {
|
||||
self.requestFailed(transfer, error.Abort);
|
||||
break :blk;
|
||||
}
|
||||
}
|
||||
transfer.req.done_callback(transfer.ctx) catch |err| {
|
||||
// transfer isn't valid at this point, don't use it.
|
||||
@@ -771,7 +775,7 @@ pub const Request = struct {
|
||||
ctx: *anyopaque = undefined,
|
||||
|
||||
start_callback: ?*const fn (transfer: *Transfer) anyerror!void = null,
|
||||
header_callback: *const fn (transfer: *Transfer) anyerror!void,
|
||||
header_callback: *const fn (transfer: *Transfer) anyerror!bool,
|
||||
data_callback: *const fn (transfer: *Transfer, data: []const u8) anyerror!void,
|
||||
done_callback: *const fn (ctx: *anyopaque) anyerror!void,
|
||||
error_callback: *const fn (ctx: *anyopaque, err: anyerror) void,
|
||||
@@ -1042,7 +1046,7 @@ pub const Transfer = struct {
|
||||
// headerDoneCallback is called once the headers have been read.
|
||||
// It can be called either on dataCallback or once the request for those
|
||||
// w/o body.
|
||||
fn headerDoneCallback(transfer: *Transfer, easy: *c.CURL) !void {
|
||||
fn headerDoneCallback(transfer: *Transfer, easy: *c.CURL) !bool {
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(transfer._header_done_called == false);
|
||||
}
|
||||
@@ -1070,7 +1074,7 @@ pub const Transfer = struct {
|
||||
if (i >= ct.?.amount) break;
|
||||
}
|
||||
|
||||
transfer.req.header_callback(transfer) catch |err| {
|
||||
const proceed = transfer.req.header_callback(transfer) catch |err| {
|
||||
log.err(.http, "header_callback", .{ .err = err, .req = transfer });
|
||||
return err;
|
||||
};
|
||||
@@ -1080,6 +1084,8 @@ pub const Transfer = struct {
|
||||
.transfer = transfer,
|
||||
});
|
||||
}
|
||||
|
||||
return proceed;
|
||||
}
|
||||
|
||||
// headerCallback is called by curl on each request's header line read.
|
||||
@@ -1193,7 +1199,7 @@ pub const Transfer = struct {
|
||||
return buf_len;
|
||||
}
|
||||
|
||||
fn dataCallback(buffer: [*]const u8, chunk_count: usize, chunk_len: usize, data: *anyopaque) callconv(.c) usize {
|
||||
fn dataCallback(buffer: [*]const u8, chunk_count: usize, chunk_len: usize, data: *anyopaque) callconv(.c) isize {
|
||||
// libcurl should only ever emit 1 chunk at a time
|
||||
if (comptime IS_DEBUG) {
|
||||
std.debug.assert(chunk_count == 1);
|
||||
@@ -1206,14 +1212,18 @@ pub const Transfer = struct {
|
||||
};
|
||||
|
||||
if (transfer._redirecting or transfer._auth_challenge != null) {
|
||||
return chunk_len;
|
||||
return @intCast(chunk_len);
|
||||
}
|
||||
|
||||
if (!transfer._header_done_called) {
|
||||
transfer.headerDoneCallback(easy) catch |err| {
|
||||
const proceed = transfer.headerDoneCallback(easy) catch |err| {
|
||||
log.err(.http, "header_done_callback", .{ .err = err, .req = transfer });
|
||||
return c.CURL_WRITEFUNC_ERROR;
|
||||
};
|
||||
if (!proceed) {
|
||||
// signal abort to libcurl
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
transfer.bytes_received += chunk_len;
|
||||
@@ -1230,7 +1240,7 @@ pub const Transfer = struct {
|
||||
});
|
||||
}
|
||||
|
||||
return chunk_len;
|
||||
return @intCast(chunk_len);
|
||||
}
|
||||
|
||||
pub fn responseHeaderIterator(self: *Transfer) HeaderIterator {
|
||||
@@ -1288,7 +1298,10 @@ pub const Transfer = struct {
|
||||
}
|
||||
}
|
||||
|
||||
try req.header_callback(transfer);
|
||||
if (try req.header_callback(transfer) == false) {
|
||||
transfer.abort(error.Abort);
|
||||
return;
|
||||
}
|
||||
|
||||
if (body) |b| {
|
||||
try req.data_callback(transfer, b);
|
||||
|
||||
Reference in New Issue
Block a user