mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
Handle when unable to use sendfile() with Bun.file
This commit is contained in:
@@ -303,7 +303,7 @@ pub const HTMLRewriter = struct {
|
||||
defer if (!is_pending) input.detach();
|
||||
|
||||
if (is_pending) {
|
||||
input.doReadFileInternal(*BufferOutputSink, sink, onFinishedLoadingWrap, global);
|
||||
input.doReadFileInternal(*BufferOutputSink, sink, onFinishedLoading, global);
|
||||
} else if (sink.runOutputSink(input.sharedView(), false)) |error_value| {
|
||||
return error_value;
|
||||
}
|
||||
@@ -315,10 +315,6 @@ pub const HTMLRewriter = struct {
|
||||
);
|
||||
}
|
||||
|
||||
pub fn onFinishedLoadingWrap(sink: *anyopaque, bytes: JSC.WebCore.Blob.Store.ReadFile.ResultType) void {
|
||||
onFinishedLoading(bun.cast(*BufferOutputSink, sink), bytes);
|
||||
}
|
||||
|
||||
pub fn onFinishedLoading(sink: *BufferOutputSink, bytes: JSC.WebCore.Blob.Store.ReadFile.ResultType) void {
|
||||
switch (bytes) {
|
||||
.err => |err| {
|
||||
|
||||
@@ -354,6 +354,9 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
|
||||
pub const RequestContextStackAllocator = std.heap.StackFallbackAllocator(@sizeOf(RequestContext) * 2048 + 4096);
|
||||
|
||||
// TODO: support builtin compression
|
||||
const can_sendfile = !ssl_enabled;
|
||||
|
||||
pub threadlocal var pool: *RequestContextStackAllocator = undefined;
|
||||
|
||||
pub fn setAbortHandler(this: *RequestContext) void {
|
||||
@@ -476,7 +479,6 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
if (this.aborted) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.sendWritableBytes(this.fallback_buf.items, write_offset, resp);
|
||||
}
|
||||
|
||||
@@ -657,12 +659,6 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
return this.onSendfile();
|
||||
}
|
||||
|
||||
pub fn onWritablePrepareSendfile(this: *RequestContext, _: c_ulong, _: *App.Response) callconv(.C) bool {
|
||||
this.renderSendFile(this.blob);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn onPrepareSendfileWrap(this: *anyopaque, fd: i32, size: anyerror!Blob.SizeType, _: *JSGlobalObject) void {
|
||||
onPrepareSendfile(bun.cast(*RequestContext, this), fd, size);
|
||||
}
|
||||
@@ -699,10 +695,6 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
}
|
||||
|
||||
pub fn renderSendFile(this: *RequestContext, blob: JSC.WebCore.Blob) void {
|
||||
if (this.has_sendfile_ctx) return;
|
||||
this.has_sendfile_ctx = true;
|
||||
this.setAbortHandler();
|
||||
|
||||
JSC.WebCore.Blob.doOpenAndStatFile(
|
||||
&this.blob,
|
||||
*RequestContext,
|
||||
@@ -712,27 +704,53 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
);
|
||||
}
|
||||
|
||||
pub fn doRender(this: *RequestContext) void {
|
||||
if (this.aborted) {
|
||||
pub fn doSendfile(this: *RequestContext, blob: Blob) void {
|
||||
if (this.has_sendfile_ctx) return;
|
||||
this.has_sendfile_ctx = true;
|
||||
this.setAbortHandler();
|
||||
|
||||
if (comptime can_sendfile) {
|
||||
return this.renderSendFile(blob);
|
||||
}
|
||||
|
||||
this.blob.doReadFileInternal(*RequestContext, this, onReadFile, this.server.globalThis);
|
||||
}
|
||||
|
||||
pub fn onReadFile(this: *RequestContext, result: Blob.Store.ReadFile.ResultType) void {
|
||||
if (result == .err) {
|
||||
this.runErrorHandler(result.err.toErrorInstance(this.server.globalThis));
|
||||
return;
|
||||
}
|
||||
var response = this.response_ptr.?;
|
||||
var body = &response.body;
|
||||
|
||||
switch (body.value) {
|
||||
this.blob.resolveSize();
|
||||
this.doRenderBlob();
|
||||
}
|
||||
|
||||
pub fn doRenderWithBodyLocked(this: *anyopaque, value: *JSC.WebCore.Body.Value) void {
|
||||
doRenderWithBody(bun.cast(*RequestContext, this), value);
|
||||
}
|
||||
|
||||
pub fn doRenderWithBody(this: *RequestContext, value: *JSC.WebCore.Body.Value) void {
|
||||
if (this.aborted) {
|
||||
this.finalize();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (value.*) {
|
||||
.Error => {
|
||||
const err = body.value.Error;
|
||||
_ = response.body.use();
|
||||
const err = value.Error;
|
||||
_ = value.use();
|
||||
this.runErrorHandler(err);
|
||||
return;
|
||||
},
|
||||
.Blob => {
|
||||
this.blob = response.body.use();
|
||||
this.blob = value.use();
|
||||
|
||||
if (this.blob.needsToReadFile()) {
|
||||
this.req.setYield(false);
|
||||
this.setAbortHandler();
|
||||
if (!this.has_sendfile_ctx) this.renderSendFile(this.blob);
|
||||
if (!this.has_sendfile_ctx)
|
||||
this.doSendfile(this.blob);
|
||||
return;
|
||||
}
|
||||
},
|
||||
@@ -742,6 +760,10 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
else => {},
|
||||
}
|
||||
|
||||
this.doRenderBlob();
|
||||
}
|
||||
|
||||
pub fn doRenderBlob(this: *RequestContext) void {
|
||||
if (this.has_abort_handler)
|
||||
this.resp.runCorked(*RequestContext, renderMetadata, this)
|
||||
else
|
||||
@@ -750,6 +772,14 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
this.renderBytes();
|
||||
}
|
||||
|
||||
pub fn doRender(this: *RequestContext) void {
|
||||
if (this.aborted) {
|
||||
return;
|
||||
}
|
||||
var response = this.response_ptr.?;
|
||||
this.doRenderWithBody(&response.body.value);
|
||||
}
|
||||
|
||||
pub fn renderProductionError(this: *RequestContext) void {
|
||||
this.resp.writeStatus("500 Internal Server Error");
|
||||
this.resp.writeHeader("content-type", "text/plain");
|
||||
@@ -851,7 +881,7 @@ fn NewRequestContext(comptime ssl_enabled: bool, comptime debug_mode: bool, comp
|
||||
|
||||
this.resp.writeHeader(
|
||||
"content-disposition",
|
||||
std.fmt.bufPrint(&filename_buf, "filename=\"{s}\"", .{basename}) catch "",
|
||||
std.fmt.bufPrint(&filename_buf, "filename=\"{s}\"", .{basename[0..@minimum(basename.len, 1024 - 32)]}) catch "",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1802,8 +1802,14 @@ pub const Blob = struct {
|
||||
|
||||
bun.default_allocator.destroy(this);
|
||||
|
||||
cb(cb_ctx, .{ .result = bytes });
|
||||
store.deref();
|
||||
// Attempt to free it as soon as possible
|
||||
if (store.ref_count > 1) {
|
||||
store.deref();
|
||||
cb(cb_ctx, .{ .result = bytes });
|
||||
} else {
|
||||
cb(cb_ctx, .{ .result = bytes });
|
||||
store.deref();
|
||||
}
|
||||
}
|
||||
pub fn run(this: *ReadFile, task: *ReadFileTask) void {
|
||||
var frame = HTTPClient.getAllocator().create(@Frame(runAsync)) catch unreachable;
|
||||
@@ -3007,7 +3013,7 @@ pub const Blob = struct {
|
||||
bun.default_allocator,
|
||||
this.store.?,
|
||||
ctx,
|
||||
Function,
|
||||
NewInternalReadFileHandler(Handler, Function).run,
|
||||
this.offset,
|
||||
this.size,
|
||||
) catch unreachable;
|
||||
|
||||
Reference in New Issue
Block a user