You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Zig静态文件服务器无法加载JS文件,请求排查修复

Zig静态文件服务器无法加载JavaScript文件的解决方案

当前用Zig实现的静态文件服务器可正常加载index.html,但无法加载main.js,浏览器报错:

unexpected </ at <script src="main.js"></script>

问题根源

现有代码存在两处关键问题:

  1. 路由逻辑错误:只要请求路径以/开头,就固定返回index.html——包括请求/main.js时,服务器返回的是HTML内容而非JS文件,浏览器将HTML当作JavaScript解析,触发语法错误。
  2. MIME类型缺失:未为不同类型文件设置对应Content-Type响应头,即便正确返回文件,浏览器也无法识别类型。

修改方案

1. 添加MIME类型映射函数

在代码中新增一个根据文件扩展名返回对应MIME类型的工具函数(可放在readFile函数前后任意位置):

fn getMimeType(filename: []const u8) []const u8 {
    if (std.fs.path.extension(filename)) |ext| {
        if (std.mem.eql(u8, ext, ".html")) return "text/html; charset=utf-8";
        if (std.mem.eql(u8, ext, ".js")) return "application/javascript; charset=utf-8";
        // 可按需扩展更多文件类型的MIME映射
        if (std.mem.eql(u8, ext, ".css")) return "text/css; charset=utf-8";
        if (std.mem.eql(u8, ext, ".png")) return "image/png";
        if (std.mem.eql(u8, ext, ".jpg")) return "image/jpeg";
    }
    // 默认返回二进制文件类型
    return "application/octet-stream";
}

2. 重写请求处理逻辑

修改handleRequest函数,实现动态路由匹配、文件读取及MIME类型设置:

fn handleRequest(response: *http.Server.Response, allocator: std.mem.Allocator) !void {
    log.info("{s} {s} {s}", .{ @tagName(response.request.method), @tagName(response.request.version), response.request.target });
    const body = try response.reader().readAllAlloc(allocator, 8192);
    defer allocator.free(body);
    if (response.request.headers.contains("connection")) {
        try response.headers.append("connection", "keep-alive");
    }

    // 根路径请求默认返回index.html
    var target_path = response.request.target;
    if (std.mem.eql(u8, target_path, "/")) {
        target_path = "/index.html";
    }

    // 转换为本地文件路径,同时防止路径遍历攻击
    const filename = target_path[1..];
    if (std.mem.indexOf(u8, filename, "..") != null) {
        response.status = .forbidden;
        try response.do();
        return;
    }

    // 尝试读取目标文件,处理文件不存在的情况
    const contents = readFile(allocator, filename) catch |err| switch (err) {
        error.FileNotFound => {
            response.status = .not_found;
            try response.do();
            return;
        },
        else => return err,
    };
    defer allocator.free(contents);

    // 设置正确的Content-Type并返回文件内容
    const mime_type = getMimeType(filename);
    response.transfer_encoding = .chunked;
    try response.headers.append("content-type", mime_type);
    try response.do();
    if (response.request.method != .HEAD) {
        try response.writeAll(contents);
        try response.finish();
    }
}

关键优化点

  • 路径安全:新增对..的检测,避免攻击者通过路径遍历访问服务器敏感文件
  • 动态路由:根据请求路径返回对应文件,根路径自动映射到index.html
  • 正确MIME类型:浏览器可根据响应头识别文件类型,确保JS、CSS等资源正常解析

内容的提问来源于stack exchange,提问作者Hasan A Yousef

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 06:07:19