
Assistente Connexus (Parte 5): Métodos HTTP e códigos de status
Introdução
Este artigo é a continuação de uma série na qual estamos criando uma biblioteca chamada Connexus. No primeiro artigo entendemos os fundamentos da função WebRequest, exploramos cada um de seus parâmetros e criamos um exemplo de código que demonstra seu uso e as dificuldades envolvidas. No artigo anterior, compreendemos como funciona uma requisição, o que é o corpo da requisição e como enviar dados para o servidor e, no final, desenvolvemos o suporte a requisições com corpo.
Nesta quinta parte da série dedicada à criação da biblioteca Connexus, vamos abordar um aspecto importante do protocolo HTTP: métodos e códigos de status. Entender como cada operação HTTP funciona e como lidar com os códigos de status é fundamental para criar uma interação confiável entre clientes e servidores. Vamos nessa!
Métodos HTTP
Os métodos HTTP são as ações que solicitamos ao servidor para serem executadas. Ao enviar uma requisição HTTP, seja para acessar uma página ou enviar dados, você "conversa" com o servidor usando esses comandos. Aqui estão os principais:
- GET: é o clássico "me dá isso". O navegador solicita acesso a algo no servidor, como uma página, uma imagem ou um arquivo. Ele apenas obtém a informação, sem alterar nada. É como pedir o cardápio em um restaurante apenas para ver o que eles oferecem.
- POST: o POST é o entregador de encomendas. Aqui, você envia dados para o servidor. Isso é muito comum em formulários, por exemplo, ao se registrar em um site. Pense como se estivesse enviando uma carta: você aguarda que ela chegue ao destino e lá faça algo, como registrar você.
- PUT: ao usar o comando PUT, você basicamente diz: "substitua isso aqui por esta nova versão". É usado para atualizar um recurso existente. É como trocar o óleo do carro – continua sendo o mesmo carro, mas agora com algo renovado.
- DELETE: bem óbvio, né? Significa "remova isso daqui". Você pede para o servidor apagar algo. Adeus, não vamos mais nos encontrar.
- PATCH: o PATCH é mais delicado. Ele altera apenas parte de um recurso. É como consertar uma peça quebrada de um brinquedo – não é necessário trocar tudo, apenas reparar o que está quebrado.
- HEAD: é igual ao GET, mas sem o corpo. Você precisa apenas das informações do cabeçalho, não do conteúdo. É como ler o título de um livro sem abrir as páginas.
Existem também outros métodos, como CONNECT, OPTIONS e TRACE, mas eles raramente são usados no dia a dia de um desenvolvedor. Não vou detalhar cada um deles aqui, mas meu objetivo ao trabalhar com a biblioteca é que ela possa oferecer suporte a todos os métodos HTTP. Se você quiser saber mais sobre todos os métodos HTTP, consulte a documentação completa do protocolo aqui. Mas acredite, para a maioria dos problemas do dia a dia de um desenvolvedor, os métodos mais comuns, como GET, POST e DELETE, já são suficientes.
Quero destacar que usamos apenas um método para cada requisição, ou seja, uma requisição não pode ser do tipo GET e POST ao mesmo tempo.
Criação da classe CHttpMethod
Agora que entendemos cada método HTTP, sua finalidade e quando utilizá-lo, podemos partir para o código. Vamos implementar no Connexus uma classe responsável por armazenar o método HTTP que será utilizado na execução das requisições. Ela será bem simples e, independentemente do seu nível de programação, você entenderá a maior parte do que está acontecendo. Embora o objetivo da classe seja apenas guardar o método utilizado, como estamos trabalhando com uma classe, vamos adicionar funções extras para tornar o uso da biblioteca Connexus o mais simples possível para o usuário final.
Começamos criando uma nova pasta chamada Constants e, dentro dela, um novo arquivo chamado CHttpMethod, resultando no caminho: Include/Constants/HttpMethod.mqh. Dentro desse novo arquivo, vamos criar a classe CHttpMethod:
//+------------------------------------------------------------------+ //| HttpMethods.mqh | //| Copyright 2024, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, MetaQuotes Ltd." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| class : CHttpMethods | //| | //| [PROPERTY] | //| Name : CHttpMethods | //| Heritage : No heritage | //| Description : Saved http method. | //| | //+------------------------------------------------------------------+ class CHttpMethod { public: CHttpMethod(void); ~CHttpMethod(void); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CHttpMethod::CHttpMethod(void) { } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CHttpMethod::~CHttpMethod(void) { } //+------------------------------------------------------------------+
Para armazenar todos os possíveis métodos HTTP, vamos criar um enum que contenha todos os métodos possíveis de requisição HTTP. Também vamos adicionar à classe uma nova variável do tipo ENUM_HTTP_METHOD, chamada m_method:
//+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ enum ENUM_HTTP_METHOD { HTTP_METHOD_NULL = 0, // [0] Null HTTP_METHOD_CONNECT, // [1] Connect HTTP_METHOD_DELETE, // [2] Delete HTTP_METHOD_GET, // [3] Get HTTP_METHOD_HEAD, // [4] Head HTTP_METHOD_OPTION, // [5] Option HTTP_METHOD_PATCH, // [6] Patch HTTP_METHOD_POST, // [7] Post HTTP_METHOD_PUT, // [8] Put HTTP_METHOD_TRACE, // [9] Trace }; //+------------------------------------------------------------------+ //| class : CHttpMethods | //| | //| [PROPERTY] | //| Name : CHttpMethods | //| Heritage : No heritage | //| Description : Saved http method. | //| | //+------------------------------------------------------------------+ class CHttpMethod { private: ENUM_HTTP_METHOD m_method; // Stores the method that will be used }; //+------------------------------------------------------------------+
Agora que temos a variável que será usada para o armazenamento, vamos criar métodos auxiliares para definir e recuperar o método HTTP, em adição à sobrecarga do operador = para facilitar o uso das funções principais:
- O operador de atribuição (operator= ): Permite definir diretamente o método HTTP usando o operador =.
- SetMethod(ENUM_HTTP_METHOD) e SetMethod(string): Definimos o método HTTP usando um enum ou uma string. Se o parâmetro for do tipo string, ele utiliza a função StringToUpper() para formar corretamente a string.
- GetMethod() e GetMethodDescription(): Obtêm o método HTTP e sua descrição em texto.
- void operator=(ENUM_HTTP_METHOD method): Essa é uma operação sobrecarregada, mas, em termos simples, ela é usada para definir o método HTTP usando o operador "=". Aqui vai um exemplo de como aplicar esse operador na prática:
CHttpMethod method; method = HTTP_METHOD_POST;
- Funções de verificação (IsPost(), IsGet() etc.): Elas facilitam a checagem do método, tornando o código mais legível e simples. Aqui está um exemplo de como essas funções podem nos ajudar:
CHttpMethod method; method.SetMethod("POST") if(method.GetMethod() == HTTP_METHOD_POST) { //--- Action } //--- Or if(method.IsPost()) { //--- Action }
Assim, evitamos comparações explícitas de métodos.
//+------------------------------------------------------------------+ //| class : CHttpMethod | //| | //| [PROPERTY] | //| Name : CHttpMethod | //| Heritage : No heritage | //| Description : Saved http method. | //| | //+------------------------------------------------------------------+ class CHttpMethod { private: ENUM_HTTP_METHOD m_method; // Stores the method that will be used public: CHttpMethod(void); ~CHttpMethod(void); //--- Get and set void operator=(ENUM_HTTP_METHOD method); void Set(ENUM_HTTP_METHOD method); bool Set(string method); ENUM_HTTP_METHOD Get(void); string GetAsString(void); //--- Check method bool IsConnect(void); bool IsGet(void); bool IsPost(void); bool IsPut(void); bool IsDelete(void); bool IsPatch(void); bool IsHead(void); bool IsOption(void); bool IsTrace(void); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CHttpMethod::CHttpMethod(void) { } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CHttpMethod::~CHttpMethod(void) { } //+------------------------------------------------------------------+ //| Defines the http method | //+------------------------------------------------------------------+ void CHttpMethod::operator=(ENUM_HTTP_METHOD method) { m_method = method; } //+------------------------------------------------------------------+ //| Defines the http method | //+------------------------------------------------------------------+ void CHttpMethod::Set(ENUM_HTTP_METHOD method) { m_method = method; } //+------------------------------------------------------------------+ //| Defines the http method | //+------------------------------------------------------------------+ bool CHttpMethod::Set(string method) { string method_upper = method; StringToUpper(method_upper); if(method_upper == "CONNECT") { m_method = HTTP_METHOD_CONNECT; return(true); } else if(method_upper == "DELETE") { m_method = HTTP_METHOD_DELETE; return(true); } else if(method_upper == "GET") { m_method = HTTP_METHOD_GET; return(true); } else if(method_upper == "HEAD") { m_method = HTTP_METHOD_HEAD; return(true); } else if(method_upper == "OPTIONS") { m_method = HTTP_METHOD_OPTION; return(true); } else if(method_upper == "PATCH") { m_method = HTTP_METHOD_PATCH; return(true); } else if(method_upper == "POST") { m_method = HTTP_METHOD_POST; return(true); } else if(method_upper == "PUT") { m_method = HTTP_METHOD_PUT; return(true); } else if(method_upper == "TRACE") { m_method = HTTP_METHOD_TRACE; return(true); } return(false); } //+------------------------------------------------------------------+ //| Get http method | //+------------------------------------------------------------------+ ENUM_HTTP_METHOD CHttpMethod::Get(void) { return(m_method); } //+------------------------------------------------------------------+ //| Get the description of the selected http method | //+------------------------------------------------------------------+ string CHttpMethod::GetAsString(void) { switch(m_method) { case HTTP_METHOD_NULL: return "NULL"; case HTTP_METHOD_CONNECT: return "CONNECT"; case HTTP_METHOD_DELETE: return "DELETE"; case HTTP_METHOD_GET: return "GET"; case HTTP_METHOD_HEAD: return "HEAD"; case HTTP_METHOD_OPTION: return "OPTIONS"; case HTTP_METHOD_PATCH: return "PATCH"; case HTTP_METHOD_POST: return "POST"; case HTTP_METHOD_PUT: return "PUT"; case HTTP_METHOD_TRACE: return "TRACE"; default: return "Unknown HTTP Method"; } } //+------------------------------------------------------------------+ //| Check if method is connect | //+------------------------------------------------------------------+ bool CHttpMethod::IsConnect(void) { return(m_method == HTTP_METHOD_CONNECT); } //+------------------------------------------------------------------+ //| Check if method is get | //+------------------------------------------------------------------+ bool CHttpMethod::IsGet(void) { return(m_method == HTTP_METHOD_GET); } //+------------------------------------------------------------------+ //| Check if method is post | //+------------------------------------------------------------------+ bool CHttpMethod::IsPost(void) { return(m_method == HTTP_METHOD_POST); } //+------------------------------------------------------------------+ //| Check if method is put | //+------------------------------------------------------------------+ bool CHttpMethod::IsPut(void) { return(m_method == HTTP_METHOD_PUT); } //+------------------------------------------------------------------+ //| Check if method is delete | //+------------------------------------------------------------------+ bool CHttpMethod::IsDelete(void) { return(m_method == HTTP_METHOD_DELETE); } //+------------------------------------------------------------------+ //| Check if method is patch | //+------------------------------------------------------------------+ bool CHttpMethod::IsPatch(void) { return(m_method == HTTP_METHOD_PATCH); } //+------------------------------------------------------------------+ //| Check if method is head | //+------------------------------------------------------------------+ bool CHttpMethod::IsHead(void) { return(m_method == HTTP_METHOD_HEAD); } //+------------------------------------------------------------------+ //| Check if method is option | //+------------------------------------------------------------------+ bool CHttpMethod::IsOption(void) { return(m_method == HTTP_METHOD_OPTION); } //+------------------------------------------------------------------+ //| Check if method is trace | //+------------------------------------------------------------------+ bool CHttpMethod::IsTrace(void) { return(m_method == HTTP_METHOD_TRACE); } //+------------------------------------------------------------------+
Com isso, finalizamos a classe responsável por armazenar o método HTTP utilizado. Agora contamos com algumas funções auxiliares que vão poupar código no futuro. Vamos para a próxima classe de suporte.
Código de status
Os códigos de status, em termos simples, são números. Esse número é padronizado e enviado pelo servidor ao cliente após o processamento da requisição. Cada código é formado por três dígitos, sendo que o primeiro indica a categoria à qual o status pertence (1xx, 2xx, 3xx, 4xx e 5xx). Esse código apenas informa o resultado da requisição: se foi bem-sucedida, se houve erro do lado do servidor ou se a requisição foi feita de forma incorreta. Existem diversos códigos de status. Isso vai de 100 a 599, divididos em 5 categorias. Para saber a qual categoria um código pertence, basta identificar em qual faixa ele está, veja a tabela com os valores:
Faixa do código de status | Descrição |
---|---|
100-199 | Não é algo que vemos com frequência. São respostas do tipo "estou processando, aguarde". É o servidor informando que está trabalhando na sua requisição, mas ainda não terminou. |
200-299 | Ah, essa é a resposta que mais gostamos! Significa que tudo ocorreu bem. O mais famoso deles é o 200 OK – sinal de que "deu tudo certo". Você pediu, foi entregue. Simples assim. |
300-399 | Aqui, o servidor basicamente diz: "Ops, você está no lugar errado, vá para lá". O 301 "Movido permanentemente" é um redirecionamento definitivo, enquanto o 302 "Encontrado" é temporário, algo como: "Estou em manutenção, mas você pode achar isso aqui por enquanto". |
400-499 | São os famosos erros que nós, usuários, frequentemente cometemos. O mais conhecido é o 404 "Não encontrado", quando a página que você procura simplesmente não existe. É como chegar no endereço certo e descobrir que o prédio foi demolido. |
500-599 | Agora, quando o problema está do outro lado, a culpa é do servidor. O famoso erro interno do servidor 500 é, basicamente, quando o servidor levanta as mãos e diz: "alguma coisa deu errado por aqui". |
Existem vários códigos possíveis. Não vou descrever todos para não deixar o artigo longo demais. Se quiser conhecer todos os valores possíveis, leia aqui, onde cada código é explicado em detalhes. Se quiser saber mais sobre o protocolo HTTP, vale a pena essa leitura. No dia a dia de um desenvolvedor, usamos apenas alguns códigos, e muitos deles raramente são vistos na internet. Aqui estão os mais comuns:
1xx: Informativo
- 100 Continue: O servidor recebeu os cabeçalhos e o cliente pode continuar enviando o corpo da requisição.
- 101 Switching Protocols: O cliente solicitou a troca de protocolo e o servidor aceitou.
2xx: Sucesso
- 200 OK: A requisição foi concluída com sucesso.
- 201 Created: A requisição foi concluída com sucesso e um novo recurso foi criado. 204 No Content: A requisição foi concluída com sucesso, mas a resposta não contém conteúdo.
3xx: Redirecionamento
- 301 Moved Permanently: O recurso foi movido permanentemente para um novo URL.
- 302 Found: O recurso foi movido temporariamente para um novo URL.
- 304 Not Modified: O recurso não foi modificado desde a última requisição, permitindo ao cliente usar a versão em cache.
4xx: Erros do cliente
- 400 Bad Request: A requisição é inválida ou foi malformada.
- 401 Unauthorized: Acesso não autorizado; é necessária autenticação.
- 403 Forbidden: O servidor entendeu a requisição, mas negou o acesso.
- 404 Not Found: O recurso solicitado não foi encontrado.
- 405 Method Not Allowed: O método HTTP usado não é permitido para o recurso solicitado.
5xx: Erros do servidor
- 500 Internal Server Error: Ocorreu um erro genérico no servidor.
- 502 Bad Gateway: O servidor recebeu uma resposta inválida ao tentar processar a requisição.
- 503 Service Unavailable: O servidor está temporariamente indisponível, geralmente por sobrecarga ou manutenção.
- 504 Gateway Timeout: O servidor não recebeu resposta a tempo de outro servidor ao qual tentou se conectar.
Agora que entendemos todas as categorias de status e os mais utilizados, quero que a biblioteca seja capaz de lidar com todos os status possíveis. Para isso, vamos criar uma classe capaz de processar qualquer código de status recebido do servidor, desde que ele seja válido.
Criação da classe CHttpStatusCode
Agora que conhecemos todos os possíveis códigos de status, vamos adicionar a implementação correspondente na biblioteca. O objetivo aqui é simples: criar uma classe responsável por armazenar o código de status recebido. Essa classe também deve oferecer suporte para a descrição de cada status, além de permitir identificar rapidamente a qual categoria esse status pertence.
Vamos ao código. Na mesma pasta criada anteriormente para a classe CHttpMethod, vamos criar um novo arquivo chamado HttpStatusCode.mqh. No final, o caminho completo ficará assim: Includes/Connexus/Constants/HttpStatusCode.mqh.
//+------------------------------------------------------------------+ //| HttpStatusCode.mqh | //| Copyright 2024, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, MetaQuotes Ltd." #property link "https://www.mql5.com" //+------------------------------------------------------------------+ //| class : CHttpStatusCodes | //| | //| [PROPERTY] | //| Name : CHttpStatusCodes | //| Heritage : No heritage | //| Description : Saved http status code. | //| | //+------------------------------------------------------------------+ class CHttpStatusCodes { public: CHttpStatusCodes(void); ~CHttpStatusCodes(void); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CHttpStatusCodes::CHttpStatusCodes(void) { } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CHttpStatusCodes::~CHttpStatusCodes(void) { } //+------------------------------------------------------------------+
Para conter todos os possíveis códigos de status, vamos criar um enum com todos os valores possíveis. O nome do enum será ENUM_HTTP_STATUS, e cada valor corresponderá ao código de status adequado.
enum ENUM_HTTP_STATUS { //--- Mql error HTTP_STATUS_URL_NOT_ALLOWED = -1, HTTP_STATUS_URL_NOT_DEFINED = 1, HTTP_STATUS_METHOD_NOT_DEFINED = 2, //--- Informational HTTP_STATUS_CONTINUE = 100, HTTP_STATUS_SWITCHING_PROTOCOLS = 101, HTTP_STATUS_PROCESSING = 102, HTTP_STATUS_EARLY_HINTS = 103, //--- Successul HTTP_STATUS_OK = 200, HTTP_STATUS_CREATED = 201, HTTP_STATUS_ACCEPTED = 202, HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION = 203, HTTP_STATUS_NO_CONTENT = 204, HTTP_STATUS_RESET_CONTENT = 205, HTTP_STATUS_PARTIAL_CONTENT = 206, HTTP_STATUS_MULTI_STATUS = 207, HTTP_STATUS_ALREADY_REPORTED = 208, //--- Redirection messages HTTP_STATUS_MULTIPLE_CHOICES = 300, HTTP_STATUS_MOVED_PERMANENTLY = 301, HTTP_STATUS_FOUND = 302, HTTP_STATUS_SEE_OTHER = 303, HTTP_STATUS_NOT_MODIFIED = 304, HTTP_STATUS_USE_PROXY = 305, HTTP_STATUS_SWITCH_PROXY = 306, HTTP_STATUS_TEMPORARY_REDIRECT = 307, HTTP_STATUS_PERMANENT_REDIRECT = 308, //--- Client error HTTP_STATUS_BAD_REQUEST = 400, HTTP_STATUS_UNAUTHORIZED = 401, HTTP_STATUS_PAYMENT_REQUIRED = 402, HTTP_STATUS_FORBIDDEN = 403, HTTP_STATUS_NOT_FOUND = 404, HTTP_STATUS_METHOD_NOT_ALLOWED = 405, HTTP_STATUS_NOT_ACCEPTABLE = 406, HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED = 407, HTTP_STATUS_REQUEST_TIMEOUT = 408, HTTP_STATUS_CONFLICT = 409, HTTP_STATUS_GONE = 410, HTTP_STATUS_LENGTH_REQUIRED = 411, HTTP_STATUS_PRECONDITION_FAILED = 412, HTTP_STATUS_PAYLOAD_TOO_LARGE = 413, HTTP_STATUS_URI_TOO_LONG = 414, HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE = 415, HTTP_STATUS_RANGE_NOT_SATISFIABLE = 416, HTTP_STATUS_EXPECTATION_FAILED = 417, HTTP_STATUS_MISDIRECTED_REQUEST = 421, HTTP_STATUS_UNPROCESSABLE_ENTITY = 422, HTTP_STATUS_LOCKED = 423, HTTP_STATUS_FAILED_DEPENDENCY = 424, HTTP_STATUS_TOO_EARLY = 425, HTTP_STATUS_UPGRADE_REQUIRED = 426, HTTP_STATUS_PRECONDITION_REQUIRED = 428, HTTP_STATUS_TOO_MANY_REQUESTS = 429, HTTP_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE = 431, HTTP_STATUS_UNAVAILABLE_FOR_LEGAL_REASONS = 451, //--- Server error HTTP_STATUS_INTERNAL_SERVER_ERROR = 500, HTTP_STATUS_NOT_IMPLEMENTED = 501, HTTP_STATUS_BAD_GATEWAY = 502, HTTP_STATUS_SERVICE_UNAVAILABLE = 503, HTTP_STATUS_GATEWAY_TIMEOUT = 504, HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED = 505, HTTP_STATUS_VARIANT_ALSO_NEGOTIATES = 506, HTTP_STATUS_INSUFFICIENT_STORAGE = 507, HTTP_STATUS_LOOP_DETECTED = 508, HTTP_STATUS_NOT_EXTENDED = 510, HTTP_STATUS_NETWORK_AUTHENTICATION_REQUIRED = 511 };
Observe que adicionei alguns comentários separando as categorias de cada status. Note também que nos primeiros valores do enum incluí "códigos de status personalizados", que serão gerados automaticamente pela biblioteca, são eles:
- HTTP_STATUS_URL_NOT_ALLOWED: O URL não foi adicionado à lista de URLs permitidos no terminal
- HTTP_STATUS_URL_NOT_DEFINED: O URL não foi definido na requisição
- HTTP_STATUS_METHOD_NOT_DEFINED: Não foi definido um método válido para a requisição
Quando a função WebRequest é chamada e retorna o valor -1, isso significa que o URL não foi adicionado no terminal, conforme indicado na documentação do MQL5, portanto a biblioteca deve automaticamente retornar HTTP_STATUS_URL_NOT_ALLOWED. A mesma lógica será aplicada para os outros códigos personalizados, mas não vamos nos aprofundar nisso agora.
Seguindo com o desenvolvimento da classe, ela será semelhante à CHttpMethod, vamos adicionar uma nova variável privada chamada m_status do tipo ENUM_HTTP_STATUS, além de alguns métodos auxiliares para definir e obter o valor dessa variável:
- operator=(int) e operator=(ENUM_HTTP_STATUS): Definem o valor de m_status usando o operador =, recebendo um número inteiro ou um valor enumerado.
- Set(ENUM_HTTP_STATUS): Define o código de status usando um valor do enum.
- Get() e GetMessage(): Retornam o código de status atual ou apenas a mensagem correspondente ao código armazenado.
Abaixo está o código com a implementação desses métodos:
//+------------------------------------------------------------------+ //| class : CHttpStatusCodes | //| | //| [PROPERTY] | //| Name : CHttpStatusCodes | //| Heritage : No heritage | //| Description : Saved http status code. | //| | //+------------------------------------------------------------------+ class CHttpStatusCodes { private: ENUM_HTTP_STATUS m_status; // Stores the status used public: CHttpStatusCodes(void); ~CHttpStatusCodes(void); //--- Set void operator=(int status); void operator=(ENUM_HTTP_STATUS status); void Set(ENUM_HTTP_STATUS status); //--- Get ENUM_HTTP_STATUS Get(void); string GetMessage(void); }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CHttpStatusCodes::CHttpStatusCodes(void) { } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CHttpStatusCodes::~CHttpStatusCodes(void) { } //+------------------------------------------------------------------+ //| Assignment operator to set status from integer value | //+------------------------------------------------------------------+ void CHttpStatusCodes::operator=(int status) { m_status = (ENUM_HTTP_STATUS)status; } //+------------------------------------------------------------------+ //| Assignment operator to set status from ENUM_HTTP_STATUS | //+------------------------------------------------------------------+ void CHttpStatusCodes::operator=(ENUM_HTTP_STATUS status) { m_status = status; } //+------------------------------------------------------------------+ //| Sets the HTTP status code | //+------------------------------------------------------------------+ void CHttpStatusCodes::Set(ENUM_HTTP_STATUS status) { m_status = status; } //+------------------------------------------------------------------+ //| Returns the stored HTTP status code | //+------------------------------------------------------------------+ ENUM_HTTP_STATUS CHttpStatusCodes::Get(void) { return(m_status); } //+------------------------------------------------------------------+ //| Returns a message corresponding to the stored HTTP status code | //+------------------------------------------------------------------+ string CHttpStatusCodes::GetMessage(void) { switch(m_status) { case HTTP_STATUS_URL_NOT_ALLOWED: return "The URL was not added to the list of allowed URLs in the terminal"; case HTTP_STATUS_URL_NOT_DEFINED: return "URL was not defined in the request"; case HTTP_STATUS_METHOD_NOT_DEFINED: return "Method was not defined in the request"; case HTTP_STATUS_CONTINUE: return "Continue"; case HTTP_STATUS_SWITCHING_PROTOCOLS: return "Switching Protocols"; case HTTP_STATUS_PROCESSING: return "Processing"; case HTTP_STATUS_EARLY_HINTS: return "Early Hints"; case HTTP_STATUS_OK: return "OK"; case HTTP_STATUS_CREATED: return "Created"; case HTTP_STATUS_ACCEPTED: return "Accepted"; case HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION: return "Non-Authoritative Information"; case HTTP_STATUS_NO_CONTENT: return "No Content"; case HTTP_STATUS_RESET_CONTENT: return "Reset Content"; case HTTP_STATUS_PARTIAL_CONTENT: return "Partial Content"; case HTTP_STATUS_MULTI_STATUS: return "Multi-Status"; case HTTP_STATUS_ALREADY_REPORTED: return "Already Reported"; case HTTP_STATUS_MULTIPLE_CHOICES: return "Multiple Choices"; case HTTP_STATUS_MOVED_PERMANENTLY: return "Moved Permanently"; case HTTP_STATUS_FOUND: return "Found"; case HTTP_STATUS_SEE_OTHER: return "See Other"; case HTTP_STATUS_NOT_MODIFIED: return "Not Modified"; case HTTP_STATUS_USE_PROXY: return "Use Proxy"; case HTTP_STATUS_SWITCH_PROXY: return "Switch Proxy"; case HTTP_STATUS_TEMPORARY_REDIRECT: return "Temporary Redirect"; case HTTP_STATUS_PERMANENT_REDIRECT: return "Permanent Redirect"; case HTTP_STATUS_BAD_REQUEST: return "Bad Request"; case HTTP_STATUS_UNAUTHORIZED: return "Unauthorized"; case HTTP_STATUS_PAYMENT_REQUIRED: return "Payment Required"; case HTTP_STATUS_FORBIDDEN: return "Forbidden"; case HTTP_STATUS_NOT_FOUND: return "Not Found"; case HTTP_STATUS_METHOD_NOT_ALLOWED: return "Method Not Allowed"; case HTTP_STATUS_NOT_ACCEPTABLE: return "Not Acceptable"; case HTTP_STATUS_PROXY_AUTHENTICATION_REQUIRED: return "Proxy Authentication Required"; case HTTP_STATUS_REQUEST_TIMEOUT: return "Request Timeout"; case HTTP_STATUS_CONFLICT: return "Conflict"; case HTTP_STATUS_GONE: return "Gone"; case HTTP_STATUS_LENGTH_REQUIRED: return "Length Required"; case HTTP_STATUS_PRECONDITION_FAILED: return "Precondition Failed"; case HTTP_STATUS_PAYLOAD_TOO_LARGE: return "Payload Too Large"; case HTTP_STATUS_URI_TOO_LONG: return "URI Too Long"; case HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE: return "Unsupported Media Type"; case HTTP_STATUS_RANGE_NOT_SATISFIABLE: return "Range Not Satisfiable"; case HTTP_STATUS_EXPECTATION_FAILED: return "Expectation Failed"; case HTTP_STATUS_MISDIRECTED_REQUEST: return "Misdirected Request"; case HTTP_STATUS_UNPROCESSABLE_ENTITY: return "Unprocessable Entity"; case HTTP_STATUS_LOCKED: return "Locked"; case HTTP_STATUS_FAILED_DEPENDENCY: return "Failed Dependency"; case HTTP_STATUS_TOO_EARLY: return "Too Early"; case HTTP_STATUS_UPGRADE_REQUIRED: return "Upgrade Required"; case HTTP_STATUS_PRECONDITION_REQUIRED: return "Precondition Required"; case HTTP_STATUS_TOO_MANY_REQUESTS: return "Too Many Requests"; case HTTP_STATUS_REQUEST_HEADER_FIELDS_TOO_LARGE: return "Request Header Fields Too Large"; case HTTP_STATUS_UNAVAILABLE_FOR_LEGAL_REASONS: return "Unavailable For Legal Reasons"; case HTTP_STATUS_INTERNAL_SERVER_ERROR: return "Internal Server Error"; case HTTP_STATUS_NOT_IMPLEMENTED: return "Not Implemented"; case HTTP_STATUS_BAD_GATEWAY: return "Bad Gateway"; case HTTP_STATUS_SERVICE_UNAVAILABLE: return "Service Unavailable"; case HTTP_STATUS_GATEWAY_TIMEOUT: return "Gateway Timeout"; case HTTP_STATUS_HTTP_VERSION_NOT_SUPPORTED: return "HTTP Version Not Supported"; case HTTP_STATUS_VARIANT_ALSO_NEGOTIATES: return "Variant Also Negotiates"; case HTTP_STATUS_INSUFFICIENT_STORAGE: return "Insufficient Storage"; case HTTP_STATUS_LOOP_DETECTED: return "Loop Detected"; case HTTP_STATUS_NOT_EXTENDED: return "Not Extended"; case HTTP_STATUS_NETWORK_AUTHENTICATION_REQUIRED: return "Network Authentication Required"; default: return "Unknown HTTP Status"; } } //+------------------------------------------------------------------+
Vamos adicionar também alguns métodos auxiliares responsáveis por verificar se o código de status armazenado na classe pertence a uma determinada categoria, são eles:
- bool IsInformational(void): Faixa informativa (100 - 199)
- bool IsSuccess(void): Faixa de sucesso (200 - 299)
- bool IsRedirection(void): Faixa de redirecionamento (300 - 399)
- bool IsClientError(void): Faixa de erro do cliente (400 - 499)
- bool IsServerError(void): Faixa de erro do servidor (500 - 599)
//+------------------------------------------------------------------+ //| class : CHttpStatusCodes | //| | //| [PROPERTY] | //| Name : CHttpStatusCodes | //| Heritage : No heritage | //| Description : Saved http status code. | //| | //+------------------------------------------------------------------+ class CHttpStatusCodes { private: ENUM_HTTP_STATUS m_status; // Stores the status used public: CHttpStatusCodes(void); ~CHttpStatusCodes(void); //--- Check which group the code is in bool IsInformational(void); // Checks if the status code is in the informational response range (100 - 199) bool IsSuccess(void); // Check if the status code is in the success range (200 - 299) bool IsRedirection(void); // Check if the status code is in the redirect range (300 - 399) bool IsClientError(void); // Checks if the status code is in the client error range (400 - 499) bool IsServerError(void); // Check if the status code is in the server error range (500 - 599) }; //+------------------------------------------------------------------+ //| Constructor | //+------------------------------------------------------------------+ CHttpStatusCodes::CHttpStatusCodes(void) { } //+------------------------------------------------------------------+ //| Destructor | //+------------------------------------------------------------------+ CHttpStatusCodes::~CHttpStatusCodes(void) { } //+------------------------------------------------------------------+ //| Checks if the status code is in the informational response | //| range (100 - 199) | //+------------------------------------------------------------------+ bool CHttpStatusCodes::IsInformational(void) { return(m_status >= 100 && m_status <= 199); } //+------------------------------------------------------------------+ //| Check if the status code is in the success range (200 - 299) | //+------------------------------------------------------------------+ bool CHttpStatusCodes::IsSuccess(void) { return(m_status >= 200 && m_status <= 299); } //+------------------------------------------------------------------+ //| Check if the status code is in the redirect range (300 - 399) | //+------------------------------------------------------------------+ bool CHttpStatusCodes::IsRedirection(void) { return(m_status >= 300 && m_status <= 399); } //+------------------------------------------------------------------+ //| Checks if the status code is in the client error range | //| (400 - 499) | //+------------------------------------------------------------------+ bool CHttpStatusCodes::IsClientError(void) { return(m_status >= 400 && m_status <= 499); } //+------------------------------------------------------------------+ //| Check if the status code is in the server error range (500 - 599)| //+------------------------------------------------------------------+ bool CHttpStatusCodes::IsServerError(void) { return(m_status >= 500 && m_status <= 599); } //+------------------------------------------------------------------+
Conclusão
Para tornar o funcionamento da biblioteca mais claro, siga o esquema abaixo:
Já temos prontos todos os classes auxiliares responsáveis pelo tratamento independente de cada elemento HTTP. Temos as classes CQueryParam, CHttpHeader e CHttpBody, que utilizam a classe CJson, mas sem relação de herança entre elas. As classes criadas neste artigo ainda não estão conectadas às demais; na próxima parte, vamos integrá-las, criando a requisição e a resposta HTTP.
Neste artigo, tratamos dos métodos HTTP e dos códigos de status, dois elementos fundamentais na comunicação entre cliente e servidor na internet. Compreender o que cada método faz de fato permite criar requisições mais precisas, informando ao servidor qual ação deve ser executada e tornando a comunicação mais eficiente. Cada método tem um papel específico na comunicação, e usá-lo corretamente torna a interação com APIs mais clara, tanto para o cliente quanto para o servidor, evitando surpresas.
Além disso, falamos sobre os códigos de status, que são a resposta direta do servidor sobre o que aconteceu com a requisição. Eles variam desde o simples "tudo certo" (200 OK) até mensagens de erro no lado do cliente (4xx) ou no lado do servidor (5xx). Saber lidar com esses códigos é uma habilidade valiosa, já que muitas vezes um erro não significa o fim do processo, mas sim a oportunidade de ajustar ou tentar novamente.
Durante o desenvolvimento da biblioteca Connexus, aprendemos como lidar com cada um desses elementos, o que deixa a biblioteca mais robusta e preparada para lidar com as particularidades da comunicação HTTP. A partir de agora, nossa classe responsável por métodos e códigos de status estará pronta para oferecer ao desenvolvedor mais controle e segurança ao interagir com APIs.
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/16136
Aviso: Todos os direitos sobre esses materiais pertencem à MetaQuotes Ltd. É proibida a reimpressão total ou parcial.
This article was written by a user of the site and reflects their personal views. MetaQuotes Ltd is not responsible for the accuracy of the information presented, nor for any consequences resulting from the use of the solutions, strategies or recommendations described.





- 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