
Corpo em Connexus (Parte 4): Adicionando suporte ao corpo de requisições HTTP
Introdução
Este artigo é a continuação da série na qual estamos criando uma biblioteca chamada Connexus. No primeiro artigo, analisamos os fundamentos da função WebRequest, entendemos cada um de seus parâmetros e também criamos um exemplo de código demonstrando o uso da função e as dificuldades relacionadas. No artigo anterior, explicamos como funciona uma requisição, o que são os cabeçalhos e como usá-los na construção da requisição. Ao final, implementamos o suporte a diferentes cabeçalhos na biblioteca.
Ao desenvolver uma API, a comunicação entre o cliente e o servidor envolve o envio de informações importantes por meio de uma requisição HTTP. Se os cabeçalhos são parecidos com o envelope dessa mensagem, o corpo é a própria carta, contendo os dados reais que você quer transmitir. No artigo de hoje, vamos analisar o papel do corpo em uma requisição HTTP, sua importância e como configurá-lo corretamente usando o Connexus. Vamos começar!
O que é o corpo em HTTP?
No protocolo HTTP, o corpo da requisição ou da resposta se refere ao conteúdo propriamente dito que está sendo enviado ou recebido. Em termos simples, o corpo é onde ficam os dados de interesse que queremos mandar para o servidor ou obter do servidor. É o componente principal de requisições do tipo POST, PUT e PATH, nas quais é necessário enviar informações como formulários, dados estruturados em formatos como JSON ou XML, e até arquivos. Nesta série de artigos, focaremos principalmente no uso do formato JSON, que é o mais comum em APIs, mas vale lembrar que também podemos enviar dados em outros formatos.
Na requisição do tipo GET normalmente não há corpo, pois esse tipo de requisição é usado para solicitar dados, ou seja, para obter informações, e não para enviá-las. Em geral, o servidor responde a esse tipo de requisição com um corpo contendo os resultados solicitados. Já em uma requisição POST, o corpo é essencial, pois é por meio dele que os dados são enviados ao servidor para processamento. O servidor pode ou não responder a esse tipo de requisição com outro corpo.
O corpo HTTP é usado para transmitir informações do cliente para o servidor ou vice-versa, dependendo do tipo de requisição. Isso é essencial ao realizar operações relacionadas à criação, atualização ou até exclusão de dados. Portanto, a função principal do corpo é transmitir o "conteúdo real" que o servidor deve processar. Sem isso, o HTTP com não funciona! Nesse caso, tudo se resumiria a uma troca de caracteres: a comunicação seria limitada a requisições simples de informação, sem a possibilidade de transmitir dados complexos ou executar ações mais avançadas.
Agora que entendemos o papel do corpo na comunicação HTTP, é importante saber como usá-lo corretamente nas requisições. Dependendo do tipo de dado que você deseja enviar, o corpo pode assumir diferentes formatos, como JSON, XML ou dados binários (em casos como upload de arquivos). Vamos ver alguns exemplos práticos.
-
Corpo em formato JSON: O formato JSON (JavaScript Object Notation) é o mais comum em aplicações modernas, especialmente em REST API. Ele é leve, fácil de ler e ideal para transmitir dados estruturados, sendo também o formato mais amplamente usado ao trabalhar com HTTP no MQL5. Vamos ver como o JSON pode ser utilizado no corpo de uma requisição:
{ "type": "BUY", "symbol": "EURUSD", "price": 1.09223 "volume": 0.01 "tp": 1.09233 "sl": 1.09213 }
Neste exemplo, estamos enviando dados de transações para o servidor, permitindo que ele receba e processe essas informações, armazenando-as em um banco de dados e gerando um painel de monitoramento com indicadores de desempenho das transações da conta, ou ele pode simplesmente reenviar os dados de transações para outras contas, criando um sistema de cópia de transações. Para utilizar esse corpo, é necessário indicar no cabeçalho que o tipo de conteúdo é JSON:
Content-Type: application/json
-
Texto simples: Outra maneira comum de enviar dados em uma requisição HTTP é no formato de texto simples. Esse formato é vantajoso por sua simplicidade. Basta escrever o que deseja enviar, sem seguir muitas regras ou formalidades, desde que o servidor aceite o tipo de informação enviado. Ele não é recomendado para envio de dados mais complexos, pois é difícil organizar grandes quantidades de informações. Para esse tipo de cenário, o formato mais indicado continua sendo o JSON. Vamos observar um exemplo de texto simples:
Это образец обычного текста
Aqui, os campos do formulário são combinados e separados pelo caractere &, com cada valor associado a uma chave específica. Para usar esse formato, o cabeçalho precisa ser configurado da seguinte maneira:
Content-Type: application/text-plain
Esse é um dos formatos mais antigos, mas ainda é amplamente usado em diversas aplicações. Nossa biblioteca Connexus irá oferecer suporte a esse tipo de conteúdo, permitindo que os desenvolvedores escolham a abordagem que melhor se adequa ao seu caso de uso.
Adicionando corpo à requisição HTTP
Vamos analisar um exemplo prático, no qual enviaremos um arquivo JSON no corpo da requisição e verificaremos se o servidor o recebeu corretamente. Para realizar essa verificação, continuaremos utilizando httpbin, já mencionado nos artigos anteriores. Desde o início, criei mais um arquivo chamado TestBody.mq5 na pasta Experts/Connexus/Test/TestBody.mq5 e adicionei uma requisição POST simples, como a que foi usada no artigo anterior. Todos os arquivos utilizados neste artigo estão incluídos ao final.
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
O corpo da requisição deve estar presente na variável body_send, que é um array do tipo char. Talvez você se pergunte por que não utilizar o tipo string no lugar de char[]? Afinal, string seria ideal para enviar JSON ou texto? Por várias razões relacionadas à flexibilidade, eficiência e compatibilidade. Abaixo estão alguns motivos em detalhes:
- Flexibilidade de tipos de dados: O corpo da requisição HTTP pode conter diversos tipos de dados, como texto, JSON, dados binários (arquivos, imagens) ou outros formatos. Usar um array de caracteres permite que a função aceite qualquer tipo de dado, independentemente de estarem em formato textual ou binário. Se o corpo contiver um arquivo (imagem, áudio etc.), ele precisa ser manipulado como um array de bytes, o que pode ser feito diretamente com um array de caracteres. O tipo string só seria útil para dados puramente textuais, o que limita o uso da função a cenários em que o conteúdo é binário.
- Eficiência: Um array de caracteres é mais eficiente em termos de manipulação de dados. Como não há sobrecarga com a gestão dinâmica de strings (como alocação e realocação de memória), ele permite que o código de rede funcione mais próximo do hardware, algo importante em aplicações que exigem alta performance, como envio de arquivos grandes ou requisições com baixa latência. Ao enviar uma requisição contendo um arquivo de imagem grande, usar um array de caracteres evita a necessidade de converter o conteúdo binário para string, economizando tempo de processamento.
- Compatibilidade com o protocolo HTTP: O protocolo HTTP trabalha diretamente com bytes na transmissão de dados pelas redes. Um array de caracteres (que nada mais é do que uma sequência de bytes) representa melhor esse comportamento de baixo nível do protocolo. Assim, ao usar arrays de caracteres, a função de requisição HTTP se alinha com a forma como os dados são processados e transmitidos no nível de rede.
O uso de um array de caracteres no corpo da requisição HTTP oferece excelente flexibilidade, eficiência e compatibilidade, especialmente em cenários que envolvem dados binários ou grandes volumes de dados. Isso permite que a função processe os dados diretamente em sua forma mais simples (bytes), evitando o uso excessivo de recursos e as limitações associadas às strings, que são mais adequadas para dados textuais.
Agora que entendemos isso, vamos adicionar o corpo a essa requisição. Para isso, utilizaremos a função StringToCharArray(), vamos analisar o que a documentação diz sobre essa função:
Parâmetro | Tipo | Descrição |
---|---|---|
text_string | string | String que será copiada. |
array[] | char[] | Array do tipo uchar. |
start | int | Posição a partir da qual a cópia será iniciada. O valor padrão é 0. |
count | int | Quantidade de elementos do array a serem copiados. Define o comprimento da string resultante. O valor padrão é -1, o que significa que será copiado até o final do array ou até o terminal 0. O terminal 0 também será copiado para o array de destino, e nesse caso o tamanho do array dinâmico pode ser aumentado conforme necessário para acomodar o tamanho da string. Se o tamanho do array dinâmico for maior que o comprimento da string, o tamanho do array não será reduzido. |
codepage | uint | Valor da página de código. Ao converter variáveis de string para arrays do tipo char e vice-versa, o MQL5 utiliza uma codificação que, por padrão, corresponde à codificação ANSI atual do sistema operacional Windows (CP_ACP). Se for necessário especificar outro tipo de codificação, ele pode ser definido neste parâmetro. |
A tabela abaixo apresenta a lista de constantes internas para algumas das páginas de código mais populares. Outras páginas de código não listadas podem ser especificadas usando o número correspondente da página.
Constante | Valor | Descrição |
---|---|---|
CP_ACP | 0 | Página de código ANSI atual do Windows. |
CP_OEMCP | 1 | Página de código OEM atual do sistema. |
CP_MACCP | 2 | Página de código do sistema Macintosh. Esse valor era usado em códigos antigos e atualmente não é mais utilizado, pois os computadores Macintosh modernos utilizam codificação Unicode. |
CP_THREAD_ACP | 3 | Página de código ANSI do Windows para a thread atual. |
CP_SYMBOL | 42 | Página de código de símbolo. |
CP_UTF7 | 65000 | Página de código UTF-7. |
CP_UTF8 | 65001 | Página de código UTF-8. |
Para a maioria das APIs, utilizaremos UTF8, que é o tipo de codificação padrão para e-mails, páginas da web etc. Sendo assim, vamos adicionar o corpo em formato JSON de acordo com a codificação 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); }
Ao executar esse código, ele será exibido na aba de ferramentas:
Observe que, na última posição do array, temos o valor "0", o que pode causar problemas para o servidor ao ler o corpo da requisição. Para evitar esse problema, vamos remover a última posição do array usando as funções ArrayRemove() e 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); }
Ao executar novamente, ele será exibido na aba de ferramentas:
Agora que ajustamos essa pequena configuração, vamos adicionar esse corpo à requisição 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); } //+------------------------------------------------------------------+
Ao executar esse código, receberemos a seguinte resposta do 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" }
Observe dois pontos interessantes: primeiro, o campo "data" contém o JSON que enviamos no corpo, em formato de string, o que indica que o servidor conseguiu receber e interpretar corretamente os dados enviados. Outro ponto que merece atenção é que o campo "json" contém o JSON enviado por nós, o que mais uma vez confirma que o servidor recebeu os dados corretamente. Está funcionando perfeitamente!
Criação da classe CHttpBody
Agora que entendemos como o corpo funciona, para que serve e como usá-lo, vamos criar uma classe na biblioteca Connexus para lidar com o corpo da requisição. O nome dessa classe será CHttpBody, e ela terá métodos para trabalhar com o corpo, permitindo adicionar, atualizar ou remover dados. Também será possível definir a codificação utilizada (por padrão, será usada UTF-8).
Vamos criar um novo arquivo chamado HttpBody.mqh na pasta Include/Connexus/Header/HttpBody.mqh. Ao criá-lo, o arquivo inicialmente terá a seguinte aparência:
//+------------------------------------------------------------------+ //| 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) { } //+------------------------------------------------------------------+
Vamos definir algumas propriedades privadas da classe, especificamente:
- m_body : Será responsável por armazenar o corpo da requisição como um array de caracteres.
- m_codepage : Usado para armazenar a codificação especificada.
//+------------------------------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
Agora vamos definir alguns métodos públicos para manipular o corpo da requisição:
- Adição de dados ao corpo
- AddString(string data) : Adiciona uma string de texto ao corpo da requisição.
- AddJson(CJson data) : Adiciona dados em formato JSON ao corpo. Isso pode incluir a conversão de um objeto JSON em uma string formatada.
- AddBinary(char &data[]) : Permite adicionar dados binários (como arquivos) diretamente ao corpo da requisição.
- Remoção de dados do corpo
- Clear(void) : Remove todo o conteúdo do corpo da requisição, permitindo começar do zero.
- Leitura do conteúdo do corpo
- GetAsString(void) : Retorna o corpo da requisição como string.
- GetAsJson(void) : Converte o corpo da requisição em um objeto JSON, útil quando o corpo contém dados estruturados. - GetAsChar(char &body[]) : Retorna o corpo como array de bytes, útil para manipulação de dados binários.
- Verificação do tamanho do corpo
- GetSize(void) : Retorna o tamanho do corpo da requisição, geralmente em bytes.
- Codificação
- GetCodePage(void) : Retorna a página de código definida.
- SetCodePage(uint codepage) : Define a página de código a ser utilizada.
Vamos adicionar esses métodos à classe, e no final ela ficará assim:
//+------------------------------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
Esses métodos são simples e diretos, visto que o maior tem apenas três linhas. No entanto, não se deixe enganar pela simplicidade. Eles são extremamente úteis e terão um impacto significativo na redução do número total de linhas de código de sua biblioteca. Além de tornar o código mais compacto, eles facilitam bastante o uso e a manutenção da biblioteca.
Testes
Vamos passar para os testes e observar o comportamento da classe. Vou utilizar o mesmo arquivo que usamos no início do artigo, o TestBody.mq5.
{ "type": "BUY", "symbol": "EURUSD", "price": 1.09223 "volume": 0.01 "tp": 1.09233 "sl": 1.09213 }
Neste teste, adicionaremos esse arquivo JSON ao corpo de uma requisição POST. Vamos criar um objeto json com os dados:
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;
Criamos uma instância da classe CHttpBody e adicionamos esse arquivo JSON nela:
CHttpBody body; body.AddJson(body_json);
Pronto! Agora é só convertê-lo em um array de caracteres:
//--- Body in char array char body_send[]; body.GetAsBinary(body_send);
É tão simples assim, pois adicionamos JSON à requisição sem nenhuma complicação. Esse último passo de converter para array de caracteres não será mais necessário ao final do desenvolvimento da biblioteca, pois ainda estamos na fase de construção e seguimos fazendo tudo "manualmente". No final, o código vai ficar assim:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+Durante a execução, obteremos o seguinte resultado:
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" }
Note mais uma vez que os campos "data" e "json" contêm dentro de si o objeto, o que significa que o servidor recebeu corretamente os dados que enviamos no corpo. Se você quiser enviar uma mensagem com texto simples, sem formatação, basta inseri-la no CHttpBody como uma string e ajustar o cabeçalho para text/plain, conforme descrito no artigo anterior:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Considerações finais
Neste artigo, exploramos o conceito de corpo nas requisições HTTP, mostrando seu papel fundamental na transmissão de dados entre cliente e servidor. Entendemos que o corpo é o local onde colocamos os dados que queremos enviar; esses dados podem estar formatados de diversas maneiras, como JSON, XML e até arquivos, mas nos aprofundamos no uso de JSON, que é o formato mais comum no contexto de APIs — nosso foco atual. Além disso, discutimos os cabeçalhos necessários para cada tipo de corpo de requisição, garantindo que o servidor interprete corretamente a requisição.
Também apresentamos a criação da classe CHttpBody na biblioteca Connexus, que será responsável por facilitar o trabalho com o corpo da requisição. Essa classe permite manipular facilmente os dados que serão enviados, sem se preocupar com o formatação de baixo nível (em bytes).
No próximo artigo da série, vamos nos aprofundar ainda mais no funcionamento do protocolo HTTP, explorando alguns métodos como GET, POST, PUT, DELETE e outros. Também discutiremos os códigos de status HTTP, como o 200 (Ok), talvez o mais conhecido da internet, o 404 (Não encontrado) e outros, como o 500 (Erro interno do servidor), e o que eles significam para a interação cliente-servidor. Fique ligado para atualizações!
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/16098






- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso