
Connexusのリクエスト(第6回):HTTPリクエストとレスポンスの作成
はじめに
この記事は、進行中の連載記事の一部で、私たちは「Connexus」というライブラリを作成しています。最初の記事では、WebRequest関数の基本的な機能とそのパラメータを解説し、その使用例や関連する課題を示すサンプルコードを作成しました。前回の記事では、HTTPメソッドと、リクエストが正常に処理されたのか、またはクライアントやサーバー側でエラーが発生したことを示すサーバーのステータスコードについて説明しました。
Connexusライブラリ連載第6回目では、HTTPリクエストの構成要素全体に焦点を当て、リクエストを構成する各コンポーネントを取り上げます。そして、リクエスト全体を表現するクラスを作成し、これまでに作成したクラスを統合します。さらに、サーバーのレスポンスを処理するための同様のクラスを作成し、レスポンスデータやステータスコードを含む内容を管理します。
HTTP通信において、リクエストは複数のコンポーネントで構成されており、これらが組み合わさることで完全なリクエストが形成されます。これらのコンポーネントは、以前の記事でそれぞれ取り上げ、個別のクラスを作成しました。以下に各要素を振り返ります。
- URL:Web上でサーバーのアドレスを定義し、ドメイン、ポート、パスなどの小さな部分から構成されます。この部分は、第2回で、URLを適切にフォーマットするためのクラスを作成しました。
- ヘッダ:リクエストに付随して送信される追加データで、ボディやURLに含まれないリクエストの詳細情報を提供します。これについては、第3回で詳しく説明し、リクエストヘッダを整理するクラスを作成しました。
- ボディ:実際に送受信されるデータの部分。簡単に言えば、ボディにはサーバーに送信する、またはサーバーから受け取るデータが含まれます。第4回では、これをより詳しく説明し、さまざまな形式(プレーンテキスト、JSON、char[](バイナリ))でボディを保存するクラスを作成しました。
- HTTPメソッド:HTTPメソッドは、クライアントがサーバーに対して実行したいアクションを指定するために使用されます。これについては、第5回で詳しく取り上げました。
- タイムアウト:タイムアウトについては、これまでの記事で取り上げていませんが、簡単に説明すると、サーバーがレスポンスを返すまでの時間をミリ秒単位で設定するものです。リクエストがこの設定時間を超えて処理されると、タイムアウトエラーが発生します。この設定は、WebRequest関数が同期的に動作するため、サーバーの応答が遅すぎる場合に問題を避けるために役立ちます。つまり、リクエストが予想以上に長時間かかると、EA(エキスパートアドバイザー)がサーバーのレスポンスを待つ間に「停止」してしまうため、タイムアウトを設定してこの状況を防ぐことが重要です。タイムアウトの設定値は利用者のニーズに応じて調整できますが、ほとんどのサーバーでは5000ミリ秒(5秒)で十分なことが多いです。
これらのコンポーネントはそれぞれ、適切なHTTPリクエストを構築するために重要な役割を果たしますが、すべてが必須というわけではありません。必須要素はURLとHTTPメソッド(GET、POST、PUTなど)のみです。
ライブラリの進捗と、これまでに作成したクラスを把握するために、現在のライブラリのダイアグラムを見てみましょう。
HTTPメソッド、ステータスコード、クエリパラメータ付きURL、ヘッダ、ボディを処理するクラスはすでに用意されていることに注意してください。
ファサードデザインパターン
ライブラリの構築を続けるために、デザインパターンを実装します。デザインパターンに馴染みがない方は、Mohamed Abdelmaaboud氏の「Design Patterns in Software Development」と「MQL5」の連載を読むことをお勧めします。この記事の中で、著者はサンプルコードとともにいくつかのデザインパターンを解説しています。Connexusライブラリでは、プログラミングにおいて広く知られている「ファサード」デザインパターンを実装します。このパターンは、より複雑なサブシステムのセットに対して簡素化されたインターフェースを提供し、内部の複雑さを隠し、クライアントがより簡単な方法でシステムと対話できるようにします。
ライブラリのコンテキストで考えてみましょう。リクエストを作成するには、各リクエスト要素のインスタンスを作成し、それらを設定する必要があります。例えば、以下のように記述します。
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;
このアプローチはコードを乱雑にし、複数のインスタンスの作成を必要とし、多くの行を消費し、コードの可読性を低下させます。ヘッダ、ボディ、URLのような複数のオブジェクトを管理することが複雑になり、メンテナンスが困難になるためです。ここでファサードデザインパターンが登場します。コンセプトに戻ります。このパターンは、より複雑なサブシステムのセットに対して簡素化されたインターフェイスを提供し、内部の複雑さを隠して、クライアントがよりシンプルな方法でシステムと対話できるようにします。。
この文脈では、サブシステムは、CHttpBody、CHttpHeadersなどのリクエスト要素のクラスであり、それらのためにより直感的なインターフェイスを作成することが目標です。このパターンは、サブシステムにアクセスするための「ファサード」として機能するクラスやインターフェイスを導入することで問題を解決します。最終的な開発者は、この簡略化されたインターフェイスだけを操作します。
まとめると、ファサードアーキテクチャには以下のような利点があります。
- 簡素化されたインタラクション:開発者は、一連の複雑なクラスを直接扱う代わりに、内部の詳細を隠す簡素化されたインターフェイスを使うことができます。
- カップリングの縮小:クライアントは内部サブシステムと直接結合していないため、これらのサブシステムの変更はクライアントに影響を与えることなくおこなえます。
- メンテナンス性の向上:ファサードインターフェイスと内部サブシステムを明確に分離することで、内部の変更はファサードによって抽象化され、コードの保守と拡張が容易になります。
このデザインパターンは、ライブラリでどのように実装されるのでしょうか。これを実現するために、CHttpRequestというサブシステムを含む新しいクラスを作成します。ライブラリユーザーにとって、このクラスの使い方は次のようになるはずです。
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");
ココードがはるかにシンプルになり、読みやすくなったことに注目してください。これこそが、このデザインパターンの背後にあるアイデアなのです。ファサードパターンは、より複雑な一連のサブシステム(CHttpBody、CHttpHeaderなどのインスタンスを管理する)に対して簡素化されたインターフェイス(CHttpRequest)を提供し、内部の複雑さを隠して、クライアントがより単純な方法でシステムと対話できるようにします。
CHttpRequestクラスの作成
ファサードの概念を理解したところで、このアーキテクチャをCHttpRequestクラスに適用してみましょう。このクラスをcoreという新しいフォルダの中に作成します。ファイル名はHttpRequest.mqhとなり、最終的なパスはInclude/Connexus/Core/HttpRequest.mqhです。初期状態では、ファイルは次のようになります。//+------------------------------------------------------------------+ //| 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) { } //+------------------------------------------------------------------+
最後のファイルで作成したクラス(CURL、CHttpBody、CHttpHeader、CHttpMethod)をインポートしてみましょう。それぞれのインスタンスを作成し、コンパイラにポインタを手動で管理することを知らせるために「*」を追加します。さらに、リクエストのタイムアウト値を格納するint型の変数m_timeoutを追加します。
//+------------------------------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
次に、各インスタンスのポインタにアクセスするメソッドと、タイムアウト値を設定したり取得したりするメソッドを追加しましょう。
- CURL *Url(void) :URLへのポインタを返す
- CHttpBody *Body(void) :ボディへのポインタを返す
- CHttpHeader *Header(void) :ヘッダへのポインタを返す
- CHttpMethod *Method(void) :メソッドへのポインタを返す
- CHttpRequest *Timeout(int timeout) :タイムアウトを設定する
- int Timeout(void) :タイムアウトを取得する
これらのメソッドに加えて、いくつかの補助メソッドを追加します。
-
void Clear(void) :インスタンスからすべてのデータを削除する
-
string FormatString(void) :すべてのリクエストデータを含む文字列を生成する
フォーマットされたリクエストの例
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] } ---------------
以下はそのメソッドの実装です。
//+------------------------------------------------------------------+ //| 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---------------" ); } //+------------------------------------------------------------------+
こうして、HTTPリクエストを形成するオブジェクトにアクセスするためのファサードとして機能するこのクラスが完成しました。重要なのは、私がコードに手を加えた部分のみを追加していることです。すべてのファイルは添付記事の最後に掲載されています。
この新しいCHttpRequestクラスによって、更新されたライブラリ図は次のようになります。
要約すると、CHttpRequestはファサードとして機能し、HTTPリクエストの設定と送信のプロセスを簡素化します。内部的には、CHttpHeadersクラスがヘッダロジックを処理し、CHttpBodyがリクエストボディの構築を担当します。このライブラリを使用する開発者は、ヘッダやボディがどのように処理されるかという詳細について心配する必要はありません。単にCHttpRequestのメソッドを使って値を設定するだけで、あとはファサードクラスが処理してくれます。
CHttpResponseクラスの作成
同じ考え方に従って、サーバーのレスポンスデータを表現するための別のクラスを作成します。これは、CHttpRequestと似た構造になります。以下は、レスポンスを構成する要素です。
- ヘッダ:リクエストと同様に、レスポンスもヘッダを含み、リクエストに関するメタデータをクライアントに通知します。
- ボディ:サーバーのレスポンス本文が含まれます。ここでサーバーは、私たちが取得したいデータを送信します。これがメッセージの核心部分です。
- ステータスコード:連載第5回で詳しく説明したステータスコードを含みます。このコードは3桁の数字で、リクエストが正常に処理されたか、クライアントやサーバーに誤りがあったかを通知します。
- 期間:リクエストが完了するまでにかかった時間をミリ秒単位で格納します。
coreフォルダに新しいファイルHttpResponseを作成します。最終的なパスはInclude/Connexus/Core/HttpResponse.mqhになります。作成されたクラスは次のようになります。
//+------------------------------------------------------------------+ //| 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) { } //+------------------------------------------------------------------+
レスポンスの要素CHttpHeader、CHttpBody、CHttpStatusCodeをインポートします。その後、それぞれのクラスのインスタンスと、リクエストの継続時間を格納するulong型のprivate変数を作成します。最終的なコードは次のようになります。
//+------------------------------------------------------------------+ //| 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; } //+------------------------------------------------------------------+
では、このクラスに追加されるメソッドに移りましょう。まず、クラスの各インスタンスのポインタと、期間を設定および取得するメソッドを返すだけの最も単純なものから始めます。
- CHttpHeader *Header(void) :ヘッダへのポインタを返します。
- CHttpBody *Body(void) :ボディへのポインタを返します。
- CHttpStatusCodes *StatusCode(void) :ステータスコードへのポインタを返します。
- void Duration(ulong duration) :継続時間を設定します。
- ulong Duration(void) :継続時間を取得します。
このクラスにもCHttpRequestと同じヘルパーメソッドを作成します。
-
void Clear(void) :インスタンスからすべてのデータを削除します。
-
string FormatString(void) :すべてのレスポンスデータを含む文字列を生成します。
以下は、書式付き回答の例です。
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" } } ---------------
これらの関数を実装したコードを以下に示します。
//+------------------------------------------------------------------+ //| 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---------------" ); } //+------------------------------------------------------------------+
念のためお伝えしておきますが、ここでは記事が長くなりすぎないように、クラスの変更点のみを掲載しています。使用したコードはすべて記事の最後に添付してあります。
これでレスポンスクラスの説明は終了です。これらのクラスは比較的シンプルで、目的はただ一つ、リクエストやレスポンスの要素をまとめて管理することです。これにより、リクエストを一つのオブジェクトとして扱うことができ、HTTPリクエストやレスポンスの取り扱いが大幅に簡素化されます。この新しいCHttpResponseクラスを取り入れた後、更新された図は次のようになります。
使用例
簡単に、これらのクラスの使用例をいくつか挙げてみましょう。CHttpRequestから始めて、このクラスを使ってHTTPリクエストを構築します。
//--- 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");
ここでの大きな利点は、リクエストの作成、ヘッダーやボディの追加、HTTPメソッドの変更が簡単にできる点です。
レスポンスの場合、求められるのはその逆です。つまり、リクエストオブジェクトを簡単に作成するのではなく、レスポンスオブジェクトを簡単に読み取れることです。両者は似たように動作し、どちらも簡単に作成および読み取りができるようになります。Connexusを使用した開発者向け画面のイメージを掲載します。
レスポンスボディには、文字列、JSON、バイナリなど、さまざまな形式でアクセスできることに注意してください。ここでは、CHttpBodyクラスのポインタに直接アクセスし、そのクラスが持つすべてのメソッドにアクセスしています。レスポンスの各要素に対応するクラスを作成した際、このライブラリのこの部分にたどり着き、それぞれのクラスを実際に使うことを考えていました。
結論
この記事では、HTTPリクエストのすべてのコンポーネントをグループ化することで、コードの明確さ、再利用性、メンテナンス性を向上させるCHttpRequestオブジェクトの重要性について説明しました。また、複雑なコンポーネントとのやり取りを簡素化するために、ファサードデザインパターンを適用し、内部の複雑さを隠すことで、クリーンで効率的なインターフェイスを提供する方法も紹介しました。Connexusの文脈では、CHttpRequestクラスにファサードパターンを適用することで、完全なHTTPリクエストの作成が容易になり、開発者の作業が簡素化されます。同じフォーマットに基づいたCHttpResponseクラスを作成することで、HTTPレスポンスデータへのアクセスがより簡単になります。
次の記事では、トランスポート層について詳しく解説します。トランスポート層は、CHttpRequestオブジェクトを受け取ってデータをWebRequest関数に変換し、ライブラリの最終層であるWebRequest関数はレスポンスデータを処理して、開発者がレスポンスデータを使用できるようにCHttpResponse型のオブジェクトを返す必要があります。それでは、次回お会いしましょう。
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/16182





- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索