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

如何修改Mongoose中mg_http_serve_dir与mg_http_serve_file的输出?

问题

我正在使用Mongoose框架的http-restful-server示例,想要找到修改mg_http_serve_dir和mg_http_serve_file输出的最佳方法——比如在调用这两个函数后对输出内容做字符串替换、调整内容长度。目前我已经自行重写了local_mg_http_serve_dir和local_mg_http_serve_file函数,以下是我的自定义serve dir函数代码:

void local_mg_http_serve_dir(struct mg_connection* c, struct mg_http_message* hm, const struct mg_http_serve_opts* opts) {
 char path[MG_PATH_MAX];
 const char* sp = opts->ssi_pattern;
 int flags = uri_to_path(c, hm, opts, path, sizeof(path));
 if (flags < 0) {
  // Do nothing: the response has already been sent by uri_to_path()
 }
 else if (flags & MG_FS_DIR) {
#if MG_ENABLE_DIRLIST
  listdir(c, hm, opts, path);
#else
  mg_http_reply(c, 403, "", "Forbidden\n");
#endif
 }
 else if (flags && sp != NULL &&
  mg_globmatch(sp, strlen(sp), path, strlen(path))) {
  mg_http_serve_ssi(c, opts->root_dir, path);
 }
 else {
  if (mg_http_match_uri(hm, "#.csp") || mg_http_match_uri(hm, "/")) {
   if(!local_mg_http_serve_404(c, hm, path, opts)) {
    char* cont;
    cont = readFile(path);
    Poco::JSON::Object::Ptr jdb = jdbRead("./var/db");
    std::string menuHtml = jdbMenuToHtml("mainmenu", jdb);
    replaceInPlace(cont, "<* menu *>", menuHtml.c_str());
    mg_http_reply(c, 200, "content-type: text/html\n", "%s", cont);
   }
  }
  else {
   local_mg_http_serve_file(c, hm, path, opts);
  }
 }
}

我想知道有没有更简便的实现方式,不用自行重写这些函数。

更简便的实现方案

不用重写整个mg_http_serve_dir和mg_http_serve_file,可以用以下几种轻量方式实现:

1. 前置拦截请求,按需处理

在官方serve函数执行前,先判断请求路径,对需要修改内容的请求提前处理,其他请求直接交给官方函数:

// 自定义请求处理入口
void my_http_handler(struct mg_connection* c, int ev, void* ev_data, void* fn_data) {
  if (ev == MG_EV_HTTP_MSG) {
    struct mg_http_message* hm = (struct mg_http_message*) ev_data;
    struct mg_http_serve_opts opts = {.root_dir = "web_root"};
    char path[MG_PATH_MAX];
    int flags = uri_to_path(c, hm, &opts, path, sizeof(path));

    // 针对需要替换内容的路径做单独处理
    if ((flags >= 0 && !MG_FS_DIR(flags)) && 
        (mg_http_match_uri(hm, "#.csp") || mg_http_match_uri(hm, "/"))) {
      if (mg_file_exists(path)) {
        // 读取文件、替换内容后直接返回
        char* cont = readFile(path);
        Poco::JSON::Object::Ptr jdb = jdbRead("./var/db");
        std::string menuHtml = jdbMenuToHtml("mainmenu", jdb);
        replaceInPlace(cont, "<* menu *>", menuHtml.c_str());
        mg_http_reply(c, 200, "content-type: text/html\n", "%s", cont);
        free(cont); // 注意释放内存
        return;
      }
    }

    // 其余请求交给官方serve_dir处理
    mg_http_serve_dir(c, hm, &opts);
  }
}

// 主函数中注册该处理器
mg_http_listen(&mgr, "http://0.0.0.0:8000", my_http_handler, NULL);

2. 扩展SSI功能实现动态替换

利用Mongoose原生的SSI(服务器端包含)机制,自定义标签处理逻辑:

  • 确保编译时开启MG_ENABLE_SSI宏
  • 将.csp等需要替换的文件后缀加入ssi_pattern配置
  • 扩展SSI处理器,让它识别你的<* menu *>标签,自动替换为动态生成的菜单HTML
    这种方式下,官方的mg_http_serve_dir会自动触发SSI处理,无需重写核心函数。

3. 全局拦截输出函数(适合统一处理场景)

如果需要对所有HTTP输出做统一修改,可以重写mg_send或mg_http_reply的底层实现,在内容发送前完成替换。但这种方式要注意内存管理和性能,仅适合全局统一调整的场景。

内容的提问来源于stack exchange,提问作者1u1u

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 06:03:14