Connexus请求解析(第六部分):创建HTTP请求与响应(基础篇)
「在MT5里拼出第一个Connexus HTTP请求」
想在 MT5 里跟 Connexus 接口对话,第一步是把 HTTP 请求结构体搭对。MQL5 的 WebRequest 只认你塞进去的 method、headers 和 body,参数拼错就直接返回 401 或 400,不会给多余提示。 下面这段是最小可跑的请求骨架,先把 host 和 endpoint 写死,验证通了再抽成输入参数。注意 Content-Type 必须显式带 application/json,否则 Connexus 网关会按表单解析导致解析失败。
class="type">class="kw">string endpoint="/api/v1/quote"; class="type">class="kw">string headers="Content-Type: application/json\r\n"; class="type">char post[]; class="type">class="kw">string data="{\"symbol\":\"XAUUSD\"}"; StringToCharArray(data,post,class="num">0,StringLen(data)); class="type">int timeout=class="num">5000; class="type">char result[]; class="type">class="kw">string result_headers; class="type">int ret=WebRequest("POST","https:class=class="str">"cmt">//connexus.io"+endpoint,headers,timeout,post,result,result_headers);
class="type">class="kw">string endpoint="/api/v1/quote"; class="type">class="kw">string headers="Content-Type: application/json\r\n"; class="type">char post[]; class="type">class="kw">string data="{\"symbol\":\"XAUUSD\"}"; StringToCharArray(data,post,class="num">0,StringLen(data)); class="type">int timeout=class="num">5000; class="type">char result[]; class="type">class="kw">string result_headers; class="type">int ret=WebRequest("POST","https:class=class="str">"cmt">//connexus.io"+endpoint,headers,timeout,post,result,result_headers);
把零散请求部件拼成完整 HTTP 调用
Connexus 系列走到第六篇,重点不再是单个参数,而是把前面拆开的 URL、请求头、请求体、HTTP 方法拢成一个「完整请求类」,再配一个「响应类」装回数据、状态码和耗时。前面五篇已经分别给每个部件写了独立类,这一步是把它们组装起来。 回顾一下已落地的部件:URL 类负责拼域名、端口、路径和查询参数;请求头类管附带元信息;请求体类支持字符串、JSON、字符数组三种格式;HTTP 方法类定义 GET/POST/PUT 等行为。还有一个之前没单聊、但极关键的量是超时——单位是毫秒,WebRequest 是同步阻塞的,EA 会卡在等响应上,所以超时设了能防服务器拖死策略。 实测里,对多数普通服务器 5000 毫秒(5 秒)足够完成一次正常请求;若你的经纪商 API 或行情网关偏慢,这个值要往上调,但别设太长以免 EA 长时间假死。所有部件里,只有 URL 和 HTTP 方法是必填,其余都能省。 当前库架构里,方法、状态码、带查询参数的 URL、头、体这五个类都已就位,第六篇要补的就是把它们包进请求/响应两个容器类,MT5 里打开对应头文件就能看到继承关系。
◍ 用外观类把请求构造压成几行
在 MT5 里手写 HTTP 请求,如果逐个去 new 子系统对象,代码会迅速膨胀。原文给出的散装写法要先建 CURL、CHttpBody、CHttpHeader、CHttpMethod 四个实例,再分别调 Parse、AddString、Add 和赋值,光超时还得单独定义 int m_timeout=5000,十行打底,可读性直接掉沟里。 外观模式就是给这套子系统套一层薄壳:新增 CHttpRequest 作为统一入口,内部持有 Url()、Body()、Header()、Method() 等子对象引用。调用方只跟 CHttpRequest 打交道,不用管 CHttpBody 和 CHttpHeader 怎么初始化。 好处不是玄学——耦合降了,后面你改底层 CHttpHeader 的实现,只要外观方法签名不动,业务代码一行不用动;可维护性也跟着上来。下面这段代码左边是裸调子系统,右边是走外观,行数差不多砍掉一半。 外汇与贵金属相关的自动化请求接口波动大、断连风险高,任何封装都只是降低编码复杂度,不降低实盘风险,参数超时建议先在策略测试器里跑通再上真实账户。
CURL m_url; m_url.Parse("http:class=class="str">"cmt">//example.com/api"); CHttpBody m_body; m_body.AddString("my text"); CHttpHeader m_headers; m_headers.Add("content-type","text/plain"); CHttpMethod m_method; m_method = HTTP_METHOD_GET; class="type">int m_timeout = class="num">5000; CHttpRequest request; request.Method() = HTTP_METHOD_GET; request.Url().Parse("http:class=class="str">"cmt">//example.com/api"); request.Body().AddString("my text"); request.Header().Add("content-type","text/plain");
「给 HTTP 请求套一层外观」
在 MT5 的 Include/Connexus/Core 目录下新建 HttpRequest.mqh,用 CHttpRequest 把 CURL、CHttpBody、CHttpHeader、CHttpMethod 四个对象收口。四个成员全部用指针声明并加「*」,意味着内存要手动管,别指望析构帮你擦屁股。 除了四个对象的访问器(Url/Body/Header/Method 各返回指针),类里还塞了一个 int m_timeout 存超时,配 Timeout(int) 和 int Timeout() 做写读。辅助方法 Clear() 清数据、FormatString() 拼出整条请求串,调用方不用关心头或体怎么拼。 实际写 EA 或脚本时,你只 new 一个 CHttpRequest,设好 Method、Url、Header、Body,超时给个 3000 毫秒级别的值,外观内部就把脏活全干了。外汇和贵金属行情接口调用对延迟敏感,超时设太短可能频繁失败,设太长又拖挂单响应,建议先在策略测试器里跑几次看分布。 下面这段是类骨架原文,只列了构造和析构,完整方法实现得看发布包末尾文件——但结构已经够你照着补访问器和辅助方法了。
class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| | class=class="str">"cmt">//| HttpRequest.mqh | class=class="str">"cmt">//| Copyright class="num">2024, MetaQuotes Ltd. | class=class="str">"cmt">//| [MQL5官方文档] | class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "Copyright class="num">2024, MetaQuotes Ltd." class="macro">#class="kw">property link "[MQL5官方文档] class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| class : CHttpRequest | class=class="str">"cmt">//| | class=class="str">"cmt">//| [PROPERTY] | class=class="str">"cmt">//| Name : CHttpRequest | class=class="str">"cmt">//| Heritage : No heritage | class=class="str">"cmt">//| Description : Gathers elements of an http request such as url, | class=class="str">"cmt">//| body, header, method and timeout | class=class="str">"cmt">//| | class=class="str">"cmt">//+------------------------------------------------------------------+ class CHttpRequest { class="kw">public: CHttpRequest(class="type">void); ~CHttpRequest(class="type">void); }; class=class="str">"cmt">//+------------------------------------------------------------------+
HttpRequest 类的空壳与依赖装配
在 MT5 自定义 HTTP 请求封装里,CHttpRequest 的构造与析构当前都是空实现:编译器生成对象时不挂任何资源,销毁时也不做额外清理。这意味该类初期只承担数据聚合角色,把 url、body、header、method、timeout 收拢到一起,而非管理连接生命周期。 头文件顶部用 #property 标了版权与链接信息,实际编译无功能影响,但能帮你快速识别这是 MetaQuotes 2024 年发布的基类结构。随后通过 4 条 #include 把相对路径里的 URL、HttpBody、HttpHeader、HttpMethod 拉进来——注意路径是 "../URL/URL.mqh" 这种上层目录引用,复制代码时目录层级不对会直接报找不到文件。 类注释写明它无继承(No heritage),纯独立聚合体。开 MT5 验证时,可先建一个空 CHttpRequest 实例,确认构造/析构零开销,再逐步往里塞上述子模块做请求拼装。外汇与贵金属行情接口调用属高风险操作,超时与鉴权参数设置不当可能触发账户端异常。
class=class="str">"cmt">//| Constructor | class=class="str">"cmt">//+------------------------------------------------------------------+ CHttpRequest::CHttpRequest(class="type">void) { } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Destructor | class=class="str">"cmt">//+------------------------------------------------------------------+ CHttpRequest::~CHttpRequest(class="type">void) { } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| HttpRequest.mqh | class=class="str">"cmt">//| Copyright class="num">2024, MetaQuotes Ltd. | class=class="str">"cmt">//| [MQL5官方文档] | class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "Copyright class="num">2024, MetaQuotes Ltd." class="macro">#class="kw">property link "[MQL5官方文档] class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Include files | class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#include "../URL/URL.mqh" class="macro">#include "../Header/HttpBody.mqh" class="macro">#include "../Header/HttpHeader.mqh" class="macro">#include "../Constants/HttpMethod.mqh" class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| class : CHttpRequest | class=class="str">"cmt">//| | class=class="str">"cmt">//| [PROPERTY] | class=class="str">"cmt">//| Name : CHttpRequest | class=class="str">"cmt">//| Heritage : No heritage | class=class="str">"cmt">//| Description : Gathers elements of an http request such as url, | class=class="str">"cmt">//| body, header, method and timeout |
◍ 把请求封装丢给类去管
在 MT5 里做外部数据拉取,最怕的是每次发请求都重写一遍连接、头、超时逻辑。把这些都收进一个 CHttpRequest 类,调用侧只关心 URL 和参数,代码可读性会好很多。 下面这段类定义把 CURL 句柄、请求体、请求头、方法、超时全部做成私有成员。构造时统一 new 出来,析构时统一 delete,避免 EA 退出时漏释放导致终端内存占用悄悄涨。 注意构造函数里 m_timeout 写死成 5000,也就是默认 5 秒超时。实盘跑外汇或贵金属信号拉取时,这个值是偏紧的,网络一抖就可能断;你可以改成 10000 或读配置文件,降低假超时概率。 类外面那份 HTTP Request 示例是 GET 到 api.example.com,带 Bearer token 和 JSON body。它只是结构演示,真要接你自己的 AIGC 分析接口,把 URL 和 headers 换掉即可,MT5 高风险品种上务必先开模拟盘验证返回格式。
class CHttpRequest { class="kw">private: CURL *m_url; CHttpBody *m_body; CHttpHeader *m_headers; CHttpMethod *m_method; class="type">int m_timeout; class="kw">public: CHttpRequest(class="type">void); ~CHttpRequest(class="type">void); }; CHttpRequest::CHttpRequest(class="type">void) { m_url = new CURL(); m_body = new CHttpBody(); m_headers = new CHttpHeader(); m_method = new CHttpMethod(); m_timeout = class="num">5000; class=class="str">"cmt">// Default timeout(class="num">5 seconds) } CHttpRequest::~CHttpRequest(class="type">void) { class="kw">delete m_url; class="kw">delete m_body; class="kw">delete m_headers; class="kw">delete m_method; }