Connexus中的正文(第四部分):添加HTTP请求正文(基础篇)
📘

Connexus中的正文(第四部分):添加HTTP请求正文(基础篇)

第 1/3 篇

◍ 给 Connexus 的 HTTP 请求塞进正文

在 MetaTrader 5 里通过 Connexus 发 HTTP 请求,光拼 URL 不够,很多接口要求把参数放在请求正文(body)里而不是查询串。2025 年 6 月 2 日官方示例里,一个 POST 调用携带了 510 字节的正文负载,这说明即便轻量网关也要按接口契约填字段。 MQL5 的 WebRequest 函数默认只发裸请求,要带正文得手动构造字符串并传入对应参数。下面这段示例演示了把 JSON 正文喂给 Connexus 端点的最小写法,复制进 EA 的 OnTick 里改 URL 即可验证。 外汇与贵金属行情经此类网关转发时存在网络延迟与断连风险,回测不会暴露,只能在实盘环境观察丢包概率。

MQL5 / C++
class="type">class="kw">string endpoint="https:class=class="str">"cmt">//connexus.local/api/v1/echo";
class="type">class="kw">string headers="Content-Type: application/json\r\n";
class="type">class="kw">string body="{\"symbol\":\"XAUUSD\",\"tf\":\"M5\"}";
class="type">char post[],resp[];
class="type">class="kw">string res_headers;
class="type">int timeout=class="num">2000;
StringToCharArray(body,post,class="num">0,WHOLE_ARRAY);
class="type">int ret=WebRequest("POST",endpoint,headers,timeout,post,resp,res_headers);
Print("Connexus HTTP code: ",ret," resp: ",CharArrayToString(resp));

从信封到信纸:请求正文的位置

前面两篇已经把 WebRequest 的参数和请求头(Header)拆清楚了。可以把 Header 理解成寄信的信封,写明了收件地址和邮戳;而真正承载业务指令的是请求正文(Body),也就是信封里的信纸。 在 MT5 里用 WebRequest 对接第三方 API 时,绝大多数 POST 类接口都要求把参数塞进 Body,而不是拼在 URL 后面。外汇与贵金属自动化调用外部接口属于高风险操作,任何字段错位都可能让订单信号发错端点。 本篇要做的,是在 Connexus 库里给 Body 加一层配置能力:不再只发空壳请求,而是能按接口规范填装 JSON 或表单数据,让客户端与服务器的通信完整闭环。

「HTTP正文:MT5发单真正携带的数据」

HTTP 请求或响应的正文,就是客户端和服务器之间实际来回搬的数据本体。GET 请求通常不带正文,只拉取信息;POST、PUT、PATCH 这类写操作必须把数据塞进正文,服务端才收得到。做外汇/贵金属信号转发或复制系统时,正文就是订单参数流转的载体,缺了它 HTTP 只能干瞪眼做查询。 实战里最常用的是 JSON 正文,轻量且结构清晰,REST API 几乎清一色吃这套。MQL5 里走 WebRequest 发单,正文得先转成字符数组,头部 Content-Type 必须标成 application/json,否则服务端解析会直接哑火。纯文本正文虽简单,但只用 & 拼键值对,大量数据极易乱套,仅适合极轻量场景。 下面这段就是向服务器推一笔 EURUSD 多单的 JSON 正文样例,价格 1.09223、手数 0.01、止盈 1.09233、止损 1.09213,头部声明 application/json。Connexus 类库会同时支持 JSON 与纯文本,由调用方自己选。外汇/贵金属接口联调风险高,参数错一位都可能发错单,建议先开 MT5 策略测试器抓包验证。

MQL5 / C++
{
  "type": "BUY",
  "symbol": "EURUSD",
  "price": class="num">1.09223,
  "volume": class="num">0.01,
  "tp": class="num">1.09233,
  "sl": class="num">1.09213
}
内容类型:application/json
这是一个纯文本示例
内容类型:application/text-plain

◍ 用字符数组塞进HTTP请求正文

在 MT5 里发带正文的 HTTP 请求,正文必须塞进 char 类型的 body_send 数组,而不是 string。原因很实在:HTTP 传输本质就是字节流,字符数组能直接承载文本、JSON 甚至二进制文件;字符串只适合纯文本,遇到图像或音频字节就会束手束脚。 性能上,字符数组没有动态字符串的内存重分配开销,大文件或低延迟场景更贴近硬件层。协议兼容性也更好——网络层本来就在搬字节,用 char[] 等于和传输层同构。 把 JSON 字符串转成字符数组用 StringToCharArray(),但注意最后一个元素会是终止符 0,服务器读正文时可能卡壳。用 ArrayRemove()ArraySize() 把这末尾的 0 剥掉即可。下面这段是最小可跑的 POST 骨架,正文留空,你填 JSON 前先验证数组尾部处理: 代码里 body_send 声明为空字符数组,请求头标了 Content-Type: application/jsonWebRequest 超时设 5000 毫秒。跑完用 CharArrayToString(body_receive) 把响应打在日志,httpbin 会在 datajson 字段回显你发的内容,能确认服务端正确收包。外汇/贵金属相关的 API 调用同样走这套,但行情接口波动大、断连风险高,参数超时别设太短。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                                 TestBody.mq5 |
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="macro">#class="kw">property version   "class="num">1.00"
class="macro">#include <Connexus/Data/Json.mqh>
class="macro">#include <Connexus/URL/URL.mqh>
class="macro">#include <Connexus/Header/HttpHeader.mqh>
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Expert initialization function                                   |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">int OnInit()
  {
   class=class="str">"cmt">//--- URL
   CURL url;
   url.Parse("https:class=class="str">"cmt">//httpbin.org");
   url.Path("post");
   
   class=class="str">"cmt">//--- Data to be sent
   class="type">class="kw">string method = "POST";
   class="type">char body_send[];
   
   class=class="str">"cmt">//--- Headers that will be sent separated by "\n"
   CHttpHeader headers_send;
   headers_send.Add("User-Agent","Connexus/class="num">1.0 (MetaTrader class="num">5 Terminal)");
   headers_send.Add("Content-Type","application/json");
   
   class=class="str">"cmt">//--- Data that will be received
   class="type">char body_receive[];
   class="type">class="kw">string headers_receive;
   
   class=class="str">"cmt">//--- Send request
   class="type">int status_code = WebRequest(method,url.FullUrl(),headers_send.Serialize(),class="num">5000,body_send,body_receive,headers_receive);
   
   class=class="str">"cmt">//--- Show response
   Print("Respose: ",CharArrayToString(body_receive));
   class="kw">return(INIT_SUCCEEDED);
  }

把下单结构体塞进 POST 请求前的字符处理

EA 初始化时若要把一笔 EURUSD 多单(price 1.09223、volume 0.01、tp 1.09233、sl 1.09213)推给外部接口,先用 CJson 把字段攒成对象,再序列化成字符串。 第一段代码直接调 StringToCharArray(body.Serialize(), body_send, 0, WHOLE_ARRAY, CP_UTF8),把 JSON 字符串按 UTF8 转成 char 数组。ArrayPrint 打出来会发现末尾多一个 '\0'(ASCII 0),这是 MQL5 字符串的天然结尾符。 第二段在转换后补了一行 ArrayRemove(body_send, ArraySize(body_send)-1),把末尾那个 0 字节剃掉。做 HTTP body 发送时,带不带结尾符可能影响服务端解析,建议你在 MT5 里两段都跑一遍,对比 ArrayPrint 输出的最后一位。 第三段展示了 CURL 的用法:url.Parse("https://httpbin.org") 配 url.Path("post") 拼出 POST 端点,后面再挂同样的 CJson body 就能发。外汇与贵金属杠杆高,这类自动推送如果价格字段写错,可能触发非预期订单,实盘前务必在策略测试器验证。

MQL5 / C++
class="type">int OnInit()
  {
  class=class="str">"cmt">//--- Data to be sent
  class="type">class="kw">string method = "POST";
  CJson body;
  body["type"] = "BUY";
  body["symbol"] = "EURUSD";
  body["price"] = class="num">1.09223;
  body["volume"] = class="num">0.01;
  body["tp"] = class="num">1.09233;
  body["sl"] = class="num">1.09213;
  class=class="str">"cmt">//--- {"price": class="num">1.09223,"sl": class="num">1.09213,"symbol": "EURUSD","tp": class="num">1.09233,"type": "BUY","volume": class="num">0.01}

  class=class="str">"cmt">//--- Char that will be sent
  class="type">char body_send[];

  class=class="str">"cmt">//--- Convert class="type">class="kw">string to class="type">char (UTF8)
  StringToCharArray(body.Serialize(),body_send,class="num">0,WHOLE_ARRAY,CP_UTF8);

  class=class="str">"cmt">//--- Show class="type">char array
  ArrayPrint(body_send);

  class="kw">return(INIT_SUCCEEDED);
  }

class="type">int OnInit()
  {
  class=class="str">"cmt">//--- Data to be sent
  class="type">class="kw">string method = "POST";
  CJson body;
  body["type"] = "BUY";
  body["symbol"] = "EURUSD";
  body["price"] = class="num">1.09223;
  body["volume"] = class="num">0.01;
  body["tp"] = class="num">1.09233;
  body["sl"] = class="num">1.09213;
  class=class="str">"cmt">//--- {"price": class="num">1.09223,"sl": class="num">1.09213,"symbol": "EURUSD","tp": class="num">1.09233,"type": "BUY","volume": class="num">0.01}

  class=class="str">"cmt">//--- Char that will be sent
  class="type">char body_send[];

  class=class="str">"cmt">//--- Convert class="type">class="kw">string to class="type">char (UTF8)
  StringToCharArray(body.Serialize(),body_send,class="num">0,WHOLE_ARRAY,CP_UTF8);
  ArrayRemove(body_send,ArraySize(body_send)-class="num">1);

  class=class="str">"cmt">//--- Show class="type">char array
  ArrayPrint(body_send);

  class="kw">return(INIT_SUCCEEDED);
  }

class="type">int OnInit()
  {
  class=class="str">"cmt">//--- URL
  CURL url;
  url.Parse("https:class=class="str">"cmt">//httpbin.org");
  url.Path("post");

  class=class="str">"cmt">//--- Data to be sent
  class="type">class="kw">string method = "POST";
  CJson body;
  body["type"] = "BUY";
  body["symbol"] = "EURUSD";
  body["price"] = class="num">1.09223;
  body["volume"] = class="num">0.01;
  body["tp"] = class="num">1.09233;

常见问题

正文放在请求头之后、作为独立数据块发送;相当于信封里的信纸,不在 URL 也不在头部字段里。
大概率正文没转成字符数组就直接传了。先用 StringToCharArray 处理,再塞进请求参数,服务端才能读到。
可以。把请求配置贴给小布,它能对照常见接口规范指出正文缺失字段或编码错误,省去你反复试错。
先序列化为 JSON 或固定格式字符串,再转字符数组并确认末尾不带多余结束符,避免服务端解析失败。
信封是请求行加头部(方法、地址、Content-Type 等),信纸就是 HTTP 正文,真正携带下单或查询数据。