mirror of
https://github.com/lightpanda-io/browser.git
synced 2026-02-04 14:33:47 +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));
|
var self: *Page = @ptrCast(@alignCast(transfer.ctx));
|
||||||
|
|
||||||
// would be different than self.url in the case of a redirect
|
// 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(),
|
.content_type = header.contentType(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pageDataCallback(transfer: *Http.Transfer, data: []const u8) !void {
|
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 });
|
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 self: *Script = @ptrCast(@alignCast(transfer.ctx));
|
||||||
const header = &transfer.response_header.?;
|
const header = &transfer.response_header.?;
|
||||||
self.status = header.status;
|
self.status = header.status;
|
||||||
@@ -673,7 +673,7 @@ pub const Script = struct {
|
|||||||
.status = header.status,
|
.status = header.status,
|
||||||
.content_type = header.contentType(),
|
.content_type = header.contentType(),
|
||||||
});
|
});
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comptime IS_DEBUG) {
|
if (comptime IS_DEBUG) {
|
||||||
@@ -694,6 +694,7 @@ pub const Script = struct {
|
|||||||
try buffer.ensureTotalCapacity(self.manager.allocator, cl);
|
try buffer.ensureTotalCapacity(self.manager.allocator, cl);
|
||||||
}
|
}
|
||||||
self.source = .{ .remote = buffer };
|
self.source = .{ .remote = buffer };
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dataCallback(transfer: *Http.Transfer, data: []const u8) !void {
|
fn dataCallback(transfer: *Http.Transfer, data: []const u8) !void {
|
||||||
@@ -733,7 +734,7 @@ pub const Script = struct {
|
|||||||
log.warn(.http, "script fetch error", .{
|
log.warn(.http, "script fetch error", .{
|
||||||
.err = err,
|
.err = err,
|
||||||
.req = self.url,
|
.req = self.url,
|
||||||
.mode = self.mode,
|
.mode = std.meta.activeTag(self.mode),
|
||||||
.kind = self.kind,
|
.kind = self.kind,
|
||||||
.status = self.status,
|
.status = self.status,
|
||||||
});
|
});
|
||||||
@@ -753,9 +754,13 @@ pub const Script = struct {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.mode == .import) {
|
switch (self.mode) {
|
||||||
const entry = self.manager.imported_modules.getPtr(self.url).?;
|
.import_async => |ia| ia.callback(ia.data, error.FailedToLoad),
|
||||||
entry.state = .err;
|
.import => {
|
||||||
|
const entry = manager.imported_modules.getPtr(self.url).?;
|
||||||
|
entry.state = .err;
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
}
|
}
|
||||||
self.deinit(true);
|
self.deinit(true);
|
||||||
manager.evaluate();
|
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));
|
const self: *Fetch = @ptrCast(@alignCast(transfer.ctx));
|
||||||
|
|
||||||
if (transfer.getContentLength()) |cl| {
|
if (transfer.getContentLength()) |cl| {
|
||||||
@@ -133,6 +133,8 @@ fn httpHeaderDoneCallback(transfer: *Http.Transfer) !void {
|
|||||||
while (it.next()) |hdr| {
|
while (it.next()) |hdr| {
|
||||||
try res._headers.append(hdr.name, hdr.value, self._page);
|
try res._headers.append(hdr.name, hdr.value, self._page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn httpDataCallback(transfer: *Http.Transfer, data: []const u8) !void {
|
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);
|
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 self: *XMLHttpRequest = @ptrCast(@alignCast(transfer.ctx));
|
||||||
|
|
||||||
const header = &transfer.response_header.?;
|
const header = &transfer.response_header.?;
|
||||||
@@ -305,7 +305,8 @@ fn httpHeaderDoneCallback(transfer: *Http.Transfer) !void {
|
|||||||
|
|
||||||
if (header.contentType()) |ct| {
|
if (header.contentType()) |ct| {
|
||||||
self._response_mime = Mime.parse(ct) catch |e| {
|
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.stateChanged(.headers_received, local, page);
|
||||||
try self._proto.dispatch(.load_start, .{ .loaded = 0, .total = self._response_len orelse 0 }, local, page);
|
try self._proto.dispatch(.load_start, .{ .loaded = 0, .total = self._response_len orelse 0 }, local, page);
|
||||||
try self.stateChanged(.loading, local, page);
|
try self.stateChanged(.loading, local, page);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn httpDataCallback(transfer: *Http.Transfer, data: []const u8) !void {
|
fn httpDataCallback(transfer: *Http.Transfer, data: []const u8) !void {
|
||||||
|
|||||||
@@ -594,15 +594,19 @@ fn processMessages(self: *Client) !bool {
|
|||||||
|
|
||||||
defer transfer.deinit();
|
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
|
// In case of request w/o data, we need to call the header done
|
||||||
// callback now.
|
// callback now.
|
||||||
if (!transfer._header_done_called) {
|
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 });
|
log.err(.http, "header_done_callback", .{ .err = err });
|
||||||
self.requestFailed(transfer, err);
|
self.requestFailed(transfer, err);
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
if (!proceed) {
|
||||||
|
self.requestFailed(transfer, error.Abort);
|
||||||
|
break :blk;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
transfer.req.done_callback(transfer.ctx) catch |err| {
|
transfer.req.done_callback(transfer.ctx) catch |err| {
|
||||||
// transfer isn't valid at this point, don't use it.
|
// transfer isn't valid at this point, don't use it.
|
||||||
@@ -771,7 +775,7 @@ pub const Request = struct {
|
|||||||
ctx: *anyopaque = undefined,
|
ctx: *anyopaque = undefined,
|
||||||
|
|
||||||
start_callback: ?*const fn (transfer: *Transfer) anyerror!void = null,
|
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,
|
data_callback: *const fn (transfer: *Transfer, data: []const u8) anyerror!void,
|
||||||
done_callback: *const fn (ctx: *anyopaque) anyerror!void,
|
done_callback: *const fn (ctx: *anyopaque) anyerror!void,
|
||||||
error_callback: *const fn (ctx: *anyopaque, err: 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.
|
// headerDoneCallback is called once the headers have been read.
|
||||||
// It can be called either on dataCallback or once the request for those
|
// It can be called either on dataCallback or once the request for those
|
||||||
// w/o body.
|
// w/o body.
|
||||||
fn headerDoneCallback(transfer: *Transfer, easy: *c.CURL) !void {
|
fn headerDoneCallback(transfer: *Transfer, easy: *c.CURL) !bool {
|
||||||
if (comptime IS_DEBUG) {
|
if (comptime IS_DEBUG) {
|
||||||
std.debug.assert(transfer._header_done_called == false);
|
std.debug.assert(transfer._header_done_called == false);
|
||||||
}
|
}
|
||||||
@@ -1070,7 +1074,7 @@ pub const Transfer = struct {
|
|||||||
if (i >= ct.?.amount) break;
|
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 });
|
log.err(.http, "header_callback", .{ .err = err, .req = transfer });
|
||||||
return err;
|
return err;
|
||||||
};
|
};
|
||||||
@@ -1080,6 +1084,8 @@ pub const Transfer = struct {
|
|||||||
.transfer = transfer,
|
.transfer = transfer,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return proceed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// headerCallback is called by curl on each request's header line read.
|
// headerCallback is called by curl on each request's header line read.
|
||||||
@@ -1193,7 +1199,7 @@ pub const Transfer = struct {
|
|||||||
return buf_len;
|
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
|
// libcurl should only ever emit 1 chunk at a time
|
||||||
if (comptime IS_DEBUG) {
|
if (comptime IS_DEBUG) {
|
||||||
std.debug.assert(chunk_count == 1);
|
std.debug.assert(chunk_count == 1);
|
||||||
@@ -1206,14 +1212,18 @@ pub const Transfer = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (transfer._redirecting or transfer._auth_challenge != null) {
|
if (transfer._redirecting or transfer._auth_challenge != null) {
|
||||||
return chunk_len;
|
return @intCast(chunk_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!transfer._header_done_called) {
|
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 });
|
log.err(.http, "header_done_callback", .{ .err = err, .req = transfer });
|
||||||
return c.CURL_WRITEFUNC_ERROR;
|
return c.CURL_WRITEFUNC_ERROR;
|
||||||
};
|
};
|
||||||
|
if (!proceed) {
|
||||||
|
// signal abort to libcurl
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
transfer.bytes_received += chunk_len;
|
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 {
|
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| {
|
if (body) |b| {
|
||||||
try req.data_callback(transfer, b);
|
try req.data_callback(transfer, b);
|
||||||
|
|||||||
Reference in New Issue
Block a user