diff options
Diffstat (limited to 'src/bun.js/api/server.zig')
-rw-r--r-- | src/bun.js/api/server.zig | 285 |
1 files changed, 215 insertions, 70 deletions
diff --git a/src/bun.js/api/server.zig b/src/bun.js/api/server.zig index 762d35bb6..823456777 100644 --- a/src/bun.js/api/server.zig +++ b/src/bun.js/api/server.zig @@ -91,6 +91,34 @@ const SendfileContext = struct { const DateTime = bun.DateTime; const linux = std.os.linux; +const BlobFileContentResult = struct { + data: [:0]const u8, + fn init(comptime fieldname: []const u8, js_obj: JSC.JSValue, global: *JSC.JSGlobalObject, exception: JSC.C.ExceptionRef) ?BlobFileContentResult { + if (JSC.WebCore.Body.Value.fromJS(global, js_obj)) |body| { + if (body == .Blob and body.Blob.store != null and body.Blob.store.?.data == .file) { + var fs: JSC.Node.NodeFS = .{}; + const read = fs.readFileWithOptions(.{ .path = body.Blob.store.?.data.file.pathlike }, .sync, .null_terminated); + switch (read) { + .err => { + global.throwValue(read.err.toJSC(global)); + return .{ .data = "" }; + }, + else => { + const str = read.result.null_terminated; + if (str.len > 0) { + return .{ .data = str }; + } + JSC.throwInvalidArguments(std.fmt.comptimePrint("Invalid {s} file", .{fieldname}), .{}, global, exception); + return .{ .data = str }; + }, + } + } + } + + return null; + } +}; + pub const ServerConfig = struct { port: u16 = 0, hostname: [*:0]const u8 = "localhost", @@ -276,8 +304,20 @@ pub const ServerConfig = struct { valid_count += 1; any = true; } + } else if (BlobFileContentResult.init("key", item, global, exception)) |content| { + if (content.data.len > 0) { + native_array[valid_count] = content.data.ptr; + valid_count += 1; + any = true; + } else { + arena.deinit(); + // mark and free all CA's + result.cert = native_array; + result.deinit(); + return null; + } } else { - global.throwInvalidArguments("key argument must be an array containing string, Buffer or TypedArray", .{}); + global.throwInvalidArguments("key argument must be an string, Buffer, TypedArray, BunFile or an array containing string, Buffer, TypedArray or BunFile", .{}); arena.deinit(); // mark and free all keys result.key = native_array; @@ -296,10 +336,40 @@ pub const ServerConfig = struct { result.key_count = valid_count; } + } else if (BlobFileContentResult.init("key", js_obj, global, exception)) |content| { + if (content.data.len > 0) { + const native_array = bun.default_allocator.alloc([*c]const u8, 1) catch unreachable; + native_array[0] = content.data.ptr; + result.key = native_array; + result.key_count = 1; + any = true; + } else { + result.deinit(); + return null; + } } else { - global.throwInvalidArguments("key argument must be an array containing string, Buffer or TypedArray", .{}); - result.deinit(); - return null; + const native_array = bun.default_allocator.alloc([*c]const u8, 1) catch unreachable; + var arena: std.heap.ArenaAllocator = std.heap.ArenaAllocator.init(bun.default_allocator); + if (JSC.Node.StringOrBuffer.fromJS(global, arena.allocator(), js_obj, exception)) |sb| { + const sliced = sb.slice(); + if (sliced.len > 0) { + native_array[0] = bun.default_allocator.dupeZ(u8, sliced) catch unreachable; + any = true; + result.key = native_array; + result.key_count = 1; + } else { + bun.default_allocator.free(native_array); + } + } else { + global.throwInvalidArguments("key argument must be an string, Buffer, TypedArray, BunFile or an array containing string, Buffer, TypedArray or BunFile", .{}); + arena.deinit(); + // mark and free all certs + result.key = native_array; + result.deinit(); + return null; + } + + arena.deinit(); } } @@ -336,8 +406,20 @@ pub const ServerConfig = struct { valid_count += 1; any = true; } + } else if (BlobFileContentResult.init("cert", item, global, exception)) |content| { + if (content.data.len > 0) { + native_array[valid_count] = content.data.ptr; + valid_count += 1; + any = true; + } else { + arena.deinit(); + // mark and free all CA's + result.cert = native_array; + result.deinit(); + return null; + } } else { - global.throwInvalidArguments("cert argument must be an array containing string, Buffer or TypedArray", .{}); + global.throwInvalidArguments("cert argument must be an string, Buffer, TypedArray, BunFile or an array containing string, Buffer, TypedArray or BunFile", .{}); arena.deinit(); // mark and free all certs result.cert = native_array; @@ -356,19 +438,51 @@ pub const ServerConfig = struct { result.cert_count = valid_count; } + } else if (BlobFileContentResult.init("cert", js_obj, global, exception)) |content| { + if (content.data.len > 0) { + const native_array = bun.default_allocator.alloc([*c]const u8, 1) catch unreachable; + native_array[0] = content.data.ptr; + result.cert = native_array; + result.cert_count = 1; + any = true; + } else { + result.deinit(); + return null; + } } else { - global.throwInvalidArguments("cert argument must be an array containing string, Buffer or TypedArray", .{}); - result.deinit(); - return null; + const native_array = bun.default_allocator.alloc([*c]const u8, 1) catch unreachable; + var arena: std.heap.ArenaAllocator = std.heap.ArenaAllocator.init(bun.default_allocator); + if (JSC.Node.StringOrBuffer.fromJS(global, arena.allocator(), js_obj, exception)) |sb| { + const sliced = sb.slice(); + if (sliced.len > 0) { + native_array[0] = bun.default_allocator.dupeZ(u8, sliced) catch unreachable; + any = true; + result.cert = native_array; + result.cert_count = 1; + } else { + bun.default_allocator.free(native_array); + } + } else { + global.throwInvalidArguments("cert argument must be an string, Buffer, TypedArray, BunFile or an array containing string, Buffer, TypedArray or BunFile", .{}); + arena.deinit(); + // mark and free all certs + result.cert = native_array; + result.deinit(); + return null; + } + + arena.deinit(); } } if (obj.getTruthy(global, "requestCert")) |request_cert| { result.request_cert = if (request_cert.asBoolean()) 1 else 0; + any = true; } if (obj.getTruthy(global, "rejectUnauthorized")) |reject_unauthorized| { result.reject_unauthorized = if (reject_unauthorized.asBoolean()) 1 else 0; + any = true; } if (obj.getTruthy(global, "ciphers")) |ssl_ciphers| { @@ -379,79 +493,119 @@ pub const ServerConfig = struct { any = true; } } - - // Optional - if (any) { - if (obj.getTruthy(global, "secureOptions")) |secure_options| { - if (secure_options.isNumber()) { - result.secure_options = secure_options.toU32(); - } + if (obj.getTruthy(global, "serverName")) |server_name| { + var sliced = server_name.toSlice(global, bun.default_allocator); + defer sliced.deinit(); + if (sliced.len > 0) { + result.server_name = bun.default_allocator.dupeZ(u8, sliced.slice()) catch unreachable; + any = true; } + } - if (obj.getTruthy(global, "serverName")) |key_file_name| { - var sliced = key_file_name.toSlice(global, bun.default_allocator); - defer sliced.deinit(); - if (sliced.len > 0) { - result.server_name = bun.default_allocator.dupeZ(u8, sliced.slice()) catch unreachable; - } - } + if (obj.getTruthy(global, "ca")) |js_obj| { + if (js_obj.jsType().isArray()) { + const count = js_obj.getLengthOfArray(global); + if (count > 0) { + const native_array = bun.default_allocator.alloc([*c]const u8, count) catch unreachable; + + var i: u32 = 0; + var valid_count: u32 = 0; - if (obj.getTruthy(global, "ca")) |js_obj| { - if (js_obj.jsType().isArray()) { - const count = js_obj.getLengthOfArray(global); - if (count > 0) { - const native_array = bun.default_allocator.alloc([*c]const u8, count) catch unreachable; - - var i: u32 = 0; - var valid_count: u32 = 0; - - var arena: std.heap.ArenaAllocator = std.heap.ArenaAllocator.init(bun.default_allocator); - while (i < count) : (i += 1) { - const item = js_obj.getIndex(global, i); - if (JSC.Node.StringOrBuffer.fromJS(global, arena.allocator(), item, exception)) |sb| { - const sliced = sb.slice(); - if (sliced.len > 0) { - native_array[valid_count] = bun.default_allocator.dupeZ(u8, sliced) catch unreachable; - valid_count += 1; - any = true; - } + var arena: std.heap.ArenaAllocator = std.heap.ArenaAllocator.init(bun.default_allocator); + while (i < count) : (i += 1) { + const item = js_obj.getIndex(global, i); + if (JSC.Node.StringOrBuffer.fromJS(global, arena.allocator(), item, exception)) |sb| { + const sliced = sb.slice(); + if (sliced.len > 0) { + native_array[valid_count] = bun.default_allocator.dupeZ(u8, sliced) catch unreachable; + valid_count += 1; + any = true; + } + } else if (BlobFileContentResult.init("ca", item, global, exception)) |content| { + if (content.data.len > 0) { + native_array[valid_count] = content.data.ptr; + valid_count += 1; + any = true; } else { - global.throwInvalidArguments("ca argument must be an array containing string, Buffer or TypedArray", .{}); arena.deinit(); // mark and free all CA's result.cert = native_array; result.deinit(); return null; } + } else { + global.throwInvalidArguments("ca argument must be an string, Buffer, TypedArray, BunFile or an array containing string, Buffer, TypedArray or BunFile", .{}); + arena.deinit(); + // mark and free all CA's + result.cert = native_array; + result.deinit(); + return null; } + } - arena.deinit(); + arena.deinit(); - if (valid_count == 0) { - bun.default_allocator.free(native_array); - } else { - result.ca = native_array; - } + if (valid_count == 0) { + bun.default_allocator.free(native_array); + } else { + result.ca = native_array; + } - result.ca_count = valid_count; + result.ca_count = valid_count; + } + } else if (BlobFileContentResult.init("ca", js_obj, global, exception)) |content| { + if (content.data.len > 0) { + const native_array = bun.default_allocator.alloc([*c]const u8, 1) catch unreachable; + native_array[0] = content.data.ptr; + result.ca = native_array; + result.ca_count = 1; + any = true; + } else { + result.deinit(); + return null; + } + } else { + const native_array = bun.default_allocator.alloc([*c]const u8, 1) catch unreachable; + var arena: std.heap.ArenaAllocator = std.heap.ArenaAllocator.init(bun.default_allocator); + if (JSC.Node.StringOrBuffer.fromJS(global, arena.allocator(), js_obj, exception)) |sb| { + const sliced = sb.slice(); + if (sliced.len > 0) { + native_array[0] = bun.default_allocator.dupeZ(u8, sliced) catch unreachable; + any = true; + result.ca = native_array; + result.ca_count = 1; + } else { + bun.default_allocator.free(native_array); } } else { - global.throwInvalidArguments("cert argument must be an array containing string, Buffer or TypedArray", .{}); + JSC.throwInvalidArguments("ca argument must be an string, Buffer, TypedArray, BunFile or an array containing string, Buffer, TypedArray or BunFile", .{}, global, exception); + arena.deinit(); + // mark and free all certs + result.ca = native_array; result.deinit(); return null; } + arena.deinit(); } + } - if (obj.getTruthy(global, "caFile")) |ca_file_name| { - var sliced = ca_file_name.toSlice(global, bun.default_allocator); - defer sliced.deinit(); - if (sliced.len > 0) { - result.ca_file_name = bun.default_allocator.dupeZ(u8, sliced.slice()) catch unreachable; - if (std.os.system.access(result.ca_file_name, std.os.F_OK) != 0) { - JSC.throwInvalidArguments("Invalid caFile path", .{}, global, exception); - result.deinit(); - return null; - } + if (obj.getTruthy(global, "caFile")) |ca_file_name| { + var sliced = ca_file_name.toSlice(global, bun.default_allocator); + defer sliced.deinit(); + if (sliced.len > 0) { + result.ca_file_name = bun.default_allocator.dupeZ(u8, sliced.slice()) catch unreachable; + if (std.os.system.access(result.ca_file_name, std.os.F_OK) != 0) { + JSC.throwInvalidArguments("Invalid caFile path", .{}, global, exception); + result.deinit(); + return null; + } + } + } + // Optional + if (any) { + if (obj.getTruthy(global, "secureOptions")) |secure_options| { + if (secure_options.isNumber()) { + result.secure_options = secure_options.toU32(); } } @@ -5142,16 +5296,7 @@ pub fn NewServer(comptime ssl_enabled_: bool, comptime debug_mode_: bool) type { if (ssl_enabled) { BoringSSL.load(); const ssl_config = this.config.ssl_config orelse @panic("Assertion failure: ssl_config"); - this.app = App.create( - .{ - .key_file_name = ssl_config.key_file_name, - .cert_file_name = ssl_config.cert_file_name, - .passphrase = ssl_config.passphrase, - .dh_params_file_name = ssl_config.dh_params_file_name, - .ca_file_name = ssl_config.ca_file_name, - .ssl_prefer_low_memory_usage = @as(c_int, @boolToInt(ssl_config.low_memory_mode)), - }, - ); + this.app = App.create(ssl_config.asUSockets()); if (ssl_config.server_name != null and std.mem.span(ssl_config.server_name).len > 0) { this.app.addServerName(ssl_config.server_name); |