English Русский 中文 Español Deutsch 日本語
preview
Solicitação no Connexus (Parte 6): Criando uma Requisição e Resposta HTTP

Solicitação no Connexus (Parte 6): Criando uma Requisição e Resposta HTTP

MetaTrader 5Exemplos |
16 1
joaopedrodev
joaopedrodev

Introdução

Este artigo faz parte de uma série em andamento onde estamos construindo uma biblioteca chamada Connexus. No primeiro artigo, abordamos a funcionalidade básica da função WebRequest, entendendo cada um de seus parâmetros e criando um código de exemplo que demonstra seu uso e os desafios associados. No artigo anterior, exploramos o que são métodos HTTP e os códigos de status retornados pelo servidor, indicando se a requisição foi processada com sucesso ou se houve um erro no lado do cliente ou do servidor.

Neste sexto artigo da série da biblioteca Connexus, focamos em uma requisição HTTP completa, cobrindo cada componente que compõe uma requisição. Criamos uma classe que representa a requisição como um todo, o que nos ajudou a reunir as classes criadas anteriormente. Além disso, desenvolvemos uma classe semelhante para lidar com a resposta do servidor, contendo os dados da resposta, o código de status e até mesmo a duração da requisição.

Na comunicação HTTP, uma requisição é composta por vários componentes que juntos formam a requisição completa. Já exploramos todos esses componentes em artigos anteriores e criamos classes individuais para cada elemento da requisição. Vamos recapitular os elementos abaixo:

  • URL: Define o endereço do servidor na web e é composta por partes menores como domínio, porta, caminho etc. Isso foi abordado em mais detalhes na Parte 2 do Connexus, onde criamos uma classe para formatar corretamente uma URL.
  • Cabeçalho: São dados adicionais enviados junto com a requisição, destinados a fornecer detalhes sobre a requisição que não fazem parte do corpo ou da URL. Isso foi abordado em mais detalhes na Parte 3 do Connexus, onde também criamos uma classe responsável por organizar o cabeçalho da requisição.
  • Corpo: Refere-se ao conteúdo real que está sendo enviado ou recebido. Simplificando, o corpo é onde ficam armazenados os dados que nos interessam, que queremos enviar ao servidor. Na Parte 4, discutimos isso em mais detalhes e também criamos uma classe responsável por armazenar o corpo da requisição, que suporta adicionar o corpo em diferentes formatos, como texto simples (string), JSON ou char[] (binário).
  • Método HTTP: Os métodos HTTP são usados pelo cliente para informar ao servidor qual ação deseja executar. Isso foi discutido em mais detalhes na Parte 5 do Connexus.
  • Timeout: O tempo limite não foi abordado em artigos anteriores, mas, explicando brevemente, é o tempo em milissegundos que o servidor tem para responder. Se a requisição levar mais do que o tempo estipulado, ela é encerrada, resultando em um erro de timeout. Esse valor pode ser útil para evitar cenários em que o servidor demore muito para responder, já que a função WebRequest é síncrona, ou seja, o Expert Advisor fica “pausado” enquanto aguarda a resposta do servidor. Isso pode ser problemático se a requisição levar muito mais tempo do que o esperado. Para evitar esse cenário, recomenda-se o uso de timeout. O valor do timeout pode variar dependendo da sua necessidade, mas para a maioria dos servidores, 5000 milissegundos (5 segundos) são suficientes para que a requisição seja processada corretamente.

Cada um desses componentes desempenha um papel fundamental na construção de uma requisição HTTP adequada, mas é importante observar que nem todos são obrigatórios. Os únicos elementos obrigatórios são a URL e o método HTTP (GET, POST, PUT etc.).

Para nos guiar sobre o progresso da biblioteca e as classes que já criamos, vamos dar uma olhada no diagrama atual da biblioteca:

current diagram

Observe que já temos classes prontas para lidar com Métodos HTTP, Códigos de Status, URLs com parâmetros de consulta, Cabeçalhos e o Corpo.


Padrão de Projeto Facade

Para continuar construindo a biblioteca, implementaremos um padrão de projeto. Se você não está familiarizado com padrões de projeto, recomendo a leitura da série de artigos Padrões de Projeto em Desenvolvimento de Software e MQL5, escrita por Mohamed Abdelmaaboud. Nessa série, o autor descreve vários padrões de projeto com códigos de exemplo. Para a biblioteca Connexus, implementaremos o padrão de projeto “Facade”, que é um padrão bem conhecido na programação. Esse padrão fornece uma interface simplificada para um conjunto mais complexo de subsistemas, ocultando a complexidade interna e permitindo que o cliente interaja com o sistema de uma forma muito mais simples.

Vamos imaginar um exemplo no contexto da biblioteca: você quer criar uma requisição. Para isso, você precisaria criar uma instância de cada um dos elementos da requisição e configurá-los, algo como isto:

CURL m_url;
m_url.Parse("http://example.com/api");

CHttpBody m_body;
m_body.AddString("my text");

CHttpHeader m_headers;
m_headers.Add("content-type","text/plain");

CHttpMethod m_method;
m_method = HTTP_METHOD_GET;

int m_timeout = 5000;

Essa abordagem torna o código poluído, exigindo a criação de múltiplas instâncias, consumindo muitas linhas e deixando o código menos legível. A situação piora ao trabalhar com várias requisições, já que gerenciar múltiplos objetos como cabeçalhos, corpo e URL se torna complicado e difícil de manter. É aqui que o padrão de projeto Facade entra em cena. Voltando ao conceito: Esse padrão fornece uma interface simplificada para um conjunto mais complexo de subsistemas, ocultando a complexidade interna e permitindo que o cliente interaja com o sistema de uma forma muito mais simples.

Nesse contexto, os subsistemas são as classes para elementos de requisição como CHttpBody, CHttpHeaders etc., e o objetivo é criar uma interface mais intuitiva para eles. Esse padrão resolve o problema introduzindo uma classe ou interface que atua como uma “Facade” para acessar os subsistemas. O desenvolvedor final interage apenas com essa interface simplificada.

Em resumo, a arquitetura Facade oferece os seguintes benefícios:

  1. Interação Simplificada: Em vez de lidar diretamente com uma série de classes complexas, o desenvolvedor pode usar uma interface simplificada que oculta os detalhes internos.
  2. Acoplamento Reduzido: Como o cliente não fica acoplado diretamente aos subsistemas internos, mudanças nesses subsistemas podem ser feitas sem afetar o cliente.
  3. Melhor Manutenibilidade: A separação clara entre a interface Facade e os subsistemas internos torna o código mais fácil de manter e expandir, já que quaisquer mudanças internas podem ser abstraídas pela fachada.

Como esse padrão de projeto seria implementado na biblioteca? Para isso, criaremos uma nova classe chamada CHttpRequest, que conterá os subsistemas. Para o usuário da biblioteca, o uso dessa classe deve se parecer com isto:

CHttpRequest request;

request.Method() = HTTP_METHOD_GET;
request.Url().Parse("http://example.com/api");
request.Body().AddString("my text");
request.Header().Add("content-type","text/plain");

Perceba como o código ficou muito mais simples e legível, que é exatamente a ideia por trás desse padrão de projeto. O padrão Facade fornece uma interface simplificada (CHttpRequest) para um conjunto mais complexo de subsistemas (gerenciando instâncias de CHttpBody, CHttpHeader etc.), ocultando a complexidade interna e permitindo que o cliente interaja com o sistema de uma forma muito mais simples.


Criando a Classe CHttpRequest

Agora que entendemos o conceito de Facade, podemos aplicar essa arquitetura à classe CHttpRequest. Vamos criar essa classe dentro de uma nova pasta chamada core. O arquivo se chamará HttpRequest.mqh, e o caminho final será Include/Connexus/Core/HttpRequest.mqh. Inicialmente, o arquivo ficará assim:
//+------------------------------------------------------------------+
//|                                                  HttpRequest.mqh |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| class : CHttpRequest                                             |
//|                                                                  |
//| [PROPERTY]                                                       |
//| Name        : CHttpRequest                                       |
//| Heritage    : No heritage                                        |
//| Description : Gathers elements of an http request such as url,   |
//|               body, header, method and timeout                   |
//|                                                                  |
//+------------------------------------------------------------------+
class CHttpRequest
  {
public:
                     CHttpRequest(void);
                    ~CHttpRequest(void);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CHttpRequest::CHttpRequest(void)
  {
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CHttpRequest::~CHttpRequest(void)
  {
  }
//+------------------------------------------------------------------+

Vamos importar as classes criadas nos últimos arquivos: CURL, CHttpBody, CHttpHeader e CHttpMethod. Criaremos uma instância de cada uma, adicionando o "*" para informar ao compilador que gerenciaremos o ponteiro manualmente. Além disso, adicionaremos uma variável chamada m_timeout do tipo int, que armazenará o valor de timeout da requisição.

//+------------------------------------------------------------------+
//|                                                  HttpRequest.mqh |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "../URL/URL.mqh"
#include "../Header/HttpBody.mqh"
#include "../Header/HttpHeader.mqh"
#include "../Constants/HttpMethod.mqh"
//+------------------------------------------------------------------+
//| class : CHttpRequest                                             |
//|                                                                  |
//| [PROPERTY]                                                       |
//| Name        : CHttpRequest                                       |
//| Heritage    : No heritage                                        |
//| Description : Gathers elements of an http request such as url,   |
//|               body, header, method and timeout                   |
//|                                                                  |
//+------------------------------------------------------------------+
class CHttpRequest
  {
private:

   CURL              *m_url;
   CHttpBody         *m_body;
   CHttpHeader       *m_headers;
   CHttpMethod       *m_method;
   int               m_timeout;

public:
                     CHttpRequest(void);
                    ~CHttpRequest(void);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CHttpRequest::CHttpRequest(void)
  {
   m_url = new CURL();
   m_body = new CHttpBody();
   m_headers = new CHttpHeader();
   m_method = new CHttpMethod();
   m_timeout = 5000; // Default timeout (5 seconds)
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CHttpRequest::~CHttpRequest(void)
  {
   delete m_url;
   delete m_body;
   delete m_headers;
   delete m_method;
  }
//+------------------------------------------------------------------+

Agora, vamos adicionar alguns métodos para acessar o ponteiro de cada instância, bem como métodos para definir e obter o valor de timeout:

  • CURL *Url(void): Retorna o ponteiro para a URL
  • CHttpBody *Body(void): Retorna o ponteiro para o corpo
  • CHttpHeader *Header(void): Retorna o ponteiro para o cabeçalho
  • CHttpMethod *Method(void): Retorna o ponteiro para o método
  • CHttpRequest *Timeout(int timeout): Define o timeout
  • int Timeout(void): Obtém o timeout

Além desses métodos, adicionaremos alguns métodos auxiliares:

  • void Clear(void): Remove todos os dados das instâncias

  • string FormatString(void): Gera uma string contendo todos os dados da requisição

    Exemplo de uma requisição formatada:

    HTTP Request:
    ---------------
    Method: GET
    URL: https://api.example.com/resource?id=123&filter=active
    
    Headers:
    ---------------
    Authorization: Bearer token
    Content-Type: application/json
    User-Agent: MyHttpClient/1.0
    
    Body:
    ---------------
    {
        "key": "value",
        "data": [1, 2, 3]
    }
    ---------------

Aqui está a implementação dos métodos.

//+------------------------------------------------------------------+
//|                                                  HttpRequest.mqh |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| class : CHttpRequest                                             |
//|                                                                  |
//| [PROPERTY]                                                       |
//| Name        : CHttpRequest                                       |
//| Heritage    : No heritage                                        |
//| Description : Gathers elements of an http request such as url,   |
//|               body, header, method and timeout                   |
//|                                                                  |
//+------------------------------------------------------------------+
class CHttpRequest
  {
public:
   //--- HTTP
   CURL              *Url(void);                         // Get url object
   CHttpBody         *Body(void);                        // Get body object
   CHttpHeader       *Header(void);                      // Get header object
   CHttpMethod       *Method(void);                      // Get method object
   
   //--- Timeout
   CHttpRequest      *Timeout(int timeout);              // Set timeout
   int               Timeout(void);                      // Get timeout
   
   //--- Auxiliary methods
   void              Clear(void);                        // Reset data
   string            FormatString(void);                 // Format data
  };
//+------------------------------------------------------------------+
//| Get url object                                                   |
//+------------------------------------------------------------------+
CURL *CHttpRequest::Url(void)
  {
   return(GetPointer(m_url));
  }
//+------------------------------------------------------------------+
//| Get body object                                                  |
//+------------------------------------------------------------------+
CHttpBody *CHttpRequest::Body(void)
  {
   return(GetPointer(m_body));
  }
//+------------------------------------------------------------------+
//| Get header object                                                |
//+------------------------------------------------------------------+
CHttpHeader *CHttpRequest::Header(void)
  {
   return(GetPointer(m_headers));
  }
//+------------------------------------------------------------------+
//| Get method object                                                |
//+------------------------------------------------------------------+
CHttpMethod *CHttpRequest::Method(void)
  {
   return(GetPointer(m_method));
  }
//+------------------------------------------------------------------+
//| Set timeout                                                      |
//+------------------------------------------------------------------+
CHttpRequest *CHttpRequest::Timeout(int timeout)
  {
   m_timeout = timeout;
   return(GetPointer(this));
  }
//+------------------------------------------------------------------+
//| Get timeout                                                      |
//+------------------------------------------------------------------+
int CHttpRequest::Timeout(void)
  {
   return(m_timeout);
  }
//+------------------------------------------------------------------+
//| Reset data                                                       |
//+------------------------------------------------------------------+
void CHttpRequest::Clear(void)
  {
   m_url.Clear();
   m_body.Clear();
   m_headers.Clear();
   m_timeout = 5000;
  }
//+------------------------------------------------------------------+
//| Format data                                                      |
//+------------------------------------------------------------------+
string CHttpRequest::FormatString(void)
  {
   return(
      "HTTP Request:"+
    "\n---------------"+
    "\nMethod: "+m_method.GetMethodDescription()+
    "\nURL: "+m_url.FullUrl()+
    "\n"+
    "\n---------------"+
    "\nHeaders:"+
    "\n"+m_headers.Serialize()+
    "\n"+
    "\n---------------"+
    "\nBody:"+
    "\n"+m_body.GetAsString()+
    "\n---------------"
   );
  }
//+------------------------------------------------------------------+

Assim, concluímos esta classe, que serve como uma fachada para acessar os objetos que formam uma requisição HTTP. É importante observar que estou adicionando apenas as partes que foram modificadas no código. O arquivo completo pode ser encontrado ao final do artigo anexado.

Com essa nova classe CHttpRequest, o diagrama atualizado da biblioteca fica assim:

diagram 2

Em resumo, a CHttpRequest atua como uma fachada, simplificando o processo de configurar e enviar uma requisição HTTP. Internamente, a classe CHttpHeaders lida com a lógica de cabeçalhos, enquanto a CHttpBody cuida da construção do corpo da requisição. O desenvolvedor que usa esta biblioteca não precisa se preocupar com os detalhes de como os cabeçalhos ou o corpo são manipulados — ele simplesmente define os valores usando os métodos de CHttpRequest, e a classe fachada cuida do restante.


Criando a Classe CHttpResponse

Seguindo a mesma ideia, vamos criar outra classe que será usada para representar os dados da resposta do servidor. Ela seguirá uma estrutura semelhante à CHttpRequest. Estes são os elementos que compõem uma resposta:

  • Cabeçalho: Assim como na requisição, a resposta também inclui um cabeçalho, que informa ao cliente metadados sobre a requisição.
  • Corpo: Aqui ficará o corpo da resposta do servidor. É onde o servidor envia os dados que queremos obter, sendo o núcleo da mensagem.
  • Código de Status: Contém o código de status, que discutimos em mais detalhes na Parte 5 da série. Esse código é um número de 3 dígitos que informa se a requisição foi processada com sucesso ou se encontrou um erro do cliente ou do servidor.
  • Duração: Armazena o tempo que a requisição levou para ser concluída, medido em milissegundos.

Criaremos um novo arquivo dentro da pasta core chamado HttpResponse, e o caminho final será Include/Connexus/Core/HttpResponse.mqh. A classe criada deve se parecer com isto:

//+------------------------------------------------------------------+
//|                                                 HttpResponse.mqh |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| class : CHttpResponse                                            |
//|                                                                  |
//| [PROPERTY]                                                       |
//| Name        : CHttpResponse                                      |
//| Heritage    : No heritage                                        |
//| Description : gathers elements of an http response such as body, |
//|               header, status code and duration                   |
//|                                                                  |
//+------------------------------------------------------------------+
class CHttpResponse
  {
public:
                     CHttpResponse(void);
                    ~CHttpResponse(void);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CHttpResponse::CHttpResponse(void)
  {
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CHttpResponse::~CHttpResponse(void)
  {
  }
//+------------------------------------------------------------------+

Importaremos os elementos de uma resposta, que são: CHttpHeader, CHttpBody e CHttpStatusCode. Em seguida, criaremos uma instância de cada uma dessas classes e também uma variável privada do tipo ulong, que armazenará a duração da requisição. O código final ficará assim:

//+------------------------------------------------------------------+
//|                                                 HttpResponse.mqh |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| Include files                                                    |
//+------------------------------------------------------------------+
#include "../Constants/HttpStatusCode.mqh"
#include "../Header/HttpBody.mqh"
#include "../Header/HttpHeader.mqh"
//+------------------------------------------------------------------+
//| class : CHttpResponse                                            |
//|                                                                  |
//| [PROPERTY]                                                       |
//| Name        : CHttpResponse                                      |
//| Heritage    : No heritage                                        |
//| Description : gathers elements of an http response such as body, |
//|               header, status code and duration                   |
//|                                                                  |
//+------------------------------------------------------------------+
class CHttpResponse
  {
private:
   
   CHttpHeader       *m_header;
   CHttpBody         *m_body;
   CHttpStatusCodes  *m_status_code;
   ulong              m_duration;

public:
                     CHttpResponse(void);
                    ~CHttpResponse(void);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CHttpResponse::CHttpResponse(void)
  {
   m_header = new CHttpHeader();
   m_body = new CHttpBody();
   m_status_code = new CHttpStatusCodes();
   m_duration = 0; // Reset duration
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CHttpResponse::~CHttpResponse(void)
  {
   delete m_header;
   delete m_body;
   delete m_status_code;
  }
//+------------------------------------------------------------------+

Agora vamos avançar para os métodos que serão adicionados a essa classe. Começaremos pelos mais simples, que apenas retornam os ponteiros de cada uma das instâncias das classes, e métodos para definir e obter a duração:

  • CHttpHeader *Header(void): Retorna o ponteiro para o cabeçalho.
  • CHttpBody *Body(void): Retorna o ponteiro para o corpo.
  • CHttpStatusCodes *StatusCode(void) : Retorna o ponteiro para o código de status.
  • void Duration(ulong duration) : Define a duração.
  • ulong Duration(void) : Obtém a duração.

Criaremos os mesmos métodos auxiliares de CHttpRequest para esta classe:

  • void Clear(void) : Remove todos os dados das instâncias.

  • string FormatString(void) : Gera uma string contendo todos os dados da resposta.

    Exemplo de uma resposta formatada

    HTTP Response:
    ---------------
    Status Code: 200 OK
    Duration: 120ms
    
    Headers:
    ---------------
    Content-Type: application/json
    Content-Length: 256
    Server: Apache/2.4.41 (Ubuntu)
    Date: Wed, 02 Oct 2024 12:34:56 GMT
    
    Body:
    ---------------
    {
        "message": "Success",
        "data": {
            "id": 123,
            "name": "Sample Item",
            "status": "active"
        }
    }
    ---------------

Aqui está o código com a implementação dessas funções:

//+------------------------------------------------------------------+
//|                                                 HttpResponse.mqh |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
//+------------------------------------------------------------------+
//| class : CHttpResponse                                            |
//|                                                                  |
//| [PROPERTY]                                                       |
//| Name        : CHttpResponse                                      |
//| Heritage    : No heritage                                        |
//| Description : gathers elements of an http response such as body, |
//|               header, status code and duration                   |
//|                                                                  |
//+------------------------------------------------------------------+
class CHttpResponse
  {
public:
   //--- HTTP
   CHttpHeader       *Header(void);                      // Get header object
   CHttpBody         *Body(void);                        // Get body object
   CHttpStatusCodes  *StatusCode(void);                  // Get status code object
   
   //--- Duration
   void              Duration(ulong duration);           // Set duration
   ulong             Duration(void);                     // Get duration
   
   //--- Auxiliary methods
   void              Clear(void);                        // Reset data
   string            FormatString(void);                 // Format data
  };
//+------------------------------------------------------------------+
//| Get header object                                                |
//+------------------------------------------------------------------+
CHttpHeader *CHttpResponse::Header(void)
  {
   return(GetPointer(m_header));
  }
//+------------------------------------------------------------------+
//| Get body object                                                  |
//+------------------------------------------------------------------+
CHttpBody *CHttpResponse::Body(void)
  {
   return(GetPointer(m_body));
  };
//+------------------------------------------------------------------+
//| Get status code object                                           |
//+------------------------------------------------------------------+
CHttpStatusCodes *CHttpResponse::StatusCode(void)
  {
   return(GetPointer(m_status_code));
  };
//+------------------------------------------------------------------+
//| Set duration                                                     |
//+------------------------------------------------------------------+
void CHttpResponse::Duration(ulong duration)
  {
   m_duration = duration;
  }
//+------------------------------------------------------------------+
//| Get duration                                                     |
//+------------------------------------------------------------------+
ulong CHttpResponse::Duration(void)
  {
   return(m_duration);
  }
//+------------------------------------------------------------------+
//| Reset data                                                       |
//+------------------------------------------------------------------+
void CHttpResponse::Clear(void)
  {
   m_header.Clear();
   m_body.Clear();
   m_status_code.SetStatusCode(HTTP_STATUS_URL_NOT_ALLOWED);
  }
//+------------------------------------------------------------------+
//| Format data                                                      |
//+------------------------------------------------------------------+
string CHttpResponse::FormatString(void)
  {
   return(
      "HTTP Response:"+
    "\n---------------"+
    "\nStatus Code: "+m_status_code.GetStatusCodeFormat()+
    "\nDuration: "+IntegerToString(m_duration)+" ms"+
    "\n"+
    "\n---------------"+
    "\nHeaders:"+
    "\n"+m_header.Serialize()+
    "\n---------------"+
    "\nBody:"+
    "\n"+m_body.GetAsString()+
    "\n---------------"
   );
  }
//+------------------------------------------------------------------+

Apenas para lembrar, aqui estou incluindo somente as alterações da classe para que o artigo não fique muito extenso. Todo o código utilizado está anexado ao final do artigo.

Com isso, concluímos a classe de resposta. Essas são classes relativamente simples, e o objetivo é um só: agrupar os elementos de uma requisição ou resposta. Dessa forma, podemos trabalhar com uma requisição como um único objeto, simplificando significativamente o uso de requisições e respostas HTTP. Com essa nova classe CHttpResponse, o diagrama atualizado fica assim:

diagram 3


Exemplos de uso

De forma breve, darei alguns exemplos de uso dessas classes. Começando com a CHttpRequest, construirei uma requisição HTTP usando essa classe.

//--- Example 1 - GET
CHttpRequest request;
request.Method() = HTTP_METHOD_GET;
request.Url().Parse("http://example.com/api/symbols");

//--- Example 2 - POST
CHttpRequest request;
request.Method() = HTTP_METHOD_POST;
request.Url().Parse("http://example.com/api/symbols");
request.Body().AddToString("{\"EURUSD\":1.08312}");
request.Header().Add("content-type","application/json");

//--- Example 3 - DELETE
CHttpRequest request;
request.Method() = HTTP_METHOD_DELETE;
request.Url().Parse("http://example.com/api/symbols?symbol=EURUSD");

A grande vantagem aqui é a simplicidade de criar uma requisição, adicionar um cabeçalho e corpo ou alterar o método HTTP.

Para as respostas, o que precisamos é do oposto disso, ou seja, em vez de criar um objeto de requisição facilmente, queremos ler um objeto de resposta facilmente — e ambos funcionam de maneira semelhante, o que permite criação e leitura simples. Incluirei uma imagem mostrando como fica a tela do desenvolvedor ao usar o Connexus:

example 1

É isso que aparecerá para você, desenvolvedor. Marquei cada um dos dados da resposta que podem ser acessados com cores diferentes. Vamos acessar o corpo da resposta:

example 2

Note que podemos acessar o corpo da resposta em diferentes formatos, como string, JSON ou binário. Aqui acessamos diretamente o ponteiro da classe CHttpBody e, em seguida, acessamos todos os métodos que ela possui. Quando criamos uma classe para cada um desses elementos de uma resposta, eu já estava pensando em chegar a essa parte da biblioteca, onde utilizamos cada uma das classes.


Conclusão

Neste artigo, exploramos a importância de ter um objeto CHttpRequest que agrupe todos os componentes de uma requisição HTTP, garantindo clareza, reutilização e fácil manutenção do código. Também vimos como o padrão de projeto Facade pode ser aplicado para simplificar a interação com componentes complexos, ocultando a complexidade interna e oferecendo uma interface limpa e eficiente. No contexto do Connexus, aplicar o padrão Facade à classe CHttpRequest facilita a criação de requisições HTTP completas, simplificando o processo para o desenvolvedor, além de criar a classe CHttpResponse que segue o mesmo formato, mas deve facilitar o acesso aos dados de uma resposta HTTP.

No próximo artigo, vamos aprofundar na camada de transporte, que deve receber um objeto CHttpRequest e converter os dados para a função WebRequest, que é a camada final da biblioteca.Ela deve ser capaz de processar os dados da resposta e retornar um objeto do tipo CHttpResponse para que o desenvolvedor então utilize os dados da resposta. Até lá!

Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/16182

Últimos Comentários | Ir para discussão (1)
Jedidiah
Jedidiah | 6 nov. 2024 em 10:39
Você fez uma enorme contribuição para o mql5 e para todos nós. Tornando mais fácil do que nunca trabalhar com solicitações da Web e http em geral. Esse material é excelente. Obrigado, cara. Mal posso esperar pelo artigo final para fechar o negócio com a biblioteca connexus.
Caminhe em novos trilhos: Personalize indicadores no MQL5 Caminhe em novos trilhos: Personalize indicadores no MQL5
Vou agora listar todas as possibilidades novas e recursos do novo terminal e linguagem. Elas são várias, e algumas novidades valem a discussão em um artigo separado. Além disso, não há códigos aqui escritos com programação orientada ao objeto, é um tópico muito importante para ser simplesmente mencionado em um contexto como vantagens adicionais para os desenvolvedores. Neste artigo vamos considerar os indicadores, sua estrutura, desenho, tipos e seus detalhes de programação em comparação com o MQL4. Espero que este artigo seja útil tanto para desenvolvedores iniciantes quanto para experientes, talvez alguns deles encontrem algo novo.
Desenvolvendo um EA multimoeda (Parte 24): Conectando uma nova estratégia (I) Desenvolvendo um EA multimoeda (Parte 24): Conectando uma nova estratégia (I)
Neste artigo, vamos analisar como conectar uma nova estratégia ao sistema de otimização automática criado. Vamos ver quais EAs precisaremos criar e se será possível evitar alterações nos arquivos da biblioteca Advisor, ou pelo menos reduzi-las ao mínimo.
Está chegando o novo MetaTrader 5 e MQL5 Está chegando o novo MetaTrader 5 e MQL5
Esta é apenas uma breve resenha do MetaTrader 5. Eu não posso descrever todos os novos recursos do sistema por um período tão curto de tempo - os testes começaram em 09.09.2009. Esta é uma data simbólica, e tenho certeza que será um número de sorte. Alguns dias passaram-se desde que eu obtive a versão beta do terminal MetaTrader 5 e MQL5. Eu ainda não consegui testar todos os seus recursos, mas já estou impressionado.
Otimização com Jogo do Caos — Chaos Game Optimization (CGO) Otimização com Jogo do Caos — Chaos Game Optimization (CGO)
Apresentamos o novo algoritmo meta-heurístico Chaos Game Optimization (CGO), que demonstra capacidade única de manter alta eficiência em tarefas de grande dimensionalidade. Ao contrário da maioria dos algoritmos de otimização, o CGO não apenas não perde desempenho, como também às vezes melhora sua performance quando a complexidade do problema aumenta, o que constitui sua principal característica.