Connexus助手(第五部分):HTTP方法和状态码·综合运用
📘

Connexus助手(第五部分):HTTP方法和状态码·综合运用

第 3/3 篇

◍ HTTP 5xx 状态码与封装类设计

在 MT5 通过 WebRequest 对接外部行情或信号服务时,服务端返回 5xx 表示网关或服务器侧异常。常见的高位状态码包括 504 网关超时、505 协议版本不支持、506 协商变体、507 存储不足、508 环路检测、510 未扩展、511 网络认证要求,这些数字直接对应枚举值,可用于判断请求失败的性质。 下面这段类把状态码收进一个对象里,避免散落各处用裸 int 比较。私有成员 m_status 存当前状态,公有接口提供 int 与枚举两种赋值重载,以及 Get 取枚举、GetMessage 取描述文本。 构造与析构目前为空实现,说明该类只做轻量状态容器,不持有连接资源。实盘调用 WebRequest 后,把返回码喂给 CHttpStatusCodes,就能在 EA 日志里统一输出人类可读的失败原因,而不是一堆看不懂的数字。

MQL5 / C++
  HTTP_STATUS_GATEWAY_TIMEOUT = class="num">504,
  HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED = class="num">505,
  HTTP_STATUS_VARIANT_ALSO_NEGOTIATES = class="num">506,
  HTTP_STATUS_INSUFFICIENT_STORAGE = class="num">507,
  HTTP_STATUS_LOOP_DETECTED = class="num">508,
  HTTP_STATUS_NOT_EXTENDED = class="num">510,
  HTTP_STATUS_NETWORK_AUTHENTICATION_REQUIRED = class="num">511
  };
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| class : CHttpStatusCodes                                          |
class=class="str">"cmt">//|                                                                        |
class=class="str">"cmt">//| [PROPERTY]                                                             |
class=class="str">"cmt">//| Name     : CHttpStatusCodes                                            |
class=class="str">"cmt">//| Heritage : No heritage                                                 |
class=class="str">"cmt">//| Description : Saved http status code.                                  |
class=class="str">"cmt">//|                                                                        |
class=class="str">"cmt">//+------------------------------------------------------------------+
class CHttpStatusCodes
  {
class="kw">private:
  ENUM_HTTP_STATUS    m_status;             class=class="str">"cmt">// Stores the status used

class="kw">public:
                    CHttpStatusCodes(class="type">void);
                   ~CHttpStatusCodes(class="type">void);
  class=class="str">"cmt">//--- Set
  class="type">void              class="kw">operator=(class="type">int status);
  class="type">void              class="kw">operator=(ENUM_HTTP_STATUS status);
  class="type">void              Set(ENUM_HTTP_STATUS status);

  class=class="str">"cmt">//--- Get
  ENUM_HTTP_STATUS  Get(class="type">void);
  class="type">class="kw">string            GetMessage(class="type">void);
  };
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Constructor                                                          |
class=class="str">"cmt">//+------------------------------------------------------------------+
CHttpStatusCodes::CHttpStatusCodes(class="type">void)
  {
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Destructor                                                           |

HTTP 状态封装类的赋值与取数逻辑

在 MT5 里做 WebRequest 调用外部行情或信号接口时,返回码的处理最好收口到一个类里。下面这段 CHttpStatusCodes 的实现,把整数和枚举两种状态来源都接住了,避免散落在 EA 各处做强制转换。 析构函数 CHttpStatusCodes::~CHttpStatusCodes(void) 是空的,说明这个类不持有需要手动释放的资源,轻量可直接栈上用。两个重载的 operator= 分别吃 int 和 ENUM_HTTP_STATUS:前者把整型先强转成枚举再存进 m_status,后者直接赋值,写代码时无论拿到的是 WebRequest 的原始 int 还是自己定义的枚举都能一句搞定。 Set(ENUM_HTTP_STATUS status) 与 Get(void) 是一对最朴素的存取器,Get 直接 return m_status,没有做越界校验——这意味着如果你塞了一个枚举外的值进去,取出来也不会报错,调试时容易踩坑。 GetMessage(void) 用 switch 把 m_status 映射成可读字符串。目前已覆盖的码里,HTTP_STATUS_URL_NOT_ALLOWED 对应“URL 未加入终端白名单”,HTTP_STATUS_OK 返回“OK”,HTTP_STATUS_PARTIAL_CONTENT 返回“Partial Content”等。注意 switch 在原文中列到 HTTP_STATUS_MULTIPLE_CHOICES 就断了,说明这个类在截取片段时尚未写完所有 3xx~5xx 分支,实盘复制前需补齐全量枚举映射,否则未知状态会落到默认返回空串。 外汇与贵金属行情接口调用受网络与经纪商限制,白名单漏配会直接触发 URL_NOT_ALLOWED,这类错误概率不低,建议上线前在策略测试器外先用脚本跑一次连通性。

MQL5 / C++
CHttpStatusCodes::~CHttpStatusCodes(class="type">void)
  {
  }
class="type">void CHttpStatusCodes::class="kw">operator=(class="type">int status)
  {
   m_status = (ENUM_HTTP_STATUS)status;
  }
class="type">void CHttpStatusCodes::class="kw">operator=(ENUM_HTTP_STATUS status)
  {
   m_status = status;
  }
class="type">void CHttpStatusCodes::Set(ENUM_HTTP_STATUS status)
  {
   m_status = status;
  }
ENUM_HTTP_STATUS CHttpStatusCodes::Get(class="type">void)
  {
   class="kw">return(m_status);
  }
class="type">class="kw">string CHttpStatusCodes::GetMessage(class="type">void)
  {
   class="kw">switch(m_status)
     {
     case HTTP_STATUS_URL_NOT_ALLOWED:
       class="kw">return "The URL was not added to the list of allowed URLs in the terminal";
     case HTTP_STATUS_URL_NOT_DEFINED:
       class="kw">return "URL was not defined in the request";
     case HTTP_STATUS_METHOD_NOT_DEFINED:
       class="kw">return "Method was not defined in the request";
     case HTTP_STATUS_CONTINUE:
       class="kw">return "Continue";
     case HTTP_STATUS_SWITCHING_PROTOCOLS:
       class="kw">return "Switching Protocols";
     case HTTP_STATUS_PROCESSING:
       class="kw">return "Processing";
     case HTTP_STATUS_EARLY_HINTS:
       class="kw">return "Early Hints";
     case HTTP_STATUS_OK:
       class="kw">return "OK";
     case HTTP_STATUS_CREATED:
       class="kw">return "Created";
     case HTTP_STATUS_ACCEPTED:
       class="kw">return "Accepted";
     case HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION:
       class="kw">return "Non-Authoritative Information";
     case HTTP_STATUS_NO_CONTENT:
       class="kw">return "No Content";
     case HTTP_STATUS_RESET_CONTENT:
       class="kw">return "Reset Content";
     case HTTP_STATUS_PARTIAL_CONTENT:
       class="kw">return "Partial Content";
     case HTTP_STATUS_MULTI_STATUS:
       class="kw">return "Multi-Status";
     case HTTP_STATUS_ALREADY_REPORTED:
       class="kw">return "Already Reported";
     case HTTP_STATUS_MULTIPLE_CHOICES:

「HTTP 状态码的字符化映射」

在 MT5 的 WebRequest 封装函数里,把枚举型状态码转成可读字符串,是排查接口联通性的第一步。下面这段 switch 分支覆盖了从 3xx 重定向到 4xx 客户端错误的主要情形,直接 return 对应英文短语,方便在日志里肉眼定位。 例如 HTTP_STATUS_MOVED_PERMANENTLY 返回 "Moved Permanently",HTTP_STATUS_NOT_FOUND 返回 "Not Found",HTTP_STATUS_REQUEST_TIMEOUT 返回 "Request Timeout"。实盘调用第三方行情或信号接口时,若日志频繁出现 "Forbidden" 或 "Unauthorized",大概率不是策略问题,而是密钥或 IP 白名单配置失效。 外汇与贵金属接口调用受网络与平台限制,高风险且可能因 broker 策略中断;建议把这段映射原样塞进 EA 的调试模块,开 MT5 跑一次模拟请求验证输出。

MQL5 / C++
      class="kw">return "Multiple Choices";
      case HTTP_STATUS_MOVED_PERMANENTLY:
         class="kw">return "Moved Permanently";
      case HTTP_STATUS_FOUND:
         class="kw">return "Found";
      case HTTP_STATUS_SEE_OTHER:
         class="kw">return "See Other";
      case HTTP_STATUS_NOT_MODIFIED:
         class="kw">return "Not Modified";
      case HTTP_STATUS_USE_PROXY:
         class="kw">return "Use Proxy";
      case HTTP_STATUS_SWITCH_PROXY:
         class="kw">return "Switch Proxy";
      case HTTP_STATUS_TEMPORARY_REDIRECT:
         class="kw">return "Temporary Redirect";
      case HTTP_STATUS_PERMANENT_REDIRECT:
         class="kw">return "Permanent Redirect";
      case HTTP_STATUS_BAD_REQUEST:
         class="kw">return "Bad Request";
      case HTTP_STATUS_UNAUTHORIZED:
         class="kw">return "Unauthorized";
      case HTTP_STATUS_PAYMENT_REQUIRED:
         class="kw">return "Payment Required";
      case HTTP_STATUS_FORBIDDEN:
         class="kw">return "Forbidden";
      case HTTP_STATUS_NOT_FOUND:
         class="kw">return "Not Found";
      case HTTP_STATUS_METHOD_NOT_ALLOWED:
         class="kw">return "Method Not Allowed";
      case HTTP_STATUS_NOT_ACCEPTABLE:
         class="kw">return "Not Acceptable";
      case HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED:
         class="kw">return "Proxy Authentication Required";
      case HTTP_STATUS_REQUEST_TIMEOUT:
         class="kw">return "Request Timeout";
      case HTTP_STATUS_CONFLICT:
         class="kw">return "Conflict";
      case HTTP_STATUS_GONE:
         class="kw">return "Gone";
      case HTTP_STATUS_LENGTH_REQUIRED:
         class="kw">return "Length Required";
      case HTTP_STATUS_PRECONDITION_FAILED:
         class="kw">return "Precondition Failed";
      case HTTP_STATUS_PAYLOAD_TOO_LARGE:
         class="kw">return "Payload Too Large";
      case HTTP_STATUS_URI_TOO_LONG:
         class="kw">return "URI Too Long";
      case HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE:
         class="kw">return "Unsupported Media Type";
      case HTTP_STATUS_RANGE_NOT_SATISFIABLE:
         class="kw">return "Range Not Satisfiable";
      case HTTP_STATUS_EXPECTATION_FAILED:

◍ HTTP 状态枚举的尾部映射

这段 switch 收口的是 4xx 与 5xx 区间里偏冷门的状态码,从 421 Misdirected Request 一直铺到 511 Network Authentication Required,每个 case 直接回吐英文短语,方便 EA 在日志里原样打印。 default 分支兜底返回 Unknown HTTP Status,意味着若经纪商网关回了非标准码(比如某些 CDN 夹层返回的 520),你的诊断函数不会崩,但也不会给你更多信息。 实际跑 MT5 时,这类映射常出现在 WebRequest 封装类里;若你发现日志频繁出现 Too Many Requests,大概率是对方 REST 接口限频,外汇/贵金属行情接口在高波动期可能触发,属正常风控,需降低轮询频率。

MQL5 / C++
      class="kw">return "Expectation Failed";
      case HTTP_STATUS_MISDIRECTED_REQUEST:
        class="kw">return "Misdirected Request";
      case HTTP_STATUS_UNPROCESSABLE_ENTITY:
        class="kw">return "Unprocessable Entity";
      case HTTP_STATUS_LOCKED:
        class="kw">return "Locked";
      case HTTP_STATUS_FAILED_DEPENDENCY:
        class="kw">return "Failed Dependency";
      case HTTP_STATUS_TOO_EARLY:
        class="kw">return "Too Early";
      case HTTP_STATUS_UPGRADE_REQUIRED:
        class="kw">return "Upgrade Required";
      case HTTP_STATUS_PRECONDITION_REQUIRED:
        class="kw">return "Precondition Required";
      case HTTP_STATUS_TOO_MANY_REQUESTS:
        class="kw">return "Too Many Requests";
      case HTTP_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE:
        class="kw">return "Request Header Fields Too Large";
      case HTTP_STATUS_UNAVAILABLE_FOR_LEGAL_REASONS:
        class="kw">return "Unavailable For Legal Reasons";
      case HTTP_STATUS_INTERNAL_SERVER_ERROR:
        class="kw">return "Internal Server Error";
      case HTTP_STATUS_NOT_IMPLEMENTED:
        class="kw">return "Not Implemented";
      case HTTP_STATUS_BAD_GATEWAY:
        class="kw">return "Bad Gateway";
      case HTTP_STATUS_SERVICE_UNAVAILABLE:
        class="kw">return "Service Unavailable";
      case HTTP_STATUS_GATEWAY_TIMEOUT:
        class="kw">return "Gateway Timeout";
      case HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED:
        class="kw">return "HTTP Version Not Supported";
      case HTTP_STATUS_VARIANT_ALSO_NEGOTIATES:
        class="kw">return "Variant Also Negotiates";
      case HTTP_STATUS_INSUFFICIENT_STORAGE:
        class="kw">return "Insufficient Storage";
      case HTTP_STATUS_LOOP_DETECTED:
        class="kw">return "Loop Detected";
      case HTTP_STATUS_NOT_EXTENDED:
        class="kw">return "Not Extended";
      case HTTP_STATUS_NETWORK_AUTHENTICATION_REQUIRED:
        class="kw">return "Network Authentication Required";
      class="kw">default:
        class="kw">return "Unknown HTTP Status";
    }
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| class : CHttpStatusCodes                                          |

把 HTTP 状态码收进一个类里判组

在 MT5 里用 WebRequest 拉外盘报价或新闻流时,返回的状态码决定你是该重发、还是直接报错停策略。下面这个类把状态码存成成员变量,再用几个布尔方法按区间归类,省得每次都在 EA 里写一堆 if 判断。 类里 m_status 是 ENUM_HTTP_STATUS 类型,构造和析构都是空实现,重点在五个判组函数:IsInformational 覆盖 100–199,IsSuccess 覆盖 200–299,IsRedirection 覆盖 300–399,IsClientError 覆盖 400–499,IsServerError 覆盖 500–599。 实盘接数据接口时,若 IsSuccess 返回 false 且 IsServerError 为 true,说明券商或数据商后端可能挂了,策略应倾向暂停请求而不是频繁重试,外汇和贵金属行情中断期间滑点风险显著放大。

MQL5 / C++
class=class="str">"cmt">//|                                                                              |
class=class="str">"cmt">//| [PROPERTY]                                                                     |
class=class="str">"cmt">//| Name       : CHttpStatusCodes                                                 |
class=class="str">"cmt">//| Heritage   : No heritage                                                      |
class=class="str">"cmt">//| Description : Saved http status code.                                         |
class=class="str">"cmt">//|                                                                              |
class=class="str">"cmt">//+------------------------------------------------------------------+
class CHttpStatusCodes
  {
class="kw">private:

   ENUM_HTTP_STATUS      m_status;                                             class=class="str">"cmt">// Stores the status used

class="kw">public:
                        CHttpStatusCodes(class="type">void);
                       ~CHttpStatusCodes(class="type">void);

   class=class="str">"cmt">//--- Check which group the code is in
   class="type">bool                 IsInformational(class="type">void);                                class=class="str">"cmt">// Checks if the status code is in the informational response range(class="num">100 - class="num">199)
   class="type">bool                 IsSuccess(class="type">void);                                      class=class="str">"cmt">// Check if the status code is in the success range(class="num">200 - class="num">299)
   class="type">bool                 IsRedirection(class="type">void);                                  class=class="str">"cmt">// Check if the status code is in the redirect range(class="num">300 - class="num">399)
   class="type">bool                 IsClientError(class="type">void);                                   class=class="str">"cmt">// Checks if the status code is in the client error range(class="num">400 - class="num">499)
   class="type">bool                 IsServerError(class="type">void);                                   class=class="str">"cmt">// Check if the status code is in the server error range(class="num">500 - class="num">599)
   };
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Constructor                                                            |
class=class="str">"cmt">//+------------------------------------------------------------------+
CHttpStatusCodes::CHttpStatusCodes(class="type">void)
  {
  }
class=class="str">"cmt">//+------------------------------------------------------------------+

「HTTP 状态码分类的析构与区间判定」

在 MT5 里封装 HTTP 响应处理时,CHttpStatusCodes 类的析构函数留空即可,因为该类通常只持有 m_status 整型成员,不申请堆内存,不需要手动释放资源。 真正的重点是五个布尔方法,把 m_status 按 RFC 7231 的区间直接映射成语义类别:100–199 是信息响应,200–299 是成功,300–399 是重定向,400–499 是客户端错误,500–599 是服务端错误。 这些判定没有复杂逻辑,就是边界比较。你在写 EA 调用 WebRequest 做行情中转或 AIGC 信号拉取时,用 IsSuccess() 过滤掉非 2xx 响应,能避免把 404 或 500 的空包当有效数据解析。 下面这段是类的析构与判定实现,逐行看:析构函数体为空;四个 Is* 方法均用 m_status 与硬编码上下界做 && 比较后 return。

MQL5 / C++
class=class="str">"cmt">//| Destructor                                                                 |
class=class="str">"cmt">//+------------------------------------------------------------------+
CHttpStatusCodes::~CHttpStatusCodes(class="type">void)
  {
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Checks if the status code is in the informational response         |
class=class="str">"cmt">//| range(class="num">100 - class="num">199)                                                 |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool CHttpStatusCodes::IsInformational(class="type">void)
  {
   class="kw">return(m_status >= class="num">100 && m_status <= class="num">199);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Check if the status code is in the success range(class="num">200 - class="num">299)       |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool CHttpStatusCodes::IsSuccess(class="type">void)
  {
   class="kw">return(m_status >= class="num">200 && m_status <= class="num">299);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Check if the status code is in the redirect range(class="num">300 - class="num">399)      |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool CHttpStatusCodes::IsRedirection(class="type">void)
  {
   class="kw">return(m_status >= class="num">300 && m_status <= class="num">399);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Checks if the status code is in the client error range             |
class=class="str">"cmt">//| (class="num">400 - class="num">499)                                                       |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool CHttpStatusCodes::IsClientError(class="type">void)
  {
   class="kw">return(m_status >= class="num">400 && m_status <= class="num">499);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Check if the status code is in the server error range(class="num">500 - class="num">599)  |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool CHttpStatusCodes::IsServerError(class="type">void)
  {
   class="kw">return(m_status >= class="num">500 && m_status <= class="num">599);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+

◍ 别急着下结论

这套 Connexus 辅助类目前只拆出了 CQueryParam、CHttpHeader、CHttpBody 三个独立处理单元,都依赖 CJson 但没有互相继承,彼此还没接成完整请求链路。也就是说,现在能单独拼出参数、头、体,却还发不出去一个真实 HTTP 调用。 方法和状态码是客户端—服务器通信的两块地基:200 代表通路正常,4xx 是客户端侧问题,5xx 是服务端崩了。读懂这些返回码,错误就不再是终止信号,而是重试或调参的入口。 下一篇才会把请求和响应类接起来,让上面三个类真正跑通。外汇与贵金属 API 对接本身高风险,未连线的代码直接上实盘等于裸奔,先在本机 MT5 里编译附件里的 24.99 KB ZIP 验证类结构再说。

常见问题

把状态码收进封装类,用区间判定函数识别500-599即归为服务器错误组,避免和4xx客户端错误混淆。
在状态枚举尾部做字符化映射表,把数字码对应到短描述字符串,取数时直接按码查表返回文本。
小布可对接你的日志流,自动归类5xx出现频率并在盘口页提示,省去你手动翻状态码。
若类内只存基础类型和枚举不必显式释放,但若有动态字符映射缓冲应在析构时清掉防泄漏。
用整除区间判定:码/100==2为成功组,==3为重定向组,比逐个枚举更省代码。