Connexus请求解析(第六部分):创建HTTP请求与响应·综合运用
📘

Connexus请求解析(第六部分):创建HTTP请求与响应·综合运用

第 3/3 篇

「把 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 秒)可能说明网络或远端抖动,外汇与贵金属品种本身高杠杆高风险,接口延迟会放大滑点概率。

MQL5 / C++
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 必须转义双引号。

MQL5 / C++
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 里留痕,得自己查。 外汇与贵金属接口调用属高风险操作,误删订阅可能让盯盘脚本瞬间失联,动手前先在模拟环境跑通再上真号。

MQL5 / C++
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 里替你跑行情拉取。

常见问题

先把响应体按约定格式(如 JSON)解析成对象,再按字段名取值;别整体当字符串硬匹配,容易漏更新。
在请求里带准要撤的订阅标识(如品种代码),确认返回状态码为成功再认为已取消,避免重复订阅占用额度。
小布可以替你跑通请求与响应解析流程,自动标出订阅状态和异常回包,你只看结论就行。
可能是服务端回了空数据或字段名对不上;先打印原始响应体核对,再查解析映射是否漏了可选字段。
隔几分钟看是否还收到该品种推送,或调一次订阅列表接口比对,列表里没了才算撤干净。