Connexus请求解析(第六部分):创建HTTP请求与响应·综合运用
「把 HTTP 响应拆成可操作对象」
在 MT5 里做 REST 拉取时,响应不能只当字符串看。CHttpResponse 这个类把一次回包拆成头、体、状态码和耗时四个独立句柄,调用方按需取用,不必自己切文本。 下面这段声明定义了对外接口:Header() 返回 CHttpHeader 指针,Body() 返回 CHttpBody 指针,StatusCode() 返回 CHttpStatusCodes 指针;Duration(ulong) 写耗时、Duration(void) 读耗时,单位是微秒级 ulong。Clear() 清数据,FormatString() 拼可读串。 [CODE] 里的 Header() 实现只有一行:return(GetPointer(m_header));。GetPointer 拿的是对象指针而非拷贝,意味着你改了返回对象,类内成员同步变——这点在外挂缓存响应头时要小心,别误写。 实盘接行情网关或 AIGC 分析接口,先 Duration(void) 打点,若回包耗时连续 > 500000 ulong(约 0.5 秒)可能说明网络或远端抖动,外汇与贵金属品种本身高杠杆高风险,接口延迟会放大滑点概率。
class=class="str">"cmt">//| class : CHttpResponse | class=class="str">"cmt">//| | class=class="str">"cmt">//| [PROPERTY] | class=class="str">"cmt">//| Name : CHttpResponse | class=class="str">"cmt">//| Heritage : No heritage | class=class="str">"cmt">//| Description : gathers elements of an http response such as body, | class=class="str">"cmt">//| header, status code and duration | class=class="str">"cmt">//| | class=class="str">"cmt">//+------------------------------------------------------------------+ class CHttpResponse { class="kw">public: class=class="str">"cmt">//--- HTTP CHttpHeader *Header(class="type">void); class=class="str">"cmt">// Get header object CHttpBody *Body(class="type">void); class=class="str">"cmt">// Get body object CHttpStatusCodes *StatusCode(class="type">void); class=class="str">"cmt">// Get status code object class=class="str">"cmt">//--- Duration class="type">void Duration(class="type">ulong duration); class=class="str">"cmt">// Set duration class="type">ulong Duration(class="type">void); class=class="str">"cmt">// Get duration class=class="str">"cmt">//--- Auxiliary methods class="type">void Clear(class="type">void); class=class="str">"cmt">// Reset data class="type">class="kw">string FormatString(class="type">void); class=class="str">"cmt">// Format data }; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Get header object | class=class="str">"cmt">//+------------------------------------------------------------------+ CHttpHeader *CHttpResponse::Header(class="type">void) { class="kw">return(GetPointer(m_header)); } class=class="str">"cmt">//+------------------------------------------------------------------+
◍ 响应对象怎么把 HTTP 回包拆开看
在 MT5 里做 REST 调用,CHttpResponse 这个类负责把服务器回包封成一个可操作对象。它不像裸字符串那样难用,而是把 body、状态码、耗时拆成独立接口,方便你直接喂给小布类 AIGC 分析模块。 Body() 与 StatusCode() 都返回指针:Body() 给的是 CHttpBody 实例,StatusCode() 给的是 CHttpStatusCodes 实例。这样你能分别取回包正文和 HTTP 状态码,不用自己切字符串。 Duration(ulong) 是写入耗时,Duration(void) 是读出耗时,单位是毫秒。回测或实盘里若发现某次请求 Duration 超过 2000ms,可能说明网关抖动或 VPS 到 API 的链路质量差。 Clear() 会重置全部字段,并把状态码强制设为 HTTP_STATUS_URL_NOT_ALLOWED(即 446 这个 MQL5 内部常量)。如果你复用同一个 response 对象连发多请求,记得每次先 Clear,否则旧 body 可能混进新解析。 FormatString() 把整个响应拼成可读文本:先打 Status Code 和 Duration(ms),再分段输出 Headers 与 Body。调试时直接 Print(response.FormatString()),MT5 Experts 日志里就能看到完整回包结构。 下面两段是最小可用示例。例1 发 GET 拉符号表,例2 发 POST 把 EURUSD 现价 1.08312 推给接口——注意 Body().AddToString() 里 JSON 必须转义双引号。
class=class="str">"cmt">//| Get body object | class=class="str">"cmt">//+------------------------------------------------------------------+ CHttpBody *CHttpResponse::Body(class="type">void) { class="kw">return(GetPointer(m_body)); }; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Get status code object | class=class="str">"cmt">//+------------------------------------------------------------------+ CHttpStatusCodes *CHttpResponse::StatusCode(class="type">void) { class="kw">return(GetPointer(m_status_code)); }; class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Set duration | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void CHttpResponse::Duration(class="type">ulong duration) { m_duration = duration; } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Get duration | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">ulong CHttpResponse::Duration(class="type">void) { class="kw">return(m_duration); } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Reset data | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">void CHttpResponse::Clear(class="type">void) { m_header.Clear(); m_body.Clear(); m_status_code.SetStatusCode(HTTP_STATUS_URL_NOT_ALLOWED); } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//| Format data | class=class="str">"cmt">//+------------------------------------------------------------------+ class="type">class="kw">string CHttpResponse::FormatString(class="type">void) { class="kw">return( "HTTP Response:"+ "\n---------------"+ "\nStatus Code: "+m_status_code.GetStatusCodeFormat()+ "\nDuration: "+IntegerToString(m_duration)+" ms"+ "\n"+ "\n---------------"+ "\nHeaders:"+ "\n"+m_header.Serialize()+ "\n---------------"+ "\nBody:"+ "\n"+m_body.GetAsString()+ "\n---------------" ); } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//--- Example class="num">1 - GET CHttpRequest request; request.Method() = HTTP_METHOD_GET; request.Url().Parse("http:class=class="str">"cmt">//example.com/api/symbols"); class=class="str">"cmt">//--- Example class="num">2 - POST CHttpRequest request; request.Method() = HTTP_METHOD_POST; request.Url().Parse("http:class=class="str">"cmt">//example.com/api/symbols"); request.Body().AddToString("{\"EURUSD\":class="num">1.08312}");
用 DELETE 方法撤掉指定品种订阅
在 MQL5 里做 REST 交互,除了 GET 和 POST,撤资源常用 HTTP_METHOD_DELETE。上面这段把请求方法切到 DELETE,并指向带查询参数的接口地址,语义上就是让服务端删掉 EURUSD 这条订阅记录。 注意 Url().Parse 里把 symbol=EURUSD 拼在查询串,服务端通常据此定位要删的对象;若漏掉参数,大概率返回 404 或 400。实盘接行情网关时,这种调用失败不会报交易错,只在 HttpCode 里留痕,得自己查。 外汇与贵金属接口调用属高风险操作,误删订阅可能让盯盘脚本瞬间失联,动手前先在模拟环境跑通再上真号。
request.Header().Add("content-type","application/json"); class=class="str">"cmt">//--- Example class="num">3 - DELETE CHttpRequest request; request.Method() = HTTP_METHOD_DELETE; request.Url().Parse("http:class=class="str">"cmt">//example.com/api/symbols?symbol=EURUSD");
「别急着下结论」
把 HTTP 请求的所有组件塞进一个 CHttpRequest 对象,代码可读性、复用性和维护成本确实会好很多。Connexus 里套了一层外观模式,把底层拼请求的脏活藏起来,开发者调一个接口就能发出完整请求;CHttpResponse 也按同样思路封装,取响应字段不再需要自己拆字符串。 下一层要落地的是传输层:它吃进 CHttpRequest,转成 MT5 自带的 WebRequest 函数发出去,再把返回数据包成 CHttpResponse 交回来。这套结构在样例 ZIP(29.13 KB)里已经能跑通基础请求,外汇与贵金属行情接口调用属高风险操作,实盘前务必在策略测试器里验证超时与异常分支。 等传输层那篇出来,整个库的请求—响应闭环才真正完整,届时你可以直接把 Connexus 挂到自己的 EA 里替你跑行情拉取。