aboutsummaryrefslogtreecommitdiff
path: root/src/http.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/http.zig')
-rw-r--r--src/http.zig121
1 files changed, 60 insertions, 61 deletions
diff --git a/src/http.zig b/src/http.zig
index 1c39654e3..588007142 100644
--- a/src/http.zig
+++ b/src/http.zig
@@ -50,12 +50,6 @@ pub fn constStrToU8(s: string) []u8 {
pub const MutableStringAPIWriter = NewApiWriter(*MutableString);
-const tcp = std.x.net.tcp;
-const ip = std.x.net.ip;
-
-const IPv4 = std.x.os.IPv4;
-const IPv6 = std.x.os.IPv6;
-const Socket = std.x.os.Socket;
const os = std.os;
const picohttp = @import("bun").picohttp;
@@ -87,10 +81,17 @@ const SOCKET_FLAGS: u32 = if (Environment.isLinux)
else
os.SOCK.CLOEXEC;
+fn iovec(buf: []const u8) os.iovec_const {
+ return os.iovec_const{
+ .iov_base = buf.ptr,
+ .iov_len = buf.len,
+ };
+}
+
fn disableSIGPIPESoClosingTheTabDoesntCrash(conn: anytype) void {
if (comptime !Environment.isMac) return;
std.os.setsockopt(
- conn.client.socket.fd,
+ conn.handle,
std.os.SOL.SOCKET,
std.os.SO.NOSIGPIPE,
&std.mem.toBytes(@as(c_int, 1)),
@@ -102,7 +103,7 @@ pub const RequestContext = struct {
request: Request,
method: Method,
url: URLPath,
- conn: *tcp.Connection,
+ conn: std.net.Stream,
allocator: std.mem.Allocator,
arena: ThreadlocalArena,
req_body_node: *RequestDataPool.Node = undefined,
@@ -679,7 +680,7 @@ pub const RequestContext = struct {
var total: usize = 0;
var buf: []const u8 = buf_;
while (buf.len > 0) {
- switch (Syscall.send(ctx.conn.client.socket.fd, buf, SOCKET_FLAGS)) {
+ switch (Syscall.send(ctx.conn.handle, buf, SOCKET_FLAGS)) {
.err => |err| {
const erro = AsyncIO.asError(err.getErrno());
if (erro == error.EBADF or erro == error.ECONNABORTED or erro == error.ECONNREFUSED) {
@@ -737,7 +738,7 @@ pub const RequestContext = struct {
this: *RequestContext,
req: Request,
arena: ThreadlocalArena,
- conn: *tcp.Connection,
+ conn: std.net.Stream,
bundler_: *Bundler,
watcher_: *Watcher,
timer: std.time.Timer,
@@ -832,7 +833,7 @@ pub const RequestContext = struct {
pub fn done(ctx: *RequestContext) void {
std.debug.assert(!ctx.has_called_done);
- ctx.conn.deinit();
+ std.os.closeSocket(ctx.conn.handle);
ctx.has_called_done = true;
}
@@ -891,7 +892,7 @@ pub const RequestContext = struct {
try ctx.prepareToSendBody(content_length, false);
_ = try std.os.sendfile(
- ctx.conn.client.socket.fd,
+ ctx.conn.handle,
node_modules_bundle.fd,
node_modules_bundle.codeStartOffset(),
content_length,
@@ -926,7 +927,7 @@ pub const RequestContext = struct {
var remain = content_length;
while (remain > 0) {
const wrote = try std.os.sendfile(
- ctx.conn.client.socket.fd,
+ ctx.conn.handle,
ctx.bundler.options.routes.single_page_app_fd,
content_length - remain,
remain,
@@ -1192,7 +1193,7 @@ pub const RequestContext = struct {
pub const JavaScriptHandler = struct {
ctx: RequestContext,
- conn: tcp.Connection,
+ conn: std.net.Stream,
params: Router.Param.List,
pub fn deinit(this: *JavaScriptHandler) void {
@@ -1605,14 +1606,14 @@ pub const RequestContext = struct {
var clone = try server.allocator.create(JavaScriptHandler);
clone.* = JavaScriptHandler{
.ctx = ctx.*,
- .conn = ctx.conn.*,
+ .conn = ctx.conn,
.params = if (params.len > 0)
try params.clone(server.allocator)
else
Router.Param.List{},
};
- clone.ctx.conn = &clone.conn;
+ clone.ctx.conn = clone.conn;
clone.ctx.matched_route.?.params = &clone.params;
// this is a threadlocal arena
@@ -1667,7 +1668,7 @@ pub const RequestContext = struct {
accept_key: [28]u8 = undefined,
ctx: RequestContext,
websocket: Websocket.Websocket,
- conn: tcp.Connection,
+ conn: std.net.Stream,
tombstone: bool = false,
builder: WatchBuilder,
message_buffer: MutableString,
@@ -1681,13 +1682,13 @@ pub const RequestContext = struct {
var clone = try server.allocator.create(WebsocketHandler);
clone.ctx = ctx.*;
- clone.conn = ctx.conn.*;
+ clone.conn = ctx.conn;
try ctx.bundler.clone(server.allocator, &clone.bundler);
ctx.bundler = &clone.bundler;
clone.task = .{ .callback = &onTask };
clone.message_buffer = try MutableString.init(server.allocator, 0);
- clone.ctx.conn = &clone.conn;
+ clone.ctx.conn = clone.conn;
clone.ctx.log = logger.Log.init(server.allocator);
clone.ctx.origin = ZigURL.parse(server.allocator.dupe(u8, ctx.origin.href) catch unreachable);
@@ -1700,7 +1701,7 @@ pub const RequestContext = struct {
.origin = clone.ctx.origin,
};
- clone.websocket = Websocket.Websocket.create(&clone.conn, SOCKET_FLAGS);
+ clone.websocket = Websocket.Websocket.create(clone.conn.handle, SOCKET_FLAGS);
clone.tombstone = false;
ctx.allocator = undefined;
@@ -1808,7 +1809,7 @@ pub const RequestContext = struct {
fn _handle(handler: *WebsocketHandler, ctx: *RequestContext) !void {
var is_socket_closed = false;
- const fd = ctx.conn.client.socket.fd;
+ const fd = ctx.conn.handle;
defer {
websocket_printer = handler.builder.printer.ctx;
handler.tombstone = true;
@@ -1911,7 +1912,7 @@ pub const RequestContext = struct {
Output.flush();
defer Output.flush();
- handler.conn.client.getError() catch |err| {
+ std.os.getsockoptError(handler.conn.handle) catch |err| {
handler.tombstone = true;
Output.prettyErrorln("<r><red>Websocket ERR:<r> <b>{s}<r>", .{@errorName(err)});
is_socket_closed = true;
@@ -2019,11 +2020,11 @@ pub const RequestContext = struct {
var writer = buffer_writer.writable.writer();
const body_len = handler.message_buffer.list.items.len;
try head.writeHeader(&writer, body_len);
- const buffers = handler.message_buffer.toSocketBuffers(2, .{
+ var buffers = handler.message_buffer.toSocketBuffers(2, .{
.{ body_len, handler.message_buffer.list.items.len },
.{ 0, body_len },
});
- _ = try handler.conn.client.writeMessage(std.x.os.Socket.Message.fromBuffers(&buffers), SOCKET_FLAGS);
+ _ = try handler.conn.writevAll(&buffers);
continue;
}
@@ -2068,7 +2069,7 @@ pub const RequestContext = struct {
handler.message_buffer.reset();
var buffer_writer = MutableStringAPIWriter.init(&handler.message_buffer);
try msg.encode(&buffer_writer);
- var socket_buffers = std.mem.zeroes([4]std.x.os.Buffer);
+ var socket_buffers = std.mem.zeroes([4]std.os.iovec_const);
var socket_buffer_count: usize = 2;
@@ -2079,15 +2080,15 @@ pub const RequestContext = struct {
const first_message_len = handler.message_buffer.list.items.len;
head.len = Websocket.WebsocketHeader.packLength(total);
try head.writeHeader(&handler.message_buffer.writer(), total);
- socket_buffers[0] = std.x.os.Buffer.from(handler.message_buffer.list.items[first_message_len..]);
- socket_buffers[1] = std.x.os.Buffer.from(handler.message_buffer.list.items[0..first_message_len]);
+ socket_buffers[0] = iovec(handler.message_buffer.list.items[first_message_len..]);
+ socket_buffers[1] = iovec(handler.message_buffer.list.items[0..first_message_len]);
if (build_result.bytes.len > 0) {
- socket_buffers[2] = std.x.os.Buffer.from(build_result.bytes);
+ socket_buffers[2] = iovec(build_result.bytes);
// we reuse the accept key buffer
// so we have a pointer that is not stack memory
handler.accept_key[0..@sizeOf(usize)].* = @bitCast([@sizeOf(usize)]u8, std.hash.Wyhash.hash(0, build_result.bytes));
- socket_buffers[3] = std.x.os.Buffer.from(handler.accept_key[0..4]);
+ socket_buffers[3] = iovec(handler.accept_key[0..4]);
socket_buffer_count = 4;
}
},
@@ -2096,14 +2097,13 @@ pub const RequestContext = struct {
head.len = Websocket.WebsocketHeader.packLength(handler.message_buffer.list.items.len);
const first_message_len = handler.message_buffer.list.items.len;
try head.writeHeader(&handler.message_buffer.writer(), handler.message_buffer.list.items.len);
- socket_buffers[0] = std.x.os.Buffer.from(handler.message_buffer.list.items[first_message_len..]);
- socket_buffers[1] = std.x.os.Buffer.from(handler.message_buffer.list.items[0..first_message_len]);
+ socket_buffers[0] = iovec(handler.message_buffer.list.items[first_message_len..]);
+ socket_buffers[1] = iovec(handler.message_buffer.list.items[0..first_message_len]);
},
}
- _ = try handler.conn.client.writeMessage(
- std.x.os.Socket.Message.fromBuffers(socket_buffers[0..socket_buffer_count]),
- SOCKET_FLAGS,
+ _ = try handler.conn.writevAll(
+ socket_buffers[0..socket_buffer_count],
);
}
},
@@ -2631,7 +2631,7 @@ pub const RequestContext = struct {
if (!send_body) return;
_ = try std.os.sendfile(
- ctx.conn.client.socket.fd,
+ ctx.conn.handle,
file.fd,
0,
result.file.size,
@@ -3036,7 +3036,7 @@ pub const RequestContext = struct {
try ctx.prepareToSendBody(content_length, false);
_ = try std.os.sendfile(
- ctx.conn.client.socket.fd,
+ ctx.conn.handle,
fd,
0,
content_length,
@@ -3439,7 +3439,9 @@ pub const Server = struct {
RequestContext.WebsocketHandler.open_websockets = @TypeOf(
RequestContext.WebsocketHandler.open_websockets,
).init(server.allocator);
- const listener = try tcp.Listener.init(.ip, .{ .close_on_exec = true });
+ var listener = std.net.StreamServer.init(.{
+ .kernel_backlog = 1280,
+ });
defer listener.deinit();
server.websocket_threadpool.stack_size = @truncate(
u32,
@@ -3449,8 +3451,6 @@ pub const Server = struct {
),
);
- listener.setReuseAddress(true) catch {};
- listener.setReusePort(false) catch {};
// listener.setFastOpen(true) catch {};
// listener.setNoDelay(true) catch {};
// listener.setQuickACK(true) catch {};
@@ -3469,8 +3469,8 @@ pub const Server = struct {
var attempts: u8 = 0;
restart: while (attempts < 10) : (attempts += 1) {
- listener.bind(ip.Address.initIPv4(
- IPv4.unspecified,
+ listener.listen(std.net.Address.initIp4(
+ .{ 0, 0, 0, 0 },
port,
)) catch |err| {
switch (err) {
@@ -3504,11 +3504,10 @@ pub const Server = struct {
}
}
- try listener.listen(1280);
- const addr = try listener.getLocalAddress();
+ const addr = listener.listen_address;
- if (port != addr.ipv4.port) {
- server.bundler.options.origin.port = try std.fmt.allocPrint(server.allocator, "{d}", .{addr.ipv4.port});
+ if (port != addr.getPort()) {
+ server.bundler.options.origin.port = try std.fmt.allocPrint(server.allocator, "{d}", .{addr.getPort()});
}
const start_time = Global.getStartTime();
@@ -3533,20 +3532,20 @@ pub const Server = struct {
// This is technically imprecise.
// However, we want to optimize for easy to copy paste
// Nobody should get weird CORS errors when you go to the printed url.
- if (std.mem.readIntNative(u32, &addr.ipv4.host.octets) == 0 or std.mem.readIntNative(u128, &addr.ipv6.host.octets) == 0) {
+ if (addr.in.sa.addr == 0) {
if (server.bundler.options.routes.single_page_app_routing) {
Output.prettyError(
" bun!! <d>v{s}<r>\n\n\n Link:<r> <b><cyan>http://localhost:{d}<r>\n <d>{s}/index.html<r> \n\n\n",
.{
Global.package_json_version_with_sha,
- addr.ipv4.port,
+ addr.getPort(),
display_path,
},
);
} else {
Output.prettyError(" bun!! <d>v{s}<r>\n\n\n<d> Link:<r> <b><cyan>http://localhost:{d}<r>\n\n\n", .{
Global.package_json_version_with_sha,
- addr.ipv4.port,
+ addr.getPort(),
});
}
} else {
@@ -3578,10 +3577,10 @@ pub const Server = struct {
var did_init = false;
while (!did_init) {
defer Output.flush();
- var conn = listener.accept(.{ .close_on_exec = true }) catch
+ var conn = listener.accept() catch
continue;
- disableSIGPIPESoClosingTheTabDoesntCrash(conn);
+ disableSIGPIPESoClosingTheTabDoesntCrash(conn.stream);
// We want to bind to the network socket as quickly as possible so that opening the URL works
// We use a secondary loop so that we avoid the extra branch in a hot code path
@@ -3592,7 +3591,7 @@ pub const Server = struct {
did_init = true;
Analytics.enqueue(Analytics.EventName.http_start);
- server.handleConnection(&conn, comptime features);
+ server.handleConnection(conn.stream, comptime features);
}
server.cleanupRequestData();
@@ -3600,12 +3599,12 @@ pub const Server = struct {
while (true) {
defer Output.flush();
- var conn = listener.accept(.{ .close_on_exec = true }) catch
+ var conn = listener.accept() catch
continue;
- disableSIGPIPESoClosingTheTabDoesntCrash(conn);
+ disableSIGPIPESoClosingTheTabDoesntCrash(conn.stream);
- server.handleConnection(&conn, comptime features);
+ server.handleConnection(conn.stream, comptime features);
counter +%= 1;
if (counter % 4 == 0) server.cleanupRequestData();
}
@@ -3623,12 +3622,12 @@ pub const Server = struct {
};
threadlocal var req_ctx_: RequestContext = undefined;
- pub fn handleConnection(server: *Server, conn: *tcp.Connection, comptime features: ConnectionFeatures) void {
+ pub fn handleConnection(server: *Server, conn: std.net.Stream, comptime features: ConnectionFeatures) void {
var req_buf_node = RequestDataPool.get(server.allocator);
// https://stackoverflow.com/questions/686217/maximum-on-http-header-values
- var read_size = conn.client.read(&req_buf_node.data, SOCKET_FLAGS) catch {
- _ = conn.client.write(comptime RequestContext.printStatusLine(400) ++ "\r\n\r\n", SOCKET_FLAGS) catch {};
+ var read_size = conn.read(&req_buf_node.data) catch {
+ _ = conn.write(comptime RequestContext.printStatusLine(400) ++ "\r\n\r\n") catch {};
return;
};
@@ -3638,8 +3637,8 @@ pub const Server = struct {
}
var req = picohttp.Request.parse(req_buf_node.data[0..read_size], &req_headers_buf) catch |err| {
- _ = conn.client.write(comptime RequestContext.printStatusLine(400) ++ "\r\n\r\n", SOCKET_FLAGS) catch {};
- _ = Syscall.close(conn.client.socket.fd);
+ _ = conn.write(comptime RequestContext.printStatusLine(400) ++ "\r\n\r\n") catch {};
+ _ = Syscall.close(conn.handle);
Output.printErrorln("ERR: {s}", .{@errorName(err)});
return;
};
@@ -3657,7 +3656,7 @@ pub const Server = struct {
server.timer,
) catch |err| {
Output.prettyErrorln("<r>[<red>{s}<r>] - <b>{s}<r>: {s}", .{ @errorName(err), req.method, req.path });
- _ = Syscall.close(conn.client.socket.fd);
+ _ = Syscall.close(conn.handle);
request_arena.deinit();
return;
};
@@ -3682,7 +3681,7 @@ pub const Server = struct {
if (req_ctx.url.needs_redirect) {
req_ctx.handleRedirect(req_ctx.url.path) catch |err| {
Output.prettyErrorln("<r>[<red>{s}<r>] - <b>{s}<r>: {s}", .{ @errorName(err), req.method, req.path });
- conn.client.deinit();
+ conn.close();
return;
};
return;