aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-08-26 15:09:53 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2021-08-26 15:09:53 -0700
commita6bf54668acf6d0e099e1ffed4f2126887b5a5c8 (patch)
tree21d202e0840338b76e961208b37b6fc3a0a2ea6f /src
parent029ba1ea4439dff3943b053848901d0391912037 (diff)
downloadbun-a6bf54668acf6d0e099e1ffed4f2126887b5a5c8.tar.gz
bun-a6bf54668acf6d0e099e1ffed4f2126887b5a5c8.tar.zst
bun-a6bf54668acf6d0e099e1ffed4f2126887b5a5c8.zip
Bug fixes
Former-commit-id: 853b372665a3762b1eeeb2202e279895bce6f544
Diffstat (limited to 'src')
-rw-r--r--src/cli.zig8
-rw-r--r--src/http.zig145
-rw-r--r--src/http/mime_type.zig5
-rw-r--r--src/options.zig104
4 files changed, 152 insertions, 110 deletions
diff --git a/src/cli.zig b/src/cli.zig
index b1eb3fe52..2589fbcfc 100644
--- a/src/cli.zig
+++ b/src/cli.zig
@@ -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,
diff --git a/src/http.zig b/src/http.zig
index 3e53b349b..fd23b349d 100644
--- a/src/http.zig
+++ b/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 },
);
}
}
diff --git a/src/http/mime_type.zig b/src/http/mime_type.zig
index dc8c40cc2..55d7ec72b 100644
--- a/src/http/mime_type.zig
+++ b/src/http/mime_type.zig
@@ -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 => {
diff --git a/src/options.zig b/src/options.zig
index c3069c54e..1c22153bd 100644
--- a/src/options.zig
+++ b/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;
-
- 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);
-
- 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;
- };
- }
+ const static_dir_set = !opts.routes.static_dir_enabled;
+ var disabled_static = false;
+
+ var chosen_dir = dir_to_use;
+
+ 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";
+ }
+ }
- 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]});
+ break :choice ".";
+ },
+ else => {
+ break :choice "";
+ },
}
- 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);
- },
+ } else |err| {
+ break :choice "";
+ }
+ };
+
+ 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) {