mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
Bug fixes
Former-commit-id: 853b372665a3762b1eeeb2202e279895bce6f544
This commit is contained in:
@@ -394,8 +394,10 @@ pub const Arguments = struct {
|
||||
};
|
||||
}
|
||||
|
||||
if (entry_points.len == 0 and opts.framework == null and opts.node_modules_bundle_path == null) {
|
||||
return error.MissingEntryPoint;
|
||||
if (cmd == .BunCommand or !FeatureFlags.dev_only) {
|
||||
if (entry_points.len == 0 and opts.framework == null and opts.node_modules_bundle_path == null) {
|
||||
return error.MissingEntryPoint;
|
||||
}
|
||||
}
|
||||
|
||||
opts.output_dir = output_dir;
|
||||
@@ -497,7 +499,7 @@ pub const Command = struct {
|
||||
log: *logger.Log,
|
||||
allocator: *std.mem.Allocator,
|
||||
|
||||
pub fn create(allocator: *std.mem.Allocator, log: *logger.Log, comptime command: Command.Tag) !Context {
|
||||
pub fn create(allocator: *std.mem.Allocator, log: *logger.Log, comptime command: Command.Tag) anyerror!Context {
|
||||
return Command.Context{
|
||||
.args = try Arguments.parse(allocator, command),
|
||||
.log = log,
|
||||
|
||||
145
src/http.zig
145
src/http.zig
@@ -454,7 +454,6 @@ pub const RequestContext = struct {
|
||||
|
||||
pub fn sendJSB(ctx: *RequestContext) !void {
|
||||
const node_modules_bundle = ctx.bundler.options.node_modules_bundle orelse unreachable;
|
||||
defer ctx.done();
|
||||
ctx.appendHeader("ETag", node_modules_bundle.bundle.etag);
|
||||
ctx.appendHeader("Content-Type", "text/javascript");
|
||||
ctx.appendHeader("Cache-Control", "immutable, max-age=99999");
|
||||
@@ -466,6 +465,8 @@ pub const RequestContext = struct {
|
||||
}
|
||||
}
|
||||
|
||||
defer ctx.done();
|
||||
|
||||
const content_length = node_modules_bundle.container.code_length.? - node_modules_bundle.codeStartOffset();
|
||||
try ctx.writeStatus(200);
|
||||
try ctx.prepareToSendBody(content_length, false);
|
||||
@@ -1158,7 +1159,7 @@ pub const RequestContext = struct {
|
||||
|
||||
switch (build_result.value) {
|
||||
.fail => {
|
||||
Output.errorLn(
|
||||
Output.prettyErrorln(
|
||||
"Error: <b>{s}<r><b>",
|
||||
.{
|
||||
file_path,
|
||||
@@ -1213,7 +1214,10 @@ pub const RequestContext = struct {
|
||||
}
|
||||
},
|
||||
else => {
|
||||
Output.prettyErrorln("<r>[Websocket]: Unknown cmd: <b>{d}<r>. This might be a version mismatch. Try updating your node_modules.jsb", .{@enumToInt(cmd.kind)});
|
||||
Output.prettyErrorln(
|
||||
"<r>[Websocket]: Unknown cmd: <b>{d}<r>. This might be a version mismatch. Try updating your node_modules.bun",
|
||||
.{@enumToInt(cmd.kind)},
|
||||
);
|
||||
},
|
||||
}
|
||||
},
|
||||
@@ -1398,10 +1402,10 @@ pub const RequestContext = struct {
|
||||
}
|
||||
}
|
||||
|
||||
defer chunky.rctx.done();
|
||||
try chunky.rctx.writeStatus(200);
|
||||
try chunky.rctx.prepareToSendBody(buf.len, false);
|
||||
try chunky.rctx.writeBodyBuf(buf);
|
||||
chunky.rctx.done();
|
||||
}
|
||||
|
||||
pub fn flush(
|
||||
@@ -1858,7 +1862,15 @@ pub const Server = struct {
|
||||
try listener.listen(1280);
|
||||
const addr = try listener.getLocalAddress();
|
||||
|
||||
Output.prettyln("<r>Started Bun at <b><cyan>http://{s}<r>", .{addr});
|
||||
// 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) {
|
||||
Output.prettyln("<r>Started Bun at <b><cyan>http://localhost:{d}<r>", .{addr.ipv4.port});
|
||||
} else {
|
||||
Output.prettyln("<r>Started Bun at <b><cyan>http://{s}<r>", .{addr});
|
||||
}
|
||||
|
||||
Output.flush();
|
||||
// var listener_handle = try std.os.kqueue();
|
||||
// var change_list = std.mem.zeroes([2]os.Kevent);
|
||||
@@ -1884,8 +1896,13 @@ pub const Server = struct {
|
||||
threadlocal var req_buf: [32_000]u8 = undefined;
|
||||
|
||||
pub const ConnectionFeatures = struct {
|
||||
public_folder: bool = false,
|
||||
public_folder: PublicFolderPriority = PublicFolderPriority.none,
|
||||
filesystem_router: bool = false,
|
||||
pub const PublicFolderPriority = enum {
|
||||
none,
|
||||
first,
|
||||
last,
|
||||
};
|
||||
};
|
||||
|
||||
pub fn handleConnection(server: *Server, conn: *tcp.Connection, comptime features: ConnectionFeatures) void {
|
||||
@@ -2005,59 +2022,25 @@ pub const Server = struct {
|
||||
return;
|
||||
};
|
||||
|
||||
if (comptime features.public_folder and features.filesystem_router) {
|
||||
if (!finished) {
|
||||
if (req_ctx.matchPublicFolder()) |result| {
|
||||
finished = true;
|
||||
req_ctx.renderServeResult(result) catch |err| {
|
||||
Output.printErrorln("FAIL [{s}] - {s}: {s}", .{ @errorName(err), req.method, req.path });
|
||||
did_print = true;
|
||||
return;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (!finished) {
|
||||
req_ctx.bundler.router.?.match(server, RequestContext, &req_ctx) catch |err| {
|
||||
switch (err) {
|
||||
error.ModuleNotFound => {
|
||||
req_ctx.sendNotFound() catch {};
|
||||
},
|
||||
else => {
|
||||
Output.printErrorln("FAIL [{s}] - {s}: {s}", .{ @errorName(err), req.method, req.path });
|
||||
did_print = true;
|
||||
return;
|
||||
},
|
||||
if (!finished) {
|
||||
switch (comptime features.public_folder) {
|
||||
.first => {
|
||||
if (!finished) {
|
||||
if (req_ctx.matchPublicFolder()) |result| {
|
||||
finished = true;
|
||||
req_ctx.renderServeResult(result) catch |err| {
|
||||
Output.printErrorln("FAIL [{s}] - {s}: {s}", .{ @errorName(err), req.method, req.path });
|
||||
did_print = true;
|
||||
return;
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
} else if (comptime features.public_folder) {
|
||||
if (!finished) {
|
||||
if (req_ctx.matchPublicFolder()) |result| {
|
||||
finished = true;
|
||||
req_ctx.renderServeResult(result) catch |err| {
|
||||
Output.printErrorln("FAIL [{s}] - {s}: {s}", .{ @errorName(err), req.method, req.path });
|
||||
did_print = true;
|
||||
return;
|
||||
};
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
if (!finished) {
|
||||
req_ctx.handleRequest() catch |err| {
|
||||
switch (err) {
|
||||
error.ModuleNotFound => {
|
||||
req_ctx.sendNotFound() catch {};
|
||||
},
|
||||
else => {
|
||||
Output.printErrorln("FAIL [{s}] - {s}: {s}", .{ @errorName(err), req.method, req.path });
|
||||
did_print = true;
|
||||
return;
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
} else if (comptime features.filesystem_router) {
|
||||
if (comptime features.filesystem_router) {
|
||||
if (!finished) {
|
||||
req_ctx.bundler.router.?.match(server, RequestContext, &req_ctx) catch |err| {
|
||||
switch (err) {
|
||||
@@ -2088,6 +2071,19 @@ pub const Server = struct {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (comptime features.public_folder == .last) {
|
||||
if (!finished) {
|
||||
if (req_ctx.matchPublicFolder()) |result| {
|
||||
finished = true;
|
||||
req_ctx.renderServeResult(result) catch |err| {
|
||||
Output.printErrorln("FAIL [{s}] - {s}: {s}", .{ @errorName(err), req.method, req.path });
|
||||
did_print = true;
|
||||
return;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn initWatcher(server: *Server) !void {
|
||||
@@ -2137,21 +2133,42 @@ pub const Server = struct {
|
||||
|
||||
try server.initWatcher();
|
||||
|
||||
const public_folder_is_top_level = server.bundler.options.routes.static_dir_enabled and strings.eql(
|
||||
server.bundler.fs.top_level_dir,
|
||||
server.bundler.options.routes.static_dir,
|
||||
);
|
||||
|
||||
if (server.bundler.router != null and server.bundler.options.routes.static_dir_enabled) {
|
||||
try server.run(
|
||||
ConnectionFeatures{ .public_folder = true, .filesystem_router = true },
|
||||
);
|
||||
if (public_folder_is_top_level) {
|
||||
try server.run(
|
||||
ConnectionFeatures{ .public_folder = .last, .filesystem_router = true },
|
||||
);
|
||||
} else {
|
||||
try server.run(
|
||||
ConnectionFeatures{ .public_folder = .first, .filesystem_router = true },
|
||||
);
|
||||
}
|
||||
} else if (server.bundler.router != null) {
|
||||
try server.run(
|
||||
ConnectionFeatures{ .public_folder = false, .filesystem_router = true },
|
||||
ConnectionFeatures{ .filesystem_router = true },
|
||||
);
|
||||
} else if (server.bundler.options.routes.static_dir_enabled) {
|
||||
try server.run(
|
||||
ConnectionFeatures{ .public_folder = true, .filesystem_router = false },
|
||||
);
|
||||
if (public_folder_is_top_level) {
|
||||
try server.run(
|
||||
ConnectionFeatures{
|
||||
.public_folder = .first,
|
||||
},
|
||||
);
|
||||
} else {
|
||||
try server.run(
|
||||
ConnectionFeatures{
|
||||
.public_folder = .last,
|
||||
},
|
||||
);
|
||||
}
|
||||
} else {
|
||||
try server.run(
|
||||
ConnectionFeatures{ .public_folder = false, .filesystem_router = false },
|
||||
ConnectionFeatures{ .filesystem_router = false },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,8 @@ pub const css = MimeType.init("text/css", .css);
|
||||
pub const javascript = MimeType.init("text/javascript;charset=utf-8", .javascript);
|
||||
pub const ico = MimeType.init("image/vnd.microsoft.icon", .image);
|
||||
pub const html = MimeType.init("text/html;charset=utf-8", .html);
|
||||
pub const json = MimeType.init("application/json;charset=utf-8", .json);
|
||||
// we transpile json to javascript so that it is importable without import assertions.
|
||||
pub const json = MimeType.init(javascript.value, .json);
|
||||
|
||||
fn init(comptime str: string, t: Category) MimeType {
|
||||
return MimeType{
|
||||
@@ -42,7 +43,7 @@ fn init(comptime str: string, t: Category) MimeType {
|
||||
// TODO: improve this
|
||||
pub fn byLoader(loader: Loader, ext: string) MimeType {
|
||||
switch (loader) {
|
||||
.tsx, .ts, .js, .jsx => {
|
||||
.tsx, .ts, .js, .jsx, .json => {
|
||||
return javascript;
|
||||
},
|
||||
.css => {
|
||||
|
||||
100
src/options.zig
100
src/options.zig
@@ -960,52 +960,74 @@ pub const BundleOptions = struct {
|
||||
opts.resolve_mode = .lazy;
|
||||
|
||||
var dir_to_use: string = opts.routes.static_dir;
|
||||
const static_dir_set = opts.routes.static_dir_enabled;
|
||||
const static_dir_set = !opts.routes.static_dir_enabled;
|
||||
var disabled_static = false;
|
||||
|
||||
var _dirs = [_]string{dir_to_use};
|
||||
opts.routes.static_dir = try fs.absAlloc(allocator, &_dirs);
|
||||
opts.routes.static_dir_handle = std.fs.openDirAbsolute(opts.routes.static_dir, .{ .iterate = true }) catch |err| brk: {
|
||||
var did_warn = false;
|
||||
switch (err) {
|
||||
error.FileNotFound => {
|
||||
// Be nice.
|
||||
// Check "static" since sometimes people use that instead.
|
||||
// Don't switch to it, but just tell "hey try --public-dir=static" next time
|
||||
if (!static_dir_set) {
|
||||
_dirs[0] = "static";
|
||||
const check_static = try fs.absAlloc(allocator, &_dirs);
|
||||
defer allocator.free(check_static);
|
||||
var chosen_dir = dir_to_use;
|
||||
|
||||
std.fs.accessAbsolute(check_static, .{}) catch {
|
||||
Output.prettyErrorln("warn: \"{s}\" folder missing. If there are external assets used in your project, pass --public-dir=\"public-folder-name\"", .{_dirs[0]});
|
||||
did_warn = true;
|
||||
};
|
||||
if (!static_dir_set) {
|
||||
chosen_dir = choice: {
|
||||
if (fs.fs.readDirectory(fs.top_level_dir, null)) |dir_| {
|
||||
const dir: *const Fs.FileSystem.RealFS.EntriesOption = dir_;
|
||||
switch (dir.*) {
|
||||
.entries => {
|
||||
if (dir.entries.getComptimeQuery("public")) |q| {
|
||||
if (q.entry.kind(&fs.fs) == .dir) {
|
||||
break :choice "public";
|
||||
}
|
||||
}
|
||||
|
||||
if (dir.entries.getComptimeQuery("static")) |q| {
|
||||
if (q.entry.kind(&fs.fs) == .dir) {
|
||||
break :choice "static";
|
||||
}
|
||||
}
|
||||
|
||||
break :choice ".";
|
||||
},
|
||||
else => {
|
||||
break :choice "";
|
||||
},
|
||||
}
|
||||
} else |err| {
|
||||
break :choice "";
|
||||
}
|
||||
};
|
||||
|
||||
if (!did_warn) {
|
||||
Output.prettyErrorln("warn: \"{s}\" folder missing. If you want to use \"static\" as the public folder, pass --public-dir=\"static\".", .{_dirs[0]});
|
||||
}
|
||||
opts.routes.static_dir_enabled = false;
|
||||
},
|
||||
error.AccessDenied => {
|
||||
Output.prettyErrorln(
|
||||
"error: access denied when trying to open dir: \"{s}\".\nPlease re-open Bun with access to this folder or pass a different folder via \"--public-dir\". Note: --public-dir is relative to --cwd (or the process' current working directory).\n\nThe public folder is where static assets such as images, fonts, and .html files go.",
|
||||
.{opts.routes.static_dir},
|
||||
);
|
||||
std.process.exit(1);
|
||||
},
|
||||
else => {
|
||||
Output.prettyErrorln(
|
||||
"error: \"{s}\" when accessing public folder: \"{s}\"",
|
||||
.{ @errorName(err), opts.routes.static_dir },
|
||||
);
|
||||
std.process.exit(1);
|
||||
},
|
||||
if (chosen_dir.len == 0) {
|
||||
disabled_static = true;
|
||||
opts.routes.static_dir_enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
break :brk null;
|
||||
};
|
||||
if (!disabled_static) {
|
||||
var _dirs = [_]string{chosen_dir};
|
||||
opts.routes.static_dir = try fs.absAlloc(allocator, &_dirs);
|
||||
opts.routes.static_dir_handle = std.fs.openDirAbsolute(opts.routes.static_dir, .{ .iterate = true }) catch |err| brk: {
|
||||
var did_warn = false;
|
||||
switch (err) {
|
||||
error.FileNotFound => {
|
||||
opts.routes.static_dir_enabled = false;
|
||||
},
|
||||
error.AccessDenied => {
|
||||
Output.prettyErrorln(
|
||||
"error: access denied when trying to open directory for static files: \"{s}\".\nPlease re-open Bun with access to this folder or pass a different folder via \"--public-dir\". Note: --public-dir is relative to --cwd (or the process' current working directory).\n\nThe public folder is where static assets such as images, fonts, and .html files go.",
|
||||
.{opts.routes.static_dir},
|
||||
);
|
||||
std.process.exit(1);
|
||||
},
|
||||
else => {
|
||||
Output.prettyErrorln(
|
||||
"error: \"{s}\" when accessing public folder: \"{s}\"",
|
||||
.{ @errorName(err), opts.routes.static_dir },
|
||||
);
|
||||
std.process.exit(1);
|
||||
},
|
||||
}
|
||||
|
||||
break :brk null;
|
||||
};
|
||||
}
|
||||
// Windows has weird locking rules for file access.
|
||||
// so it's a bad idea to keep a file handle open for a long time on Windows.
|
||||
if (isWindows and opts.routes.static_dir_handle != null) {
|
||||
|
||||
Reference in New Issue
Block a user