English 日本語
preview
Anfragen in Connexus (Teil 6): Erstellen einer HTTP-Anfrage und -Antwort

Anfragen in Connexus (Teil 6): Erstellen einer HTTP-Anfrage und -Antwort

MetaTrader 5Beispiele | 21 Januar 2025, 08:50
94 0
joaopedrodev
joaopedrodev

Einführung

Dieser Artikel ist Teil einer laufenden Serie, in der wir eine Bibliothek namens Connexus aufbauen. Im ersten Artikel haben wir uns mit den grundlegenden Funktionen der Funktion WebRequest befasst, jeden ihrer Parameter verstanden und einen Beispielcode erstellt, der ihre Verwendung und die damit verbundenen Herausforderungen demonstriert. Im vorigen Artikel haben wir uns mit den HTTP-Methoden und den vom Server zurückgegebenen Statuscodes befasst, die angeben, ob die Anfrage erfolgreich bearbeitet wurde oder ob ein Fehler auf der Client- oder Serverseite aufgetreten ist.

In diesem sechsten Artikel der Connexus-Bibliotheksreihe befassen wir uns mit einer vollständigen HTTP-Anfrage, wobei jede Komponente, aus der eine Anfrage besteht, behandelt wird. Wir werden eine Klasse erstellen, die den Anfrage als Ganzes repräsentiert, was uns helfen wird, die zuvor erstellten Klassen zusammenzuführen. Außerdem werden wir eine ähnliche Klasse entwickeln, um die Antwort des Servers zu verarbeiten, die die Antwortdaten, den Statuscode und sogar die Dauer der Anfrage enthält.

Bei der HTTP-Kommunikation setzt sich eine Anfrage aus mehreren Komponenten zusammen, die zusammen die komplette Anfrage bilden. Wir haben uns bereits in früheren Artikeln mit all diesen Komponenten beschäftigt und für jedes Element der Anfrage eine eigene Klasse erstellt. Fassen wir die Elemente im Folgenden zusammen:

  • URL: Definiert die Adresse des Servers im Internet und setzt sich aus kleineren Teilen wie Domäne, Port, Pfad usw. zusammen. Dies wurde in Teil 2 von Connexus ausführlicher behandelt, wo wir eine Klasse zur korrekten Formatierung einer URL erstellt haben.
  • Header: Dies sind zusätzliche Daten, die mit der Anfrage gesendet werden, um Details über die Anfrage zu liefern, die nicht Teil des Körpers oder der URL sind. Dies wurde in Teil 3 von Connexus ausführlicher behandelt, wo wir auch eine Klasse erstellt haben, die für die Organisation des Request Headers zuständig ist.
  • Body: Bezieht sich auf den tatsächlichen Inhalt, der gesendet oder empfangen wird. Einfach ausgedrückt: Im Body werden die Daten gespeichert, die uns interessieren und die wir an den Server senden wollen. In Teil 4 haben wir dies ausführlicher besprochen und auch eine Klasse erstellt, die für die Speicherung des Bodys der Anfrage verantwortlich ist und die das Hinzufügen des Bodys in verschiedenen Formaten unterstützt, z. B. als reiner Text (String), JSON oder char[] (binär).
  • HTTP-Methode: HTTP-Methoden werden vom Client verwendet, um dem Server mitzuteilen, welche Aktion er durchführen möchte. Dies wurde in Teil 5 von Connexus ausführlicher behandelt.
  • Zeitüberschreitung: Timeout wurde in den vorherigen Artikeln nicht behandelt, aber um es kurz zu erklären, es ist die Zeit in Millisekunden, die der Server hat, um zu antworten. Dauert die Anfrage länger als die zugewiesene Zeit, wird sie abgebrochen, was zu einem Timeout-Fehler führt. Dieser Wert kann nützlich sein, um Szenarien zu vermeiden, in denen der Server zu lange braucht, um zu antworten, da die WebRequest-Funktion synchron ist, was bedeutet, dass der Expert Advisor „pausiert“, während er auf die Antwort des Servers wartet. Dies könnte problematisch sein, wenn die Anfrage viel länger dauert als erwartet. Um dieses Szenario zu vermeiden, empfiehlt es sich, eine Zeitüberschreitung zu verwenden. Der Wert für die Zeitüberschreitung kann je nach Bedarf variieren, aber für die meisten Server sind 5000 Millisekunden (5 Sekunden) ausreichend, um die Anfrage korrekt zu bearbeiten.

Jede dieser Komponenten spielt eine grundlegende Rolle bei der Erstellung einer ordnungsgemäßen HTTP-Anfrage, aber es ist wichtig zu beachten, dass nicht alle von ihnen obligatorisch sind. Die einzigen erforderlichen Elemente sind die URL und die HTTP-Methode (GET, POST, PUT, usw.).

Um uns einen Überblick über den Fortschritt der Bibliothek und die bereits erstellten Klassen zu verschaffen, werfen wir einen Blick auf das aktuelle Diagramm der Bibliothek:

Strukturdiagramm

Beachten Sie, dass wir bereits über Klassen verfügen, die HTTP-Methoden, Statuscodes, URLs mit Abfrageparametern, Header und den Body behandeln.


Das Entwurfsmuster Facade

Um den Aufbau der Bibliothek fortzusetzen, werden wir ein Entwurfsmuster implementieren. Wenn Sie mit Entwurfsmuster nicht vertraut sind, empfehle ich Ihnen die Lektüre der Artikelserie Entwurfsmuster in der Softwareentwicklung und MQL5, die von Mohamed Abdelmaaboud geschrieben wurde. In dieser Serie beschreibt der Autor mehrere Entwurfsmuster mit Beispielcode. Für die Connexus-Bibliothek werden wir das „Facade“-Entwurfsmuster implementieren, das ein bekanntes Muster in der Programmierung ist. Dieses Muster bietet eine vereinfachte Schnittstelle zu einer komplexeren Reihe von Subsystemen, die die interne Komplexität verbirgt und es dem Kunden ermöglicht, auf viel einfachere Weise mit dem System zu interagieren.

Stellen wir uns ein Beispiel im Kontext der Bibliothek vor: Sie wollen einen Anfrage erstellen. Dazu müssen Sie eine Instanz von jedem der Anfrageelemente erstellen und sie etwa so konfigurieren:

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;

Dieser Ansatz macht den Code unübersichtlich, erfordert die Erstellung mehrerer Instanzen, verbraucht viele Zeilen und macht den Code weniger lesbar. Die Situation verschlimmert sich bei der Arbeit mit zahlreichen Anfragen, da die Verwaltung mehrerer Objekte wie Header, Body und URL kompliziert und schwer zu pflegen ist. Hier kommt das Entwurfsmuster Facade ins Spiel. Um auf das Konzept zurückzukommen: Dieses Muster bietet eine vereinfachte Schnittstelle zu einer komplexeren Reihe von Subsystemen, die die interne Komplexität verbirgt und es dem Kunden ermöglicht, auf viel einfachere Weise mit dem System zu interagieren.

In diesem Zusammenhang sind die Subsysteme die Klassen für Anforderungselemente wie CHttpBody, CHttpHeaders, usw., und das Ziel ist es, eine intuitivere Schnittstelle für sie zu schaffen. Dieses Muster löst das Problem durch die Einführung einer Klasse oder Schnittstelle, die als „Facade“ für den Zugriff auf die Teilsysteme dient. Der Endentwickler interagiert nur mit dieser vereinfachten Schnittstelle.

Zusammenfassend lässt sich sagen, dass die Architektur von Facade die folgenden Vorteile bietet:

  1. Vereinfachte Interaktion: Anstatt direkt mit einer Reihe komplexer Klassen zu arbeiten, kann der Entwickler eine vereinfachte Schnittstelle verwenden, die die internen Details verbirgt.
  2. Reduzierte Kopplung: Da der Client nicht direkt mit den internen Subsystemen gekoppelt ist, können Änderungen in diesen Subsystemen vorgenommen werden, ohne dass der Client davon betroffen ist.
  3. Verbesserte Wartbarkeit: Die klare Trennung zwischen der Schnittstelle Facade und den internen Subsystemen erleichtert die Wartung und Erweiterung des Codes, da alle internen Änderungen von „Facade“ abstrahiert werden können.

Wie würde dieses Entwurfsmuster in der Bibliothek umgesetzt werden? Um dies zu erreichen, erstellen wir eine neue Klasse namens CHttpRequest, die die Subsysteme enthalten wird. Für den Bibliotheksnutzer sollte die Verwendung dieser Klasse in etwa so aussehen:

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");

Beachten Sie, dass der Code viel einfacher und lesbarer geworden ist, was genau die Idee hinter diesem Entwurfsmuster ist. Das Facade-Muster bietet eine vereinfachte Schnittstelle (CHttpRequest) für einen komplexeren Satz von Subsystemen (Verwaltung von Instanzen von CHttpBody, CHttpHeader usw.), wodurch die interne Komplexität verborgen wird und der Client auf eine viel einfachere Weise mit dem System interagieren kann.


Erstellen der Klasse CHttpRequest

Nachdem wir nun das Konzept von „Facade“ verstanden haben, können wir diese Architektur auf die Klasse CHttpRequest anwenden. Legen wir diese Klasse in einem neuen Ordner namens Core an. Die Datei erhält den Namen HttpRequest.mqh, und der endgültige Pfad lautet Include/Connexus/Core/HttpRequest.mqh. Zu Beginn sieht die Datei wie folgt aus:
//+------------------------------------------------------------------+
//|                                                  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)
  {
  }
//+------------------------------------------------------------------+

Importieren wir nun die in den letzten Dateien erstellten Klassen: CURL, CHttpBody, CHttpHeader und CHttpMethod. Wir erstellen jeweils eine Instanz und fügen das „*“ hinzu, um den Compiler darüber zu informieren, dass wir den Zeiger manuell verwalten werden. Außerdem fügen wir eine Variable namens m_timeout vom Typ int hinzu, in der der Timeout-Wert für die Anfrage gespeichert wird.

//+------------------------------------------------------------------+
//|                                                  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;
  }
//+------------------------------------------------------------------+

Fügen wir nun einige Methoden hinzu, um auf den Zeiger für jede Instanz zuzugreifen, sowie Methoden zum Setzen und Abrufen des Timeout-Werts:

  • CURL *Url(void) : Gibt den Zeiger auf die URL zurück.
  • CHttpBody *Body(void) : Gibt den Zeiger auf den Body zurück.
  • CHttpHeader *Header(void) : Gibt den Zeiger auf den Header zurück.
  • CHttpMethod *Method(void) : Gibt den Zeiger auf die Methode.
  • CHttpRequest *Timeout(int timeout) : Legt den Timeout fest.
  • int Timeout(void) : Ermittelt den Timeout.

Zusätzlich zu diesen Methoden werden wir einige Hilfsmethoden hinzufügen:

  • void Clear(void) : Entfernt alle Daten aus den Instanzen.

  • string FormatString(void) : Erzeugt eine Zeichenkette mit allen Anfragedaten.

    Beispiel für eine formatierte Anfrage:

    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]
    }
    ---------------

Hier ist die Implementierung der Methoden.

//+------------------------------------------------------------------+
//|                                                  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---------------"
   );
  }
//+------------------------------------------------------------------+

Damit haben wir diese Klasse fertiggestellt, die als „Fassade“ für den Zugriff auf die Objekte dient, die eine HTTP-Anfrage bilden. Es ist wichtig zu beachten, dass ich nur die Teile hinzufüge, die im Code geändert wurden. Die vollständige Datei finden Sie am Ende des beigefügten Artikels.

Mit dieser neuen Klasse CHttpRequest sieht das aktualisierte Bibliotheksdiagramm wie folgt aus:

Diagramm 2

Zusammenfassend lässt sich sagen, dass CHttpRequest als Fassade fungiert und den Prozess der Konfiguration und des Sendens einer HTTP-Anforderung vereinfacht. Intern verwaltet die Klasse CHttpHeaders die Header-Logik, während CHttpBody für die Erstellung des Anforderungskörpers zuständig ist. Der Entwickler, der diese Bibliothek verwendet, muss sich nicht um die Details der Header- oder Body-Behandlung kümmern - er setzt die Werte einfach mit den Methoden von CHttpRequest, und die Klasse Facade kümmert sich um den Rest.


Erstellen der Klasse CHttpResponse

Nach dem gleichen Prinzip erstellen wir eine weitere Klasse, die zur Darstellung der Antwortdaten des Servers verwendet werden soll. Er hat eine ähnliche Struktur wie CHttpRequest . Dies sind die Elemente, aus denen eine Antwort besteht:

  • Header: Genau wie die Anfrage enthält auch die Antwort eine Kopfzeile, die den Client mit Metadaten über die Anfrage informiert.
  • Body: Dieser enthält den Text der Serverantwort. Hier sendet der Server die Daten, die wir erhalten wollen, und das ist der Kern der Nachricht.
  • Status Code: Enthält den Statuscode, den wir in Teil 5 der Serie ausführlicher besprochen haben. Dieser Code ist eine dreistellige Zahl, die angibt, ob die Anfrage erfolgreich bearbeitet wurde oder ob ein Fehler beim Client oder Server aufgetreten ist.
  • Dauer: Speichert die Zeit, die die Anfrage bis zur Fertigstellung benötigte, gemessen in Millisekunden.

Wir erstellen eine neue Datei im Ordner Core mit dem Namen HttpResponse, und der endgültige Pfad lautet Include/Connexus/Core/HttpResponse.mqh. Die erstellte Klasse sollte wie folgt aussehen:

//+------------------------------------------------------------------+
//|                                                 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)
  {
  }
//+------------------------------------------------------------------+

Wir werden die Elemente einer Antwort importieren, die da wären: CHttpHeader, CHttpBody und CHttpStatusCode. Danach erstellen wir eine Instanz jeder dieser Klassen und auch eine private Variable vom Typ ulong, die die Dauer der Anfrage speichert. Der endgültige Code wird wie folgt aussehen:

//+------------------------------------------------------------------+
//|                                                 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;
  }
//+------------------------------------------------------------------+

Kommen wir nun zu den Methoden, die dieser Klasse hinzugefügt werden sollen. Wir beginnen mit den einfachsten, die einfach die Zeiger der einzelnen Instanzen der Klassen zurückgeben, sowie Methoden zum Setzen und Abrufen der Dauer:

  • CHttpHeader *Header(void) : Gibt den Zeiger auf die Kopfzeile zurück.
  • CHttpBody *Body(void) : Gibt den Zeiger auf den Körper zurück.
  • CHttpStatusCodes *StatusCode(void) : Gibt den Zeiger auf den Statuscode zurück.
  • void Duration(ulong duration) : Legt die Dauer fest.
  • ulong Duration(void) : Ermittelt die Dauer.

Wir erstellen für diese Klasse die gleichen Hilfsmethoden wie für CHttpRequest:

  • void Clear(void) : Entfernt alle Daten aus den Instanzen.

  • string FormatString(void) : Erzeugt eine Zeichenkette mit allen Antwortdaten.

    Beispiel für eine formatierte Antwort

    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"
        }
    }
    ---------------

Hier ist der Code mit der Implementierung dieser Funktionen:

//+------------------------------------------------------------------+
//|                                                 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---------------"
   );
  }
//+------------------------------------------------------------------+

Zur Erinnerung: Ich führe hier nur die Änderungen an der Klasse auf, damit der Artikel nicht zu lang wird. Der gesamte verwendete Code ist am Ende des Artikels beigefügt.

Damit ist die Klasse der Antworten abgeschlossen. Es handelt sich um relativ einfache Klassen, die nur ein Ziel haben: die Elemente einer Anfrage oder Antwort zu gruppieren. Auf diese Weise können wir mit einer Anfrage als einem einzigen Objekt arbeiten, was die Verwendung von HTTP-Anfragen und -Antworten erheblich vereinfacht. Mit dieser neuen Klasse CHttpResponse sieht das aktualisierte Diagramm wie folgt aus:

Diagramm 3


Beispiele für den Gebrauch

Ich werde kurz einige Anwendungsbeispiele für diese Klassen geben. Beginnend mit CHttpRequest, werde ich eine HTTP-Anfrage mit dieser Klasse konstruieren.

//--- 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");

Der große Vorteil ist die Einfachheit, mit der eine Anfrage erstellt, eine Kopfzeile und ein Textkörper hinzugefügt oder die HTTP-Methode geändert werden kann.

Für Antworten brauchen wir das Gegenteil, d. h. anstatt ein Request-Objekt einfach zu erstellen, wollen wir ein Response-Objekt einfach lesen, und beide funktionieren auf ähnliche Weise, was ein einfaches Erstellen und Lesen ermöglicht. Ich werde ein Bild beifügen, das zeigt, wie der Entwicklerbildschirm mit Connexus aussieht:

Beispiel 1

Dies wird für Sie, den Entwickler, so aussehen. Ich habe alle Antwortdaten, auf die zugegriffen werden kann, mit unterschiedlichen Farben markiert. Greifen wir auf den Antwortkörper zu:

Beispiel 2

Beachten Sie, dass wir auf den Antwortkörper in verschiedenen Formaten wie string, json oder binär zugreifen können. Hier greifen wir direkt auf den Zeiger der Klasse CHttpBody zu und greifen dann auf alle darin enthaltenen Methoden zu. Als wir eine Klasse für jedes dieser Elemente einer Antwort erstellt haben, dachte ich daran, zu diesem Teil der Bibliothek zu gelangen, in dem wir jede der Klassen verwenden.


Schlussfolgerung

In diesem Artikel haben wir die Bedeutung eines CHttpRequest-Objekts untersucht, das alle Komponenten einer HTTP-Anfrage gruppiert und so für Klarheit, Wiederverwendbarkeit und einfache Wartung des Codes sorgt. Wir haben auch gesehen, wie das Entwurfsmuster Facade angewendet werden kann, um die Interaktion mit komplexen Komponenten zu vereinfachen, die interne Komplexität zu verbergen und eine saubere und effiziente Schnittstelle anzubieten. Im Kontext von Connexus erleichtert die Anwendung des Musters von „Facade“ auf die Klasse ChttpRequest die Erstellung kompletter HTTP-Anfragen und vereinfacht so den Prozess für den Entwickler. Außerdem wurde die Klasse CHttpResponse geschaffen, die demselben Format folgt, aber den Zugriff auf die Daten einer HTTP-Antwort erleichtern soll.

Im nächsten Artikel werden wir uns eingehender mit der Transportschicht befassen, die ein CHttpRequest-Objekt empfangen und die Daten in die WebRequest-Funktion umwandeln muss. Diese letzte Schicht der Bibliothek muss in der Lage sein, die Antwortdaten zu verarbeiten und ein Objekt vom Typ CHttpResponse zurückzugeben, damit der Entwickler die Antwortdaten verwenden kann. Wir sehen uns!

Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/16182

Nachrichtenhandel leicht gemacht (Teil 5): Ausführen des Handels (II) Nachrichtenhandel leicht gemacht (Teil 5): Ausführen des Handels (II)
In diesem Artikel wird die Klasse des Handelsmanagements um Kauf- und Sell-Stop-Aufträge für den Handel mit Nachrichtenereignissen erweitert und eine Ablaufbeschränkung für diese Aufträge implementiert, um den Handel über Nacht zu verhindern. Eine Slippage-Funktion wird in den Experten eingebettet, um zu versuchen, mögliche Slippage zu verhindern oder zu minimieren, die bei der Verwendung von Stop-Order im Handel auftreten können, insbesondere bei Nachrichtenereignissen.
Erstellen eines Handelsadministrator-Panels in MQL5 (Teil V): Zwei-Faktoren-Authentifizierung (2FA) Erstellen eines Handelsadministrator-Panels in MQL5 (Teil V): Zwei-Faktoren-Authentifizierung (2FA)
Heute werden wir uns mit der Verbesserung der Sicherheit für das derzeit in der Entwicklung befindliche Trading Administrator Panel befassen. Wir werden untersuchen, wie MQL5 in eine neue Sicherheitsstrategie implementiert werden kann, indem die Telegram-API für die Zwei-Faktor-Authentifizierung (2FA) verwendet wird. Diese Diskussion wird wertvolle Einblicke in die Anwendung von MQL5 bei der Verstärkung von Sicherheitsmaßnahmen liefern. Darüber hinaus werden wir die Funktion MathRand untersuchen, wobei wir uns auf ihre Funktionalität konzentrieren werden und darauf, wie sie innerhalb unseres Sicherheitsrahmens effektiv genutzt werden kann. Lesen Sie weiter, um mehr zu erfahren!
Merkmalsauswahl und Dimensionenreduktion mit Hilfe von Hauptkomponenten Merkmalsauswahl und Dimensionenreduktion mit Hilfe von Hauptkomponenten
Der Artikel befasst sich mit der Implementierung eines modifizierten Algorithmus der „Forward Selection Component Analysis“, der sich auf die von Luca Puggini und Sean McLoone in „Forward Selection Component Analysis: Algorithms and Applications“ vorgestellte Forschung stützt.
Wie man ein interaktives MQL5 Dashboard/Panel mit Hilfe der Controls-Klasse erstellt (Teil 2): Reaktionsfähigkeit von Schaltflächen hinzufügen Wie man ein interaktives MQL5 Dashboard/Panel mit Hilfe der Controls-Klasse erstellt (Teil 2): Reaktionsfähigkeit von Schaltflächen hinzufügen
In diesem Artikel konzentrieren wir uns darauf, unser statisches MQL5-Dashboard-Panel in ein interaktives Tool zu verwandeln, indem wir die Reaktionsfähigkeit von Schaltflächen aktivieren. Wir untersuchen, wie die Funktionalität der GUI-Komponenten automatisiert werden kann, um sicherzustellen, dass sie angemessen auf Nutzerklicks reagieren. Am Ende des Artikels haben wir eine dynamische Schnittstelle eingerichtet, die das Engagement der Nutzer und die Handelserfahrung verbessert.