如何修改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
相关产品推荐
相关产品推荐

