Bug fixes

Former-commit-id: 853b372665a3762b1eeeb2202e279895bce6f544
This commit is contained in:
Jarred Sumner
2021-08-26 15:09:53 -07:00
parent 029ba1ea44
commit a6bf54668a
4 changed files with 150 additions and 108 deletions

View File

@@ -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,

View File

@@ -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 },
);
}
}

View File

@@ -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 => {

View File

@@ -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) {