English Русский Deutsch 日本語
preview
Connexus中的正文(第四部分):添加HTTP请求正文

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

MetaTrader 5示例 | 2 六月 2025, 09:30
102 1
joaopedrodev
joaopedrodev

引言

本文是这一系列文章的延续,我们将构建一个名为Connexus的库。在第一篇文章中,我们了解了WebRequest函数的基本操作,理解了它的每个参数,并创建了一个示例代码,展示了这个函数的使用及其难点。在上一篇文章中,我们了解了请求的工作原理、请求的头部是什么以及如何使用头部来发起请求,并最终在库中开发了对不同头部的支持。

在API开发中,客户端与服务器之间的通信通过HTTP请求来发送必要的信息。如果头部就像是这种通信的信封,那么正文就是信件本身——包含你想要传输的实际数据。在今天的文章中,我们将探讨HTTP请求中正文的作用、其重要性以及如何使用Connexus正确配置它。让我们开始吧!


HTTP中的正文是什么?

在HTTP协议中,请求或响应的正文指的是正在发送或接收的实际内容。简单来说,正文是我们感兴趣的数据的存储位置,是我们想要发送到服务器或从服务器接收的数据。它是POST、PUT和PATH类型请求的主要组成部分,在这些请求中,需要发送诸如表单、JSON或XML格式的结构化数据,甚至是文件。在本系列文章中,主要关注的是使用JSON格式,这是调用API时最常用的一种格式,但要知道我们也可以发送其他格式的数据。

在GET类型的请求中通常没有正文,因为这种类型的请求用于查询数据,即接收信息而不是发送信息。通常,服务器会以包含请求结果的正文来响应这种类型的请求。然而,在POST请求中,正文是必不可少的,因为就是通过它将数据发送到服务器进行处理的。服务器可能会也可能不会以另一个正文来响应这种类型的请求。

HTTP正文用于在客户端和服务器之间传输信息,具体取决于请求的类型。它在涉及创建、更新甚至删除数据的操作中至关重要。因此,正文的主要功能是携带服务器需要处理的“实际内容”。没有它,HTTP将毫无用处!现在只需将其转换为字符数组:如果没有正文,HTTP通信将仅限于单纯的信息请求,而无法传输复杂数据或执行更复杂的操作。

现在我们已经理解了正文在HTTP通信中的作用,了解如何在请求中正确使用它是很重要的。根据您想要发送的数据类型,正文可以有不同的格式,例如JSON、XML或二进制数据(例如文件上传的情况)。现在让我们看一些实际例子。

  1. JSON正文:JSON(JavaScript对象表示法)格式在现代应用程序中最为常见,尤其是在REST API中。它轻量级、易于阅读,非常适合传输结构化数据,在使用MQL5中的HTTP时,将是使用最广泛的格式。让我们看看JSON如何用于请求正文中:

    {
      "type": "BUY",
      "symbol": "EURUSD",
      "price": 1.09223
      "volume": 0.01
      "tp": 1.09233
      "sl": 1.09213
    }

    在本例中,我们将交易数据发送到服务器,以便服务器接收并处理这些数据,将其保存到数据库中,并生成包含账户交易绩效指标的仪表板,或者服务器也可以将交易数据重新发送到其他账户,创建一个交易复制系统。要使用这种正文,您必须在头部指定内容类型为JSON:

    内容类型:application/json

  1. 正文文本:在HTTP请求中发送数据的另一种常见方式是使用纯文本格式。这种格式因其简单性而具有优势。您只需写下想要发送的内容,无需遵循太多规则或约定,只要服务器支持所发送的内容即可。由于难以组织大量数据,不建议使用此格式发送数据。对于此类场景,最推荐的格式是JSON。让我们来看一个纯文本的示例:

    这是一个纯文本示例

    在这里,表单字段被连接起来,并用&分隔,每个值都被分配了一个特定的键。要使用这种格式,头部应设置为:

    内容类型:application/text-plain

    这是最古老的格式之一,但在各种应用程序中仍然广泛使用。我们的Connexus库将支持这种内容类型,允许开发人员选择最适合其用例的方法。


向HTTP请求添加正文

让我们通过一个实际示例来发送一个正文为JSON的请求,并检查服务器是否正确接收。为了进行这项检查,我们将继续使用在前几篇文章中已经提到的httpbin。从一开始,我将在Experts/Connexus/Test/TestBody.mq5文件夹中创建另一个名为TestBody.mq5的文件,并添加在上一篇文章中使用的简单POST请求。本文使用的所有文件都附在文末。

//+------------------------------------------------------------------+
//|                                                     TestBody.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

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

请求的正文必须包含在 body_send 变量中,这是一个字符类型的数组。你可能会好奇,为什么不用字符串类型代替字符数组呢?字符串不是更适合发送JSON或文本吗?原因涉及灵活性、性能和兼容性等多个方面。以下是具体原因:

  • 数据类型灵活性:HTTP请求的正文可以包含各种类型的数据,例如文本、JSON、二进制(文件、图像)或其他格式。使用字符数组可以让函数接受任何类型的数据,无论是以文本还是二进制形式表示。如果正文包含文件(图像、音频等),则需要将其作为字节数组进行处理,这可以直接在字符数组中完成。而字符串仅适用于纯文本数据,这限制了函数在处理二进制内容场景中的使用。
  • 性能:字符数组在低级别数据操作方面更为高效。由于它们不涉及动态字符串管理的开销(例如内存分配和重新分配),它们能够让网络代码更接近硬件,这对于需要高性能的应用(如大文件传输或低延迟请求)至关重要。在发送包含大图像文件的请求时,使用字符数组可以避免将二进制内容转换为字符串,从而节省CPU周期。
  • HTTP协议兼容性:HTTP协议在通过网络传输数据时直接使用字节。字符数组(即字节序列)更好地反映了协议的这种底层行为。因此,使用字符数组可以让HTTP请求函数与网络层处理和传输数据的方式保持一致。

在涉及二进制数据或大量数据的场景中,使用字符数组作为HTTP请求的正文具有更高的灵活性、性能和兼容性。它允许函数直接处理数据的最基本形式(字节),避免了使用字符串所带来的开销和限制,因为字符串更适合用于文本数据。

现在我们已经理解了这一点,让我们为这个请求添加一个正文,为此我们将使用 StringToCharArray() 函数,让我们看看文档对这个函数的说明:

参数
类型
说明
text_string
string
想要复制的字符串。
array[]
char[]
无符号字符(uchar)类型的数组。
start
int
复制开始的位置默认 - 0
count
int
要复制的数组元素数量。定义结果字符串的长度。默认值是 -1,这意味着复制到数组末尾,或者直到遇到终止符 0。终止符 0 也会被复制到目标数组中,在这种情况下,如果需要,动态数组的大小可以增加到字符串的长度。如果动态数组的大小超过了字符串的长度,数组的大小不会被减少。
codepage
uint 代码页的值。在将字符串变量转换为字符类型数组以及反之,MQL5 默认使用当前 Windows 操作系统的 ANSI 编码(CP_ACP)。如果您想指定其他类型的编码,可以通过此参数设置。

下表列出了一些最流行的代码页的内部常量。未指定的代码页可以使用相应的代码页编号来指定。

常量
说明
CP_ACP
0
当前Windows ANSI代码页。
CP_OEMCP
1 当前系统的OEM代码页。
CP_MACCP
2 当前系统的Macintosh代码页。这个值主要用于早期编写的程序代码中,现在已基本没有用途,因为现代的Macintosh计算机使用Unicode进行编码。
CP_THREAD_ACP
3 当前进程的Windows ANSI 代码页。
CP_SYMBOL
42 系统代码页
CP_UTF7
65000 UTF-7 代码页。
CP_UTF8
65001 UTF-8 代码页。

对于大多数API,我们将使用UTF-8,这是一种用于电子邮件、网页等的标准编码类型。因此,让我们添加一个遵循UTF-8编码的JSON格式的正文:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   //--- Data to be sent
   string method = "POST";
   CJson body;
   body["type"] = "BUY";
   body["symbol"] = "EURUSD";
   body["price"] = 1.09223;
   body["volume"] = 0.01;
   body["tp"] = 1.09233;
   body["sl"] = 1.09213;
   //--- {"price": 1.09223,"sl": 1.09213,"symbol": "EURUSD","tp": 1.09233,"type": "BUY","volume": 0.01}
   
   //--- Char that will be sent
   char body_send[];
   
   //--- Convert string to char (UTF8)
   StringToCharArray(body.Serialize(),body_send,0,WHOLE_ARRAY,CP_UTF8);
   
   //--- Show char array
   ArrayPrint(body_send);
         
   return(INIT_SUCCEEDED);
  }

当你运行这段代码时,工具栏中会显示:

toolbox | experts

请注意,在数组的最后一个位置我们有一个值为“0”,这可能会在服务器读取请求正文时引发问题。为了避免这种情况,我们将使用ArrayRemove()ArraySize()函数移除数组的最后一个位置。

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   //--- Data to be sent
   string method = "POST";
   CJson body;
   body["type"] = "BUY";
   body["symbol"] = "EURUSD";
   body["price"] = 1.09223;
   body["volume"] = 0.01;
   body["tp"] = 1.09233;
   body["sl"] = 1.09213;
   //--- {"price": 1.09223,"sl": 1.09213,"symbol": "EURUSD","tp": 1.09233,"type": "BUY","volume": 0.01}
   
   //--- Char that will be sent
   char body_send[];
   
   //--- Convert string to char (UTF8)
   StringToCharArray(body.Serialize(),body_send,0,WHOLE_ARRAY,CP_UTF8);
   ArrayRemove(body_send,ArraySize(body_send)-1);
   
   //--- Show char array
   ArrayPrint(body_send);
         
   return(INIT_SUCCEEDED);
  }

当你再次运行时,工具栏中会显示:

toolbox | experts

现在我们已经解决了这个小问题,让我们将这个正文实际添加到一个HTTP请求中:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   //--- URL
   CURL url;
   url.Parse("https://httpbin.org");
   url.Path("post");
   
   //--- Data to be sent
   string method = "POST";
   CJson body;
   body["type"] = "BUY";
   body["symbol"] = "EURUSD";
   body["price"] = 1.09223;
   body["volume"] = 0.01;
   body["tp"] = 1.09233;
   body["sl"] = 1.09213;
   char body_send[];
   StringToCharArray(body.Serialize(),body_send,0,WHOLE_ARRAY,CP_UTF8);
   ArrayRemove(body_send,ArraySize(body_send)-1);
   
   //--- Headers that will be sent separated by "\n"
   CHttpHeader headers_send;
   headers_send.Add("User-Agent","Connexus/1.0 (MetaTrader 5 Terminal)");
   headers_send.Add("Content-Type","application/json");
   
   //--- Data that will be received
   char body_receive[];
   string headers_receive;
   
   //--- Send request
   int status_code = WebRequest(method,url.FullUrl(),headers_send.Serialize(),5000,body_send,body_receive,headers_receive);
   
   //--- Show response
   Print("Respose: ",CharArrayToString(body_receive));
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+

当运行这段代码时,我们将会从httpbin中得到如下响应:

Respose: {
  "args": {}, 
  "data": "{\"type\":\"BUY\",\"symbol\":\"EURUSD\",\"price\":1.09223000,\"volume\":0.01000000,\"tp\":1.09233000,\"sl\":1.09213000}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Accept-Language": "pt,en;q=0.5", 
    "Content-Length": "103", 
    "Content-Type": "text/plain", 
    "Host": "httpbin.org", 
    "User-Agent": "Connexus/1.0 (MetaTrader 5 Terminal)", 
    "X-Amzn-Trace-Id": "Root=1-67081b9c-3def4b1527d04edc1511cc6b"
  }, 
  "json": {
    "price": 1.09223, 
    "sl": 1.09213, 
    "symbol": "EURUSD", 
    "tp": 1.09233, 
    "type": "BUY", 
    "volume": 0.01
  }, 
  "origin": "189.74.63.39", 
  "url": "https://httpbin.org/post"
}

请注意两个有趣的地方,第一个是“data”字段包含了我们以字符串格式在正文中发送的JSON,这意味着服务器能够接收并正确解释所发送的数据。另一个需要注意的地方是,“json”字段包含了我们发送的JSON,再次证明服务器正确接收了数据。运行完美!


创建CHttpBody类

既然我们已经了解了正文的工作原理、用途以及如何使用它,让我们在Connexus库中创建一个用于处理请求正文的类。这个类将被命名为CHttpBody,它将拥有用于处理正文的方法,能够添加、更新或删除数据。还将能够定义所使用的编码(默认为UTF-8)。

让我们在Include/Connexus/Header/HttpBody.mqh文件夹中创建一个名为HttpBody.mqh的新文件。创建文件时,它最初看起来会类似于这样:

//+------------------------------------------------------------------+
//|                                                     HttpBody.mqh |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| class : CHttpBody                                                |
//|                                                                  |
//| [PROPERTY]                                                       |
//| Name        : CHttpBody                                          |
//| Heritage    : No heritage                                        |
//| Description : Responsible for organizing and storing the body of |
//|               a request.                                         |
//|                                                                  |
//+------------------------------------------------------------------+
class CHttpBody
  {
public:
                     CHttpBody(void);
                    ~CHttpBody(void);

  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CHttpBody::CHttpBody(void)
  {
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CHttpBody::~CHttpBody(void)
  {
  }
//+------------------------------------------------------------------+

让我们定义几个类的私有属性,它们是:

  • m_body:将以字符数组的形式存储请求正文。
  • m_codepage:用于存储所定义的编码。
//+------------------------------------------------------------------+
//| Include the file CJson class                                     |
//+------------------------------------------------------------------+
#include "../Data/Json.mqh"
//+------------------------------------------------------------------+
//| class : CHttpBody                                                |
//|                                                                  |
//| [PROPERTY]                                                       |
//| Name        : CHttpBody                                          |
//| Heritage    : No heritage                                        |
//| Description : Responsible for organizing and storing the body of |
//|               a request.                                         |
//|                                                                  |
//+------------------------------------------------------------------+
class CHttpBody
  {
private:
   
   char              m_body[];                           // Will store the request body as a char array
   uint              m_codepage;                         // Used to store the defined encoding
  };;
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CHttpBody::CHttpBody(void)
  {
   m_codepage = CP_UTF8;
  }
//+------------------------------------------------------------------+

现在让我们定义一些公共方法来处理请求正文:

  • 向正文中添加数据
    • AddString(string data):向请求正文中添加文本字符串。
    • AddJson(CJson data):向正文中添加JSON格式的数据。这可能涉及将JSON对象转换为格式化的字符串。
    • AddBinary(char &data[]):允许你直接向请求正文中添加二进制数据(如文件)。
  • 从正文中移除数据
    • Clear(void):从请求正文中移除所有内容,让你可以从头开始。
  • 获取正文的内容
    • GetAsString(void):将请求正文作为字符串返回。
    • GetAsJson(void):将请求正文转换为JSON对象,当正文包含结构化数据时非常有用。GetAsChar(char &body[]):将正文作为字节数组返回,适用于处理二进制数据。
  • 检查正文大小
    • GetSize(void):返回请求正文的大小,通常以字节为单位。
  • 编码
    • GetCodePage(void):返回所定义的代码页
    • SetCodePage(uint codepage):设置要使用的代码页

让我们将这些方法添加到类中,最终它将看起来像这样:

//+------------------------------------------------------------------+
//| class : CHttpBody                                                |
//|                                                                  |
//| [PROPERTY]                                                       |
//| Name        : CHttpBody                                          |
//| Heritage    : No heritage                                        |
//| Description : Responsible for organizing and storing the body of |
//|               a request.                                         |
//|                                                                  |
//+------------------------------------------------------------------+
class CHttpBody
  {
private:
   
   char              m_body[];                           // Will store the request body as a char array
   uint              m_codepage;                         // Used to store the defined encoding
   
public:
                     CHttpBody(void);
                    ~CHttpBody(void);

   //--- Add data to the body
   void              AddString(string data);             // Adds a text string to the request body
   void              AddJson(CJson &data);               // Adds data in JSON format to the body
   void              AddBinary(char &data[]);            // Allows you to add binary data
   
   //--- Clear the body
   void              Clear(void);                        // Remove all body content
   
   //--- Gets the body content
   string            GetAsString(void);                  // Returns the request body as a string
   CJson             GetAsJson(void);                    // Converts the request body into a JSON object, useful when the body contains structured data
   void              GetAsBinary(char &body[]);          // Returns the body as an array of bytes, useful for working with binary data
   
   //--- Size in bytes
   int               GetSize(void);                      // Returns the size of the request body, usually in bytes
   
   //--- Codepage
   uint              GetCodePage(void);                  // Returns the defined codepage
   void              SetCodePage(uint codepage);         // Defines the codepage to be used
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CHttpBody::CHttpBody(void)
  {
   m_codepage = CP_UTF8;
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CHttpBody::~CHttpBody(void)
  {
  }
//+------------------------------------------------------------------+
//| Adds a text string to the request body                           |
//+------------------------------------------------------------------+
void CHttpBody::AddString(string data)
  {
   StringToCharArray(data,m_body,this.GetSize()-1,WHOLE_ARRAY,m_codepage);
   ArrayRemove(m_body,this.GetSize()-1);
  }
//+------------------------------------------------------------------+
//| Adds data in JSON format to the body                             |
//+------------------------------------------------------------------+
void CHttpBody::AddJson(CJson &data)
  {
   this.AddString(data.Serialize());
  }
//+------------------------------------------------------------------+
//| Allows you to add binary data                                    |
//+------------------------------------------------------------------+
void CHttpBody::AddBinary(char &data[])
  {
   ArrayCopy(m_body,data);
  }
//+------------------------------------------------------------------+
//| Remove all body content                                          |
//+------------------------------------------------------------------+
void CHttpBody::Clear(void)
  {
   ArrayFree(m_body);
  }
//+------------------------------------------------------------------+
//| Returns the request body as a string                             |
//+------------------------------------------------------------------+
string CHttpBody::GetAsString(void)
  {
   return(CharArrayToString(m_body,0,WHOLE_ARRAY,m_codepage));
  }
//+------------------------------------------------------------------+
//| Converts the request body into a JSON object, useful when the    |
//| body contains structured data                                    |
//+------------------------------------------------------------------+
CJson CHttpBody::GetAsJson(void)
  {
   CJson json;
   json.Deserialize(this.GetAsString());
   return(json);
  }
//+------------------------------------------------------------------+
//| Returns the body as an array of bytes, useful for working with   |
//| binary data                                                      |
//+------------------------------------------------------------------+
void CHttpBody::GetAsBinary(char &body[])
  {
   ArrayCopy(body,m_body);
  }
//+------------------------------------------------------------------+
//| Returns the size of the request body, usually in bytes           |
//+------------------------------------------------------------------+
int CHttpBody::GetSize(void)
  {
   return(ArraySize(m_body));
  }
//+------------------------------------------------------------------+
//| Returns the defined codepage                                     |
//+------------------------------------------------------------------+
uint CHttpBody::GetCodePage(void)
  {
   return(m_codepage);
  }
//+------------------------------------------------------------------+
//| Defines the codepage to be used                                  |
//+------------------------------------------------------------------+
void CHttpBody::SetCodePage(uint codepage)
  {
   m_codepage = codepage;
  }
//+------------------------------------------------------------------+

这些方法简单直接——最长的也不过三行代码。然而,不要被它们的简单性所迷惑。它们极其有用,将显著减少你的库中的代码行数。它们不仅会使你的代码更加简洁,还会使你的库更容易使用和维护。


测试

让我们继续进行测试,看看这个类的表现如何。我将使用文章开头提到的同一个文件,TestBody.mq5。

{
  "type": "BUY",
  "symbol": "EURUSD",
  "price": 1.09223
  "volume": 0.01
  "tp": 1.09233
  "sl": 1.09213
}

在这个测试中,我们将这个JSON添加到POST请求的正文中。我们将使用以下数据创建JSON对象:

CJson body_json;
body_json["type"] = "BUY";
body_json["symbol"] = "EURUSD";
body_json["price"] = 1.09223;
body_json["volume"] = 0.01;
body_json["tp"] = 1.09233;
body_json["sl"] = 1.09213;

让我们创建一个CHttpBody类的实例,并将这个JSON添加到其中:

CHttpBody body;
body.AddJson(body_json);

完成!现在只需将其转换为字符数组:

//--- Body in char array
char body_send[];
body.GetAsBinary(body_send);

就这么简单,我们毫无困难地将JSON添加到了请求中。在库开发完成之后,这最后一步将不再必要,因为我们仍然处于开发阶段,目前我们还需要手动完成所有操作。最终,代码将如下所示:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   //--- URL
   CURL url;
   url.Parse("https://httpbin.org");
   url.Path("post");
   
   //--- Data to be sent
   string method = "POST";
   CJson body_json;
   body_json["type"] = "BUY";
   body_json["symbol"] = "EURUSD";
   body_json["price"] = 1.09223;
   body_json["volume"] = 0.01;
   body_json["tp"] = 1.09233;
   body_json["sl"] = 1.09213;
   CHttpBody body;
   body.AddJson(body_json);
   
   //--- Body in char array
   char body_send[];
   body.GetAsBinary(body_send);
   
   //--- Headers that will be sent separated by "\n"
   CHttpHeader headers_send;
   headers_send.Add("User-Agent","Connexus/1.0 (MetaTrader 5 Terminal)");
   headers_send.Add("Content-Type","application/json");
   
   //--- Data that will be received
   char body_receive[];
   string headers_receive;
   
   //--- Send request
   int status_code = WebRequest(method,url.FullUrl(),headers_send.Serialize(),5000,body_send,body_receive,headers_receive);
   
   //--- Show response
   Print("Respose: ",CharArrayToString(body_receive));
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
运行结果如下:
Respose: {
  "args": {}, 
  "data": "{\"type\":\"BUY\",\"symbol\":\"EURUSD\",\"price\":1.09223000,\"volume\":0.01000000,\"tp\":1.09233000,\"sl\":1.09213000}", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Accept-Language": "pt,en;q=0.5", 
    "Content-Length": "103", 
    "Content-Type": "application/json", 
    "Host": "httpbin.org", 
    "User-Agent": "Connexus/1.0 (MetaTrader 5 Terminal)", 
    "X-Amzn-Trace-Id": "Root=1-670902d1-5a796b1e1fe2053f18a07654"
  }, 
  "json": {
    "price": 1.09223, 
    "sl": 1.09213, 
    "symbol": "EURUSD", 
    "tp": 1.09233, 
    "type": "BUY", 
    "volume": 0.01
  }, 
  "origin": "189.74.63.39", 
  "url": "https://httpbin.org/post"
}

请注意,“data”和“json”字段中包含了一个对象,这意味着服务器正确接收了我们在正文中发送的数据。如果你想要发送未经格式化的纯文本正文,只需将其作为字符串插入到CHttpBody类中,并将头部更改为text/plain,正如我们在上一篇文章中看到的那样:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   //--- URL
   CURL url;
   url.Parse("https://httpbin.org");
   url.Path("post");
   
   //--- Data to be sent
   string method = "POST";
   CHttpBody body;
   body.AddString("My simple text");
   
   //--- Body in char array
   char body_send[];
   body.GetAsBinary(body_send);
   
   //--- Headers that will be sent separated by "\n"
   CHttpHeader headers_send;
   headers_send.Add("User-Agent","Connexus/1.0 (MetaTrader 5 Terminal)");
   headers_send.Add("Content-Type","text/plain");
   
   //--- Data that will be received
   char body_receive[];
   string headers_receive;
   
   //--- Send request
   int status_code = WebRequest(method,url.FullUrl(),headers_send.Serialize(),5000,body_send,body_receive,headers_receive);
   
   //--- Show response
   Print("Respose: ",CharArrayToString(body_receive));
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+


结论

在本文中,我们探讨了 HTTP 请求中正文的概念,展示了它在客户端和服务器之间数据传输中的基本作用。我们了解到正文是我们放置要发送数据的部分,它可以以不同的方式格式化,例如 JSON、XML 甚至文件,但我们更多地探讨了 JSON 的使用,JSON 是在 API 上下文中使用最广泛的,这也是我们目前关注的重点。此外,我们讨论了每种正文类型所需的请求头,以确保服务器正确解释请求。

我们还介绍了 Connexus 库中 CHttpBody 类的创建,该类将负责简化请求正文的处理工作。这个类允许轻松地操作要发送的数据,而无需担心低级格式化(字节)。

在系列文章的下一篇中,我们将更深入地探讨 HTTP 协议的操作,探索一些方法,例如 GET、POST、PUT、DELETE 等。我们还将讨论 HTTP 状态码,例如 200(OK),也许是网络上最著名的,404(未找到)以及其他如 500(内部服务器错误)等,以及它们对客户端-服务器通信意味着什么。敬请关注!

本文由MetaQuotes Ltd译自英文
原文地址: https://www.mql5.com/en/articles/16098

最近评论 | 前往讨论 (1)
yucong tang
yucong tang | 4 6月 2025 在 22:37
如何发送中文内容?中文内容乱码。
交易中的神经网络:点云的层次化特征学习 交易中的神经网络:点云的层次化特征学习
我们继续研究从点云提取特征的算法。在本文中,我们将领略提升 PointNet 方法效率的机制。
基于人工生态系统的优化(AEO)算法 基于人工生态系统的优化(AEO)算法
本文探讨了一种元启发式算法——基于人工生态系统的优化(Artificial Ecosystem-based Optimization, AEO)算法。该算法通过生成初始解种群并应用自适应更新策略,模拟生态系统各组成部分之间的相互作用。文中详细阐述了AEO算法的运行阶段,包括消耗阶段与分解阶段,以及不同智能体的行为策略。文章还介绍了该算法的特点和优势。
交易中的神经网络:点云变换器(Pointformer) 交易中的神经网络:点云变换器(Pointformer)
在本文中,我们将说道有关使用注意力方法解决点云中物体检测问题的算法。点云中的物体检测对于很多现世应用都很重要。
开发基于订单簿的交易系统(第一部分):指标 开发基于订单簿的交易系统(第一部分):指标
市场深度无疑是执行快速交易的一个非常重要的因素,特别是在高频交易(HFT)算法中。在本系列文章中,我们将探讨这种类型的交易事件,这些事件可以通过经纪商在许多可交易的交易品种上获得。我们将从一个指标开始,您可以在其中自定义直接显示在图表上的直方图的调色板、位置和大小。我们还将研究如何生成 BookEvent 事件,以在特定条件下测试指标。未来文章的其他可能主题包括如何存储价格分布数据以及如何在策略测试器中使用它。