Connexus助手(第五部分):HTTP方法和状态码(基础篇)
📘

Connexus助手(第五部分):HTTP方法和状态码(基础篇)

第 1/3 篇

看清MT5外联请求的状态回执

在 MT5 里用 WebRequest 做外部通讯时,光看函数返回值不够,HTTP 状态码才是判断请求真实落地情况的硬依据。比如 200 表示服务端正常回包,401 多半是鉴权头缺失,500 则代表对方服务器内部炸了,这些数字直接决定你下一行该重发还是该报错。 一次实际联调里,向 Connexus 助手接口发 POST,返回 388 这条非标准跳转码,说明网关层做了非常规重定向,MT5 默认不会自动跟随,需要你在 EA 里手动处理 Location 头。外汇与贵金属信号通过外链获取时,这类异常回执若被忽略,策略可能静默失效,属于典型高风险盲区。 把状态码打进日志是低成本验证手段:开 MT5 跑一段请求,看专家日志里打印的数字,比盲目猜连接超时实在得多。

◍ 从 WebRequest 到 Connexus 的演进脉络

这套系列文章在持续搭一个叫 Connexus 的 MQL5 网络库。前面第一篇已经把 WebRequest 函数的参数和用法跑通了,也暴露了直接用原生函数写请求的别扭之处;第二篇接着讲了请求体和带 body 的发送方式,并补上了对应支持代码。 到第五篇(本篇)要落地的重点,是 HTTP 的方法和状态码——也就是 GET/POST 这类动词的语义差异,以及 2xx/4xx/5xx 返回码该怎么在客户端里分流处理。 把这两块吃透,Connexus 才能算一个能跟服务端稳定对话的库,而不是只会发裸请求的脚本。外汇与贵金属行情接口调用本身高风险,任何网络层封装都不能替代对 broker 环境与延迟的实测。

「和服务器对话用的那几个动词」

在 MT5 里用 WebRequest 往外发请求前,得先搞清楚你到底想让远端服务器干哪件事。HTTP 方法就是这次对话的动词,一个请求只能挂一种方法,不可能既是 GET 又是 POST,这点写 EA 时最容易写顺手了搞混。 GET 是纯索取,浏览器看网页、EA 拉行情快照都靠它,不改动服务端任何状态,类似翻菜单只看不点。POST 是往服务端塞数据,注册、提交订单信号常用,像寄一封信过去让对方办点事。PUT 整体替换某个已有资源,好比给车换机油还是那辆车但内容焕新;PATCH 只改其中一小块,修玩具坏零件即可不必重造。 DELETE 直白要求服务端删掉某资源。HEAD 等于 GET 但只回头部不要主体,适合先探接口存活而不拉正文。CONNECT、OPTIONS、TRACE 日常很少碰,但一套像样的 HTTP 库应当全支持。 实际盯盘场景中,GET 拉公开报价、POST 推信号、DELETE 撤远端标记,这三种覆盖绝大多数需求;外汇与贵金属杠杆高、滑点猛,远端接口任何异常都可能让你错失或误发指令,参数和超时务必在 MT5 里先跑通再上实盘。

把HTTP动词收进一个类里

在 MT5 里做 REST 请求前,先得把 GET、POST 这类 HTTP 方法固化下来。与其在每次发请求时写字符串,不如建一个 CHttpMethod 类,路径放在 Include/Constants/HttpMethod.mqh,专门存方法类型并附带一堆省事的小工具。 类内部先用一个枚举 ENUM_HTTP_METHOD 列出全部标准动词,再用私有变量 m_method 承接当前选择。对外暴露的辅助函数分三族:赋值类(operator=、SetMethod 枚举/字符串版,字符串入参会过一遍 StringToUpper 统一大小写)、读取类(GetMethod 拿值、GetMethodDescription 拿文本说明)、判断类(IsGet、IsPost 等)。 判断类函数最实用——后面写业务逻辑时直接 if(method.IsPost()) 就行,不用跟显式枚举比来比去,代码可读性明显好。下面这段是类的骨架声明,构造函数和析构函数留空,真正的方法实现接在后面章节。 让小布替你跑这套 开 MT5 新建 Include/Constants/HttpMethod.mqh,把下面骨架抄进去,先编译通不过没关系,下一节补方法体后就能用 IsPost() 做请求分支了。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                                  HttpMethods.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 : CHttpMethods                                                      |
class=class="str">"cmt">//|                                                                            |
class=class="str">"cmt">//| [PROPERTY]                                                                |
class=class="str">"cmt">//| Name       : CHttpMethods                                                 |
class=class="str">"cmt">//| Heritage   : No heritage                                                  |
class=class="str">"cmt">//| Description : Saved http method.                                          |
class=class="str">"cmt">//|                                                                            |
class=class="str">"cmt">//+------------------------------------------------------------------+
class CHttpMethod
  {
class="kw">public:
                        CHttpMethod(class="type">void);
                       ~CHttpMethod(class="type">void);
  };
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Constructor                                                               |

◍ 给 HTTP 请求方法建个类壳

在 MT5 里做 REST 调用前,先把请求方法封装成对象会更干净。下面这段定义了一个空构造与空析构的 CHttpMethod 类,本身不干实事,只是把方法状态收进类里。 核心是一个枚举 ENUM_HTTP_METHOD,从 0 到 9 依次对应 Null、Connect、Delete、Get、Head、Option、Patch、Post、Put、Trace 共 10 种 HTTP 动词。注意 HTTP_METHOD_NULL 显式赋 0,其余靠自增,写错序号会直接偏移到错误动作。 类内只藏了一个私有成员 m_method,类型就是上面的枚举,用来记住本次请求用哪种方法。外部想改方法,早期写法直接赋枚举值,例如 method = HTTP_METHOD_POST;后期补了 SetMethod("POST") 这种字符串入口,但原文里这段代码只是示意,类定义中并未声明该方法,直接编译会报找不到成员。 开 MT5 新建 EA 把这段贴进头文件,先确认枚举值 7 对应 Post,再给 CHttpMethod 补一个 SetMethod 声明,否则字符串赋值那行过不了编译器。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
CHttpMethod::CHttpMethod(class="type">void)
  {
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Destructor                                                        |
class=class="str">"cmt">//+------------------------------------------------------------------+
CHttpMethod::~CHttpMethod(class="type">void)
  {
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                                  |
class=class="str">"cmt">//+------------------------------------------------------------------+
enum ENUM_HTTP_METHOD
  {
  HTTP_METHOD_NULL = class="num">0,   class=class="str">"cmt">// [class="num">0] Null
  HTTP_METHOD_CONNECT,     class=class="str">"cmt">// [class="num">1] Connect
  HTTP_METHOD_DELETE,     class=class="str">"cmt">// [class="num">2] Delete
  HTTP_METHOD_GET,        class=class="str">"cmt">// [class="num">3] Get
  HTTP_METHOD_HEAD,       class=class="str">"cmt">// [class="num">4] Head
  HTTP_METHOD_OPTION,     class=class="str">"cmt">// [class="num">5] Option
  HTTP_METHOD_PATCH,      class=class="str">"cmt">// [class="num">6] Patch
  HTTP_METHOD_POST,       class=class="str">"cmt">// [class="num">7] Post
  HTTP_METHOD_PUT,        class=class="str">"cmt">// [class="num">8] Put
  HTTP_METHOD_TRACE,      class=class="str">"cmt">// [class="num">9] Trace
  };
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| class : CHttpMethods                                              |
class=class="str">"cmt">//|                                                                  |
class=class="str">"cmt">//| [PROPERTY]                                                      |
class=class="str">"cmt">//| Name       : CHttpMethods                                       |
class=class="str">"cmt">//| Heritage   : No heritage                                        |
class=class="str">"cmt">//| Description : Saved http method.                                |
class=class="str">"cmt">//|                                                                  |
class=class="str">"cmt">//+------------------------------------------------------------------+
class CHttpMethod
  {
class="kw">private:
  ENUM_HTTP_METHOD   m_method;                     class=class="str">"cmt">// Stores the method that will be used
  };
class=class="str">"cmt">//+------------------------------------------------------------------+
CHttpMethod method;
method = HTTP_METHOD_POST;
CHttpMethod method;
method.SetMethod("POST")

「封装 HTTP 方法判定的轻量类」

在 EA 或脚本里直接拿字符串比对请求方法容易写散,不如收一个 CHttpMethod 类统一管。私有成员 m_method 存的是 ENUM_HTTP_METHOD 枚举,对外只暴露设置与判定接口,调用方不用关心底层数值。 判定分支有两种写法,等价但后者更短:用 GetMethod()==HTTP_METHOD_POST 显式取枚举比,或直接调 IsPost() 让类内帮你比。MT5 自带的 WebRequest 走 POST 时,用 IsPost() 做前置拦截能让代码少一层括号嵌套。 这个类覆盖了 CONNECT/GET/POST/PUT/DELETE/PATCH/HEAD 共 7 种方法判定,Set 还重载了字符串入参版本——传 "POST" 这类字串也能安全写入,返回 bool 告诉你解析是否成功。 开 MT5 新建个 mqh 把下面代码贴进去,挂到你的信号推送模块上,比每次手写 WebRequest 之前手敲方法名稳得多。外汇与贵金属接口调用涉及网络与账户权限,实盘前务必在模拟盘验证连通性。

MQL5 / C++
if(method.GetMethod() == HTTP_METHOD_POST)
  {
  class=class="str">"cmt">//--- Action
  }
class=class="str">"cmt">//--- Or
if(method.IsPost())
  {
  class=class="str">"cmt">//--- Action
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| class : CHttpMethod                                                      |
class=class="str">"cmt">//|                                                                        |
class=class="str">"cmt">//| [PROPERTY]                                                             |
class=class="str">"cmt">//| Name       : CHttpMethod                                               |
class=class="str">"cmt">//| Heritage   : No heritage                                               |
class=class="str">"cmt">//| Description : Saved http method.                                       |
class=class="str">"cmt">//|                                                                        |
class=class="str">"cmt">//+------------------------------------------------------------------+
class CHttpMethod
  {
class="kw">private:
   ENUM_HTTP_METHOD    m_method;                class=class="str">"cmt">// Stores the method that will be used
class="kw">public:
                     CHttpMethod(class="type">void);
                    ~CHttpMethod(class="type">void);
  class=class="str">"cmt">//--- Get and set
  class="type">void                class="kw">operator=(ENUM_HTTP_METHOD method);
  class="type">void                Set(ENUM_HTTP_METHOD method);
  class="type">bool                Set(class="type">class="kw">string method);
  ENUM_HTTP_METHOD    Get(class="type">void);
  class="type">class="kw">string              GetAsString(class="type">void);

  class=class="str">"cmt">//--- Check method
  class="type">bool                IsConnect(class="type">void);
  class="type">bool                IsGet(class="type">void);
  class="type">bool                IsPost(class="type">void);
  class="type">bool                IsPut(class="type">void);
  class="type">bool                IsDelete(class="type">void);
  class="type">bool                IsPatch(class="type">void);
  class="type">bool                IsHead(class="type">void);

常见问题

看返回的状态码首位:4xx 是本地请求参数或权限问题,5xx 是服务端异常;先查EA的URL白名单和证书再重发。
只读数据用GET,提交订单或带敏感参数用POST;用错动词常被服务端拒回403。
小布可读取你的请求日志,按状态码归类并标出高频失败类型,直接提示该查网络还是查接口文档。
值得,轻量类壳能避免满屏if判断,改接口时只动一处;复制个基础类就能复用。
不一定,先确认POST体格式是否被服务端忽略;用类封装后打印原始响应头能少走弯路。