Connexusヘルパー(第5回):HTTPメソッドとステータスコード
はじめに
この記事は、Connexusと呼ばれるライブラリを構築する連載の続きです。最初の記事では、WebRequest関数の基本的な操作方法を理解し、それぞれのパラメータについて学んだうえで、この関数の使用例と、その際に直面する課題を示すサンプルコードを作成しました。前回の記事では、リクエストがどのように機能するのか、リクエストのボディとは何か、そしてサーバーにデータを送信する方法について理解しました。最終的には、ボディを含むリクエストをサポートする機能を開発しました。
Connexusライブラリの構築に関する第5回の記事では、HTTPプロトコルの重要な側面である「メソッド」と「ステータスコード」について取り上げます。各HTTP動詞がどのように機能し、ステータスコードをどのように扱うべきかを理解することは、クライアントとサーバー間で信頼性の高いやり取りを作成するために重要です。それでは、始めましょう。
HTTPメソッド
HTTPメソッドは、サーバーに実行を要求するアクションです。HTTPリクエストを送信する際、ページへのアクセスやデータの送信など、これらのメソッドを使用してサーバーと「通信」します。主なものは次の通りです。
- GET:これは、昔ながらの「それをください」です。ブラウザは、ページ、画像、ファイルなど、サーバー上の何かを表示するように要求します。ただ情報を取得するだけで、何も変更しません。レストランのメニューを頼んで、提供されている料理を確認するようなものです。
- POST:POSTは荷物を配達する人です。ここでは、データをサーバーに送信します。例えば、Webサイトで登録する際のフォームなどでよく使われます。手紙を送るようなもので、目的地に届いたらそこで何かがおこなわれる、例えばあなたが登録されるようなイメージです。
- PUT:PUTを使うと、「これを新しいバージョンに変更します」と言っているようなものです。既存のリソースを更新するために使われます。車のオイル交換に似ていて、車はそのままですが、新しいものが取り付けられます。
- DELETE:とてもシンプルです。「それを削除してください」というリクエストです。サーバーに何かを削除するように求めています。さようなら、もう二度と会わないでしょう。
- PATCH:PATCHはもう少し繊細です。リソースの一部だけを変更します。壊れたおもちゃの部品を修理するようなもので、すべてを変更するわけではなく、壊れた部分を調整するだけです。
- HEAD:GETのようなものですが、ボディはありません。ヘッダー情報だけが必要で、コンテンツは不要です。本のタイトルを読んで、ページを開かずに中身を確認するようなものです。
CONNECT、OPTIONS、TRACEなどの他のメソッドもありますが、開発者の日常的な業務ではほとんど使用されません。ここではその詳細については触れませんが、このライブラリの目標はすべてのHTTPメソッドをサポートすることです。すべてのHTTPメソッドについて詳しく理解したい場合は、完全なプロトコルドキュメントにアクセスしてください。ただし、GET、POST、DELETEなど、開発者の日常的な作業で最もよく使われるリクエストがあれば、ほとんどの問題に対応できます。
リクエストには1つのメソッドしか使用しないことを強調したいと思います。つまり、リクエストがGETとPOSTの両方のメソッドを同時に使うことはできません。
CHttpMethodクラスの作成
各HTTPメソッドの目的と使用タイミングを理解したので、次はコードに進みましょう。Connexusライブラリ内に、リクエストを実行するために使用されるHTTPメソッドを保存するクラスを実装します。このクラスは非常にシンプルなものですので、プログラミングの経験に関係なく、何が起こっているかほとんど理解できるはずです。このクラスの目的は、使用されるメソッドを保存することにありますが、クラスであるため、Connexusライブラリのエンドユーザーができるだけ使いやすくするために、いくつかの機能を追加します。
まず、「Constants」という新しいフォルダを作成し、その中に「CHttpMethod」という新しいファイルを作成します。最終的なパスは、/Constants/HttpMethod.mqhのようになります。この新しいファイル内に、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) { } //+------------------------------------------------------------------+
可能なすべてのHTTPメソッドを含めるには、HTTPリクエストの可能なすべてのメソッドを含む列挙型を作成しましょう。また、クラスにENUM_HTTP_METHOD型の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 }; //+------------------------------------------------------------------+
保存に使用する変数ができたので、メイン関数を使いやすくするために「=」演算子をオーバーロードするだけでなく、HTTPメソッドを定義および取得するための補助メソッドを作成しましょう。
- 代入演算子 (operator= ):「=」演算子を直接使用してHTTPメソッドを定義できます。
- SetMethod(ENUM_HTTP_METHOD)およびSetMethod(string):HTTPメソッドを列挙型または文字列で定義します。パラメータが文字列型の場合、StringToUpper()関数を使用して文字列を正しく形成します。
- GetMethod()およびGetMethodDescription():HTTPメソッドとそのテキストの説明を取得します。
- void operator=(ENUM_HTTP_METHOD method):オーバーロードされた操作です。簡単に言えば、「=」演算子を使用してHTTPメソッドを定義するために使用されます。この演算子の実際の例を以下に示します。
CHttpMethod method; method = HTTP_METHOD_POST;
- 検証関数(IsPost()、IsGet()など):メソッドの検証が容易になり、コードが読みやすく簡素化されます。これらの関数がどのように役立つかの例
CHttpMethod method; method.SetMethod("POST") if(method.GetMethod() == HTTP_METHOD_POST) { //--- Action } //--- Or if(method.IsPost()) { //--- Action }
この方法では明示的なメソッドの比較を回避します。
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
これで、使用されたHTTPメソッドを保存するクラスは完了です。将来的にコードを節約するための補助関数がいくつかあります。次の補助クラスに移りましょう。
ステータスコード
ステータスコードとは、簡単に言えば番号のことです。この番号は標準化されており、サーバーがリクエストを処理した後、クライアントに送信します。各コードは3桁で構成されており、最初の数字がそのステータスが属するカテゴリを示します(1xx、2xx、3xx、4xx、5xx)。このコードはリクエストの結果を簡単に伝えるもので、リクエストが正常に完了したのか、サーバー側でエラーが発生したのか、あるいはリクエストが誤って送信されたのかを表します。ステータスコードは100から599の範囲で変化し、5つのカテゴリに分けられます。コードがどのカテゴリに属するかを確認するには、その範囲を特定し、対応する値の表を参照します。
| ステータスコード範囲 | 詳細 |
|---|---|
| 100~199 | あまり一般的ではありません。この範囲の応答は「処理中です。お待ちください」のようなものです。サーバーがリクエストを処理中であるが、まだ完了していないことを示します。 |
| 200~299 | これが最も好ましい応答です。この範囲のコードは、すべてが正常に完了したことを意味します。最も有名なのは「200 OK」で、これは「すべて順調」というサインです。リクエストを送信すると、サーバーがそれに応答してくれる、シンプルな仕組みです。 |
| 300~399 | サーバーが「おっと、違う場所に来ています。こちらへどうぞ」と言っているようなものです。「301 Moved Permanently」は恒久的なリダイレクトを意味し、「302 Found」は一時的なリダイレクトを指します。たとえば「現在改装中ですが、今のところはこちらを利用してください」といった状況に似ています。 |
| 400~499 | この範囲は、ユーザーが原因となるエラーです。最も有名なのは「404 Not Found」で、探しているページが存在しない場合に表示されます。これは、指定された住所に到着したものの、建物が取り壊されているような状況を連想させます。 |
| 500~599 | 問題がサーバー側にある場合、この範囲に該当します。有名な「500 Internal Server Error」は、サーバーが「何か問題が発生しました」と伝えるものです。 |
ステータスコードは多岐にわたりますが、この記事が長くなりすぎないよう、すべてを取り上げることはしません。すべてのステータスコードについて詳しく知りたい場合は、HTTPプロトコルを説明した資料を参照してください。日常の開発作業では、特定のコードしか使用されず、その多くはWeb上でもあまり目にしません。以下に、最も一般的なコードを示します。
1xx:情報提供
- 100 Continue:サーバーがヘッダーを受信し、クライアントがリクエスト本体の送信を続行できることを示します。
- 101 Switching Protocols:クライアントがプロトコル変更を要求し、サーバーがこれを受け入れました。
2xx:Success
- 200 OK:リクエストは成功しました。
- 201 Created:リクエストが成功し、新しいリソースが作成されました。 -204 No Content:リクエストは成功しましたが、応答本文にコンテンツがありません。
3xx:リダイレクション
- 301 Moved Permanently:リソースが恒久的に新しいURLに移動されました。
- 302 Found:リソースが一時的に新しい URLに移動されました。
- 304 Not Modified:リソースは変更されていないため、クライアントはキャッシュを使用できます。
4xx:クライアントエラー
- 400 Bad Request:リクエストが無効または不正です。
- 401 Unauthorized:認証が必要で、アクセスが許可されていません。
- 403 Forbidden:サーバーがリクエストを理解したが、アクセスを拒否しました。
- 404 Not Found:リクエストされたリソースが見つかりませんでした。
- 405 Method Not Allowed:リクエストで使用されたHTTPメソッドが許可されていません。
5xx:サーバーエラー
- 500 Internal Server Error:サーバー側で汎用的なエラーが発生しました。
- 502 Bad Gateway:サーバーがリクエストの処理中に無効な応答を受信しました。
- 503 Service Unavailable:サーバーが過負荷やメンテナンス中で一時的に利用できません。
- 504 Gateway Timeout:サーバーが別のサーバーから時間内に応答を受信しませんでした。
ステータスカテゴリと一般的なコードを理解したところで、ライブラリであらゆるステータスコードをサポートできるようにしたいと考えています。そのために、サーバーから受信したステータスコードが有効であれば、それを処理できるクラスを作成します。
CHttpStatusCodeクラスの作成
考えられるすべてのステータスコードがわかったので、適切な実装をライブラリに追加しましょう。ここでの目標はシンプルです。受信したステータスコードを保存するクラスを作成することです。クラスには各ステータスを記述するためのサポートも含まれている必要があり、そのステータスがどのカテゴリに属しているかをすばやく識別できるようにする必要があります。
コードを見てみましょう。以前にCHttpMethodクラス用に作成した同じフォルダ内に、HttpStatusCode.mqhという新しいファイルを作成します。最終的に、完全なパスは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) { } //+------------------------------------------------------------------+
考えられるすべてのステータスコードを格納するために、考えられるすべての値を持つ列挙型を作成します。列挙型の名前はENUM_HTTP_STATUSになり、列挙型の値はそれぞれのステータスコードになります。
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 };
各ステータスのカテゴリを分けるコメントをいくつか追加したことに注意してください。列挙型の最初の値をご覧ください。これらの値は「カスタムステータスコード」として追加されており、ライブラリによって自動的に生成されます。
- HTTP_STATUS_URL_NOT_ALLOWED:URLは端末の許可されたURLのリストに追加されませんでした
- HTTP_STATUS_URL_NOT_DEFINED:リクエストでURLが定義されていません
- HTTP_STATUS_METHOD_NOT_DEFINED:リクエストに対して有効なメソッドが定義されていません
WebRequest関数が呼び出されて-1を返す場合、MQL5ドキュメントに記載されているように、URLが端末に追加されていないことを意味するため、ライブラリは自動的にHTTP_STATUS_URL_NOT_ALLOWEDを返す必要があります。同様のロジックが他のカスタムコードにも適用されますが、現時点ではこれには焦点を当てません。
クラスの開発を続けましょう。このクラスはCHttpMethodに似たものになりますが、ENUM_HTTP_STATUS型のm_statusという新しいprivate変数を追加し、この変数の値を設定および取得するための補助メソッドもいくつか追加します。
- operator=(int)およびoperator=(ENUM_HTTP_STATUS):「=」演算子を使用して整数または列挙値を受け取り、m_statusの値を設定します。
- Set(ENUM_HTTP_STATUS):列挙値を使用してステータスコードを設定します。
- Get()およびGetMessage():現在のステータスコード、または保存されているコードに対応するメッセージのみを返します。
以下はこれらのメソッドを実装したコードです。
//+------------------------------------------------------------------+ //| 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"; } } //+------------------------------------------------------------------+
クラスに格納されているステータスコードが特定のカテゴリに属しているかどうかを確認する補助メソッドをいくつか追加しましょう。
- bool IsInformational(void):情報範囲(100~199)
- bool IsSuccess(void):成功範囲(200~299)
- bool IsRedirection(void):リダイレクト範囲(300~399)
- bool IsClientError(void):クライアントエラー範囲(400~499)
- bool IsServerError(void):サーバーエラー範囲(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); } //+------------------------------------------------------------------+
結論
ライブラリの進捗状況をより効果的に視覚化するには、以下の図に従ってください。

各HTTP要素を個別に処理する補助クラスはすべて準備が整っています。CJsonクラスを使用するCQueryParam、CHttpHeader、CHttpBodyクラスがありますが、これらの間には継承関係はありません。本記事で作成したクラスはまだ他のクラスと接続されておらず、次回の記事でHTTPリクエストとレスポンスを作成してすべてを接続する予定です。
この記事では、クライアントとサーバー間のWeb通信において非常に重要な2つの要素であるHTTPメソッドとステータスコードについて解説しました。各メソッドの役割を理解することで、リクエストをより正確に制御できるようになり、サーバーに対して実行したいアクションを明確に伝えることができます。これにより、通信の効率が向上します。各メソッドはそれぞれ特定の役割を果たしており、適切に使用することで、クライアントとサーバー間のAPI通信がより明確になり、予期せぬトラブルを避けられます。
また、リクエストに対するサーバーの応答であるステータスコードについても取り上げました。ステータスコードは、単純な「すべて正常」(200 OK)から、クライアント側のエラー(4xx)やサーバー側のエラー(5xx)まで多岐にわたります。これらのコードを適切に扱う能力は貴重なスキルであり、エラーは必ずしも終わりを意味するわけではなく、調整や再試行の機会を与えてくれる場合が多いからです。
Connexusライブラリの構築を進める中で、これらの要素を個別に処理する方法を学びました。この知識により、ライブラリはより堅牢で、HTTP通信の細かなニュアンスにも対応できるようになりました。今後、メソッドとステータスコードを管理するクラスは、開発者がAPIとやり取りする際に、より高いレベルの制御とセキュリティを提供できるようになるでしょう。
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/16136
警告: これらの資料についてのすべての権利はMetaQuotes Ltd.が保有しています。これらの資料の全部または一部の複製や再プリントは禁じられています。
この記事はサイトのユーザーによって執筆されたものであり、著者の個人的な見解を反映しています。MetaQuotes Ltdは、提示された情報の正確性や、記載されているソリューション、戦略、または推奨事項の使用によって生じたいかなる結果についても責任を負いません。
Candlestick Trend Constraintモデルの構築(第9回):マルチ戦略エキスパートアドバイザー(II)
プライスアクション分析ツールキットの開発(第1回):チャートプロジェクター
MQL5で取引管理者パネルを作成する(第5回):2要素認証(2FA)
MQL5とPythonで自己最適化エキスパートアドバイザーを構築する(第6回): Deep Double Descentの活用
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索