diff options
author | 2022-04-03 21:23:10 -0700 | |
---|---|---|
committer | 2022-04-03 21:23:10 -0700 | |
commit | b069ff253e6fda72103646924fa052d4d051d5aa (patch) | |
tree | 7f1fa711a6bb6664e73006aa6688e7e63024fe80 | |
parent | abc15f4d304e74fbc400b069e40b187614674934 (diff) | |
download | bun-b069ff253e6fda72103646924fa052d4d051d5aa.tar.gz bun-b069ff253e6fda72103646924fa052d4d051d5aa.tar.zst bun-b069ff253e6fda72103646924fa052d4d051d5aa.zip |
Handle when unable to use sendfile() with `Bun.file`
-rw-r--r-- | src/javascript/jsc/api/html_rewriter.zig | 6 | ||||
-rw-r--r-- | src/javascript/jsc/api/server.zig | 70 | ||||
-rw-r--r-- | src/javascript/jsc/webcore/response.zig | 12 |
3 files changed, 60 insertions, 28 deletions
diff --git a/src/javascript/jsc/api/html_rewriter.zig b/src/javascript/jsc/api/html_rewriter.zig index ac6190f7e..7d8ef2abf 100644 --- a/src/javascript/jsc/api/html_rewriter.zig +++ b/src/javascript/jsc/api/html_rewriter.zig @@ -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| { diff --git a/src/javascript/jsc/api/server.zig b/src/javascript/jsc/api/server.zig index 271f25cf3..4a57c927f 100644 --- a/src/javascript/jsc/api/server.zig +++ b/src/javascript/jsc/api/server.zig @@ -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 { + 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; + } + + 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; } - var response = this.response_ptr.?; - var body = &response.body; - switch (body.value) { + 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 "", ); } } diff --git a/src/javascript/jsc/webcore/response.zig b/src/javascript/jsc/webcore/response.zig index af0f244dc..b20d1319c 100644 --- a/src/javascript/jsc/webcore/response.zig +++ b/src/javascript/jsc/webcore/response.zig @@ -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; |