
Тело в Connexus (Часть 4): Добавление поддержки тела HTTP-запроса
Введение
Данная статья является продолжением серии статей, в которых мы будем создавать библиотеку под названием Connexus. В первой статье мы разобрались с основами работы функции WebRequest, разобрались с каждым из ее параметров, а также создали пример кода, который демонстрирует использование данной функции и связанные с этим трудности. В прошлой статье мы разобрались с тем, как работает запрос, что такое заголовки и как использовать заголовки для создания запроса. В конце мы разработали поддержку различных заголовков в библиотеке.
При разработке API коммуникация между клиентом и сервером включает в себя отправку важной информации посредством HTTP-запроса. И если заголовки похожи на конверт этого сообщения, то тело — это само письмо, содержащее фактические данные, которые вы хотите передать. В сегодняшней статье мы рассмотрим роль тела в HTTP-запросе, его важность, а также, как правильно настроить его с помощью Connexus. Начнем!
Что такое тело в HTTP?
В протоколе HTTP тело запроса или ответа относится к фактическому содержимому, которое отправляется или принимается. Проще говоря, тело - это место, где хранятся интересующие нас данные, которые мы хотим отправить на сервер или получить с сервера. Это основной компонент запросов типов POST , PUT и PATH, в которых необходимо отправлять такую информацию, как формы, структурированные данные в таких форматах, как JSON или XML, и даже файл. В этой серии статей основное внимание будет уделено использованию формата JSON, который чаще всего применяется для использования API, но знайте, что мы можем отправлять данные и в других форматах.
В запросе типа GET обычно нет тела, поскольку этот тип запроса используется для запроса данных, то есть для получения информации, а не для ее отправки. Обычно сервер отвечает на запрос такого типа с телом, содержащим запрошенные результаты. Однако в POST-запросе тело важно, поскольку именно через него данные отправляются на сервер для обработки. Сервер может отвечать, а может и не отвечать на запросы такого типа с другим телом.
Тело HTTP используется для передачи информации от клиента к серверу или наоборот, в зависимости от типа запроса. Это жизненно важно при выполнении операций, связанных с созданием, обновлением или даже удалением данных. Соответственно, основная функция тела заключается в передаче "реального контента", который сервер должен обработать. Без этого HTTP com не работает! Теперь просто преобразуем его в массив символов: общение будет ограничено простыми запросами информации, без возможности передачи сложных данных или выполнения более сложных действий.
Теперь, когда мы понимаем роль тела в HTTP-коммуникации, важно знать, как корректно использовать его в запросах. В зависимости от типа данных, которые вы хотите отправить, тело может иметь различные форматы, такие как JSON, XML или двоичные данные (в таких случаях, как загрузка файлов). Давайте рассмотрим несколько практических примеров.
-
Тело в формате JSON: Формат JSON (JavaScript Object Notation) является наиболее распространенным в современных приложениях, особенно в REST API. Он легкий, легко читаемый и идеально подходит для передачи структурированных данных, а также будет наиболее широко применяемым форматом при использовании HTTP на MQL5. Давайте рассмотрим, как JSON будет использоваться в теле запроса:
{ "type": "BUY", "symbol": "EURUSD", "price": 1.09223 "volume": 0.01 "tp": 1.09233 "sl": 1.09213 }
В этом примере мы отправляем данные о транзакциях на сервер, чтобы сервер мог получать и обрабатывать данные, сохраняя их в базе данных и создавая панель мониторинга с показателями эффективности для транзакций по счету, или он может просто повторно отправлять данные о транзакциях другим учетным записям, создавая систему копирования транзакций. Для использования этого тела, необходимо указать в заголовке, что тип контента - JSON:
Content-Type: application/json
-
Основной текст: Другой распространенный способ отправки данных в HTTP-запросе - в обычном текстовом формате. Этот формат выгоден своей простотой. Вам просто нужно написать то, что вы хотите отправить, не соблюдая многих правил или условностей, при условии, что сервер поддерживает отправляемую информацию. Он не рекомендуется для отправки данных, так как сложно организовать большое количество данных. Для этого сценария наиболее рекомендуемым форматом является JSON. Давайте рассмотрим пример обычного текста:
Это образец обычного текста
Здесь поля формы объединены и разделены символом &, и каждому значению присвоен определенный ключ. Для использования этого формата заголовок должен быть установлен следующим образом:
Content-Type: application/text-plain
Это один из старейших форматов, но он по-прежнему широко используется в различных приложениях. Наша библиотека Connexus будет поддерживать этот тип контента, позволяя разработчикам выбирать подход, который наилучшим образом соответствует их вариантам использования.
Добавление тела к HTTP-запросу
Рассмотрим практический пример, в котором отправим JSON-файл в теле запроса и проверим, корректно ли его получил сервер. Для выполнения этой проверки продолжим использовать httpbin, о котором уже упоминалось в предыдущих статьях. С самого начала я создам еще один файл с именем TestBody.mq5 в папке Experts/Connexus/Test/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, которая представляет собой массив типа char. Возможно, вам интересно, почему бы не использовать тип string вместо char[], string был бы идеальным для отправки JSON или текста? По нескольким причинам, связанным с гибкостью, эффективностью и совместимостью. Вот несколько подробных причин:
- Гибкость типов данных: Тело HTTP-запроса может содержать различные типы данных, такие как текст, JSON, двоичные (файлы, изображения) или другие форматы. Использование массива символов позволяет функции принимать данные любого типа, независимо от того, представлены ли они в текстовом или двоичном виде. Если тело содержит файл (изображение, аудио и т.д.), необходимо манипулировать им как массивом байтов, который может быть обработан непосредственно в массиве символов. Строка была бы полезна только для чисто текстовых данных, что ограничивает использование функции сценариями, в которых содержимое является двоичным.
- Эффективность: массив символов является более эффективным с точки зрения манипулирования данными. Поскольку они не требуют дополнительных затрат на динамическое управление строками (таких как выделение и перераспределение памяти), они позволяют сетевому коду работать ближе к аппаратному обеспечению, что важно для приложений, требующих высокой производительности, таких как передача больших файлов или запросы с низкой задержкой. При отправке запроса с большим файлом изображения использование массива символов позволяет избежать необходимости преобразования двоичного содержимого в строку, экономя время работы процессора.
- Совместимость с протоколом HTTP: Протокол HTTP работает непосредственно с байтами при передаче данных по сетям. Массив символов (который представляет собой последовательность байтов) лучше отражает это низкоуровневое поведение протокола. Таким образом, при использовании массивов символов функция HTTP-запроса будет приведена в соответствие со способом обработки и передачи данных на сетевом уровне.
Использование массива символов в теле HTTP-запроса обеспечивает превосходную гибкость, эффективность и совместимость, особенно в сценариях, связанных с двоичными данными или большими объемами данных. Это позволяет функции напрямую обрабатывать данные в их самой простой форме (байтах), избегая расходования ресурсов и ограничений, связанных со строками, которые больше подходят для текстовых данных.
Теперь, когда мы это поняли, добавим тело к этому запросу. Для этого мы используем функцию StringToCharArray(), давайте рассмотрим, что говорится в документации об этой функции:
Параметр | Тип | Описание |
---|---|---|
text_string | string | Строка для копирования. |
array[] | char[] | Массив типа uchar. |
start | int | Позиция, с которой начинается копирование. Значение по умолчанию равно 0. |
count | int | Количество элементов массива для копирования. Определяет длину результирующей строки. Значение по умолчанию минус 1, что означает копирование до конца массива или до терминала 0. Терминал 0 также будет скопирован в массив-приёмник, в этом случае размер динамического массива может быть увеличен при необходимости до размера строки. Если размер динамического массива превышает длину строки, размер массива не будет уменьшен. |
codepage | uint | Значение кодовой страницы. При преобразовании строковых переменных в массивы типа char и наоборот, в MQL5 используется кодировка, которая по умолчанию соответствует текущему ANSI операционной системы Windows (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 мы будем использовать UTF8, который является стандартным типом кодировки для электронной почты, веб-страниц и т.д. Итак, добавим тело в формате json в соответствии с кодировкой UTF8:
//+------------------------------------------------------------------+ //| 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); }
При запуске этого кода, он будет отображен на панели инструментов:
Обратите внимание, что в последней позиции массива у нас есть значение “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); }
При повторном запуске это будет отображено на панели инструментов:
Теперь, когда мы разобрались с этой маленькой настройкой, давайте добавим это тело в 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).
Давайте создадим новый файл под названием HttpBody.mqh в папке Include/Connexus/Header/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, который наиболее часто используется в контексте API, на чем мы сейчас и концентрируем внимание. Кроме того, мы обсудили заголовки, необходимые для каждого типа тела запроса, чтобы гарантировать корректную интерпретацию запроса сервером.
Мы также представили создание класса CHttpBody в библиотеке Connexus, который будет отвечать за облегчение работы с телом запроса. Этот класс позволяет легко манипулировать данными, которые будут отправлены, не беспокоясь о низкоуровневом форматировании (в байтах).
В следующей статье серии мы еще глубже разберемся в работе протокола HTTP, исследуя некоторые методы, такие как GET, POST, PUT, DELETE и другие. Мы также обсудим коды состояния HTTP, такие как 200 (Ok), возможно, самый известный в Интернете, 404 (Не найден) и другие, такие как 500 (Внутренняя ошибка сервера), и то, что они означают для взаимодействия клиент-сервер. Следите за обновлениями!
Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/16098





- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования