资讯动态

Mongoose 跨域没解决?把 ev_handler 贴给走 TaoToken 的 Codex 对照

发布时间:2026/9/20 13:57:37 来源:尧图企业网站定制
1. Mongoose 跨域没解决先看清 ev_handler 里到底发生了什么如果你用 C 和 Mongoose 起了一个 HTTP server前端发请求时浏览器控制台报No Access-Control-Allow-Origin header is present或者 OPTIONS 预检直接 404/405那大概率不是浏览器的问题而是ev_handler里 CORS 头的发送时机和事件分支用错了。Mongoose 是一个面向 C/C 的嵌入式网络库实现了事件驱动 TCP、UDP、HTTP、WebSocket、MQTT 的非阻塞 API适合在嵌入式设备或桌面程序里快速搭一个轻量 HTTP 服务。它的 HTTP 处理是事件驱动的MG_EV_HTTP_REQUEST、MG_EV_HTTP_CHUNK、MG_EV_HTTP_REPLY这些事件各有明确分工一旦把响应头和响应体拆到错误的事件里浏览器就会认为跨域头“没生效”。我见过最常见的写法就是在MG_EV_HTTP_CHUNK分支里调mg_send_response_line拼Access-Control-Allow-Origin然后在MG_EV_HTTP_REQUEST分支里直接mg_send返回数据。表面上看头也发了、数据也回了但实际抓包会发现响应里根本没有 CORS 头或者 OPTIONS 请求压根没被处理。这篇就按排障视角把ev_handler贴给走 TaoToken 的 Codex 对照逐段确认预检 OPTIONS 是否要单独回 204、响应头该在哪个阶段发、mg_send和 chunked 是否冲突。适合谁看正在用 Mongoose 写 C HTTP server、前端跨域被拦、已经贴过 CORS 头但没生效的开发者。你需要能本地编译运行这个 server并且愿意用浏览器或前端页面发一次真实的跨域请求来验证。2. 前置用 TaoToken 的 Key 和 Base URL 配通 CodexTaoToken 在这里的角色很明确它只提供 Key 和 Base URL不替代 Mongoose 的 HTTP 逻辑也不碰你的 C 代码。你要做的是打开 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 注册账号然后在控制台创建一个 API Key。这个 Key 就是用来配通 Codex、让它帮你对照 Mongoose 跨域代码的。创建 Key 的入口在控制台里进去之后新建一个 Key复制出来保存好。接着把 Codex 的 Base URL 填成https://taotoken.net/api注意这里不带/v1也不加任何 UTM 参数。Base URL 和 Key 填对之后Codex 就能正常发起请求你才能把ev_handler的代码贴进去让它逐行对照。注意TaoToken 只负责提供 Key 和 Base URL 这两个接入信息Mongoose 的mg_send_response_line、mg_send、mg_send_http_chunk这些调用逻辑仍然由你自己的 C 代码决定不要指望接入层去改你的 HTTP 行为。如果你还没建 Key可以先到 API Keys 页面创建接入文档里有 Base URL 的填写说明照着填就行。配通之后Codex 的对话入口在模型对话页长期编码或 Agent 场景可以看 Coding Plan。3. 可复制配置把 ev_handler 两段代码整理成可对照的版本先把原始代码里最关键的两段抽出来整理成方便贴给 Codex 对照的形式。第一段是MG_EV_HTTP_CHUNK分支第二段是MG_EV_HTTP_REQUEST分支注释里还留着mg_send_http_chunk和另一段 CORS 头。static void ev_handler(struct mg_connection *nc, int ev, void *p) { if (ev MG_EV_HTTP_CHUNK) { mg_send_response_line(nc, 200, Access-Control-Allow-Origin: *\r\n Access-Control-Allow-Methods: *\r\n Access-Control-Allow-Headers: *\r\n); } if (ev MG_EV_HTTP_REQUEST) { char addr[32]; struct http_message *hm (struct http_message *)p; mg_sock_addr_to_str(nc-sa, addr, sizeof(addr), MG_SOCK_STRINGIFY_IP | MG_SOCK_STRINGIFY_PORT); MLOG from addr : QByteArray(hm-method.p, hm-method.len).data() QByteArray(hm-uri.p, hm-uri.len).data(); QByteArray alldata 11; //Content-Type: application/json\r\n //mg_printf(nc, %s, HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\nAccess-Control-Allow-Origin: *\r\nAccess-Control-Allow-Headers: Content-Type\r\n); //mg_send_response_line(nc, 200, Access-Control-Allow-Origin: *\r\nAccess-Control-Allow-Methods:GET, POST, OPTIONS\r\nAccess-Control-Allow-Headers:*\r\n); //mg_send_http_chunk(nc, alldata.constData(), alldata.length()); //mg_send_http_chunk(nc, , 0); mg_send(nc, alldata.constData(), alldata.length()); nc-flags | MG_F_SEND_AND_CLOSE; } }把这段连同main里的mg_bind、mg_set_protocol_http_websocket一起贴给 Codex让它回答三个问题预检 OPTIONS 是否要单独回 204 并带 CORS 头、响应头是否该在 CHUNK 阶段发出、mg_send与 chunked 是否冲突。下面是我实测下来比较稳的改法你可以直接对照。static void ev_handler(struct mg_connection *nc, int ev, void *p) { if (ev MG_EV_HTTP_REQUEST) { struct http_message *hm (struct http_message *)p; std::string method(hm-method.p, hm-method.len); // 预检请求单独处理直接回 204 并带全 CORS 头 if (method OPTIONS) { mg_send_response_line(nc, 204, Access-Control-Allow-Origin: *\r\n Access-Control-Allow-Methods: GET, POST, OPTIONS\r\n Access-Control-Allow-Headers: Content-Type\r\n Access-Control-Max-Age: 86400\r\n); nc-flags | MG_F_SEND_AND_CLOSE; return; } // 正常请求先发响应行和 CORS 头再发 body mg_send_response_line(nc, 200, Access-Control-Allow-Origin: *\r\n Access-Control-Allow-Methods: GET, POST, OPTIONS\r\n Access-Control-Allow-Headers: Content-Type\r\n Content-Type: application/json\r\n); QByteArray alldata 11; mg_send(nc, alldata.constData(), alldata.length()); nc-flags | MG_F_SEND_AND_CLOSE; } }关键改动有三处OPTIONS 单独走 204 分支、CORS 头统一在MG_EV_HTTP_REQUEST里随响应行发出、不再混用mg_send_http_chunk。这样浏览器预检能拿到完整头正常请求也能拿到Access-Control-Allow-Origin。4. 验证请求本地编译运行用浏览器确认 CORS 头出现改完之后本地编译运行这个 Mongoose server确认监听端口正常。然后开一个前端页面或直接用浏览器控制台发跨域请求。最直接的方式是在另一个源的页面里执行fetch(http://127.0.0.1:8000/api, { method: POST, headers: { Content-Type: application/json }, body: JSON.stringify({ hello: mongoose }) }) .then(r r.text()) .then(t console.log(resp:, t)) .catch(e console.error(err:, e));如果预检没通过控制台会直接报 CORS 错误如果通过你能看到返回的11。更稳的验证方式是打开浏览器开发者工具的 Network 面板找那条 OPTIONS 请求看 Response Headers 里有没有Access-Control-Allow-Origin: *、Access-Control-Allow-Methods、Access-Control-Allow-Headers。再找 POST 请求确认响应头里同样带Access-Control-Allow-Origin。也可以用 curl 直接看头绕过浏览器缓存curl -i -X OPTIONS http://127.0.0.1:8000/api \ -H Origin: http://localhost:3000 \ -H Access-Control-Request-Method: POST \ -H Access-Control-Request-Headers: Content-Type正常应该看到HTTP/1.1 204以及三行Access-Control-Allow-*。如果这里没有说明 OPTIONS 分支没进对或者mg_send_response_line的参数拼错了。5. 本篇常见错排查CORS 头为什么“发了却没生效”第一个坑是把 CORS 头放在MG_EV_HTTP_CHUNK里发。MG_EV_HTTP_CHUNK是接收请求体的分块事件不是发响应头的时机在这里调mg_send_response_line很容易被后续的响应覆盖或错位。正确做法是统一在MG_EV_HTTP_REQUEST里请求体收完之后再发响应行和头。第二个坑是 OPTIONS 没单独处理。浏览器发预检时用的是 OPTIONS 方法如果你的代码只对 GET/POST 返回 CORS 头OPTIONS 就会走到默认分支返回 404 或 405预检直接失败。必须给 OPTIONS 单独回 204并且带上Access-Control-Allow-Methods和Access-Control-Allow-Headers。第三个坑是mg_send和mg_send_http_chunk混用。mg_send_http_chunk会自己写 chunked 编码的响应行和分块如果你前面已经用mg_send_response_line发过 200再调 chunk 就会产生两个响应头浏览器解析直接乱掉。要么全用mg_send发定长 body要么全用 chunk不要交叉。第四个坑是Access-Control-Allow-Methods: *这种写法。部分浏览器对通配符支持不一致预检时更稳的是显式列出GET, POST, OPTIONS。同理Access-Control-Allow-Headers建议写Content-Type而不是*。第五个坑是忘了nc-flags | MG_F_SEND_AND_CLOSE;。响应发完不关闭连接浏览器可能一直等表现为请求 pending。每个分支返回前都要记得置这个标志。把上面这几条对照你的ev_handler逐条过一遍基本能定位到跨域头没生效的具体原因。如果还不确定就把整理好的两段代码贴给走 TaoToken 的 Codex让它按事件分支逐行标注发送时机。6. 把 Key 用起来让 Codex 对照 Mongoose 跨域代码这个 Key 的用途就是配通 Codex让它帮你查 Mongoose 跨域代码。你可以在模型对话里把ev_handler、MG_EV_HTTP_CHUNK与MG_EV_HTTP_REQUEST两段、以及被注释的mg_send_http_chunk一起贴进去问它预检 OPTIONS 是否要单独回 204 并带 CORS 头、响应头是否该在 CHUNK 阶段发出、mg_send与 chunked 是否冲突。Codex 会按事件驱动模型逐条对照比你自己猜快很多。接入信息就两个Base URL 填https://taotoken.net/apiKey 用你在控制台创建的那个。需要新建 Key 就去 API Keys 页面接入细节看接入文档。验证模型效果用模型对话长期编码或 Agent 场景看 Coding Plan。Mongoose 的 HTTP 逻辑始终在你自己的 C 代码里TaoToken 只负责把 Codex 配通让你有个能对照代码的助手。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价