RPG開発者向けのWebの基本概念、パート2
前回の記事、「 RPG開発者向けのWebの基本概念 」の パート1 は、HTTPリクエストのコンポーネントを作成する方法についての入門編でした。お楽しみいただけたでしょうか。パート2は、その巨大なテーマの続編の1つに過ぎません。学ぶべきことは非常に多いからです。この記事内のリンクをクリックして、ご自身でいろいろと調べてみることもお勧めです。
JSON
Web APIエンドポイントは、HTTP POSTリクエストのボディ内のデータが、JSON(JavaScriptオブジェクト表記法: JavaScript Object Notationの略で、「ジェイソン」と発音)として構成されることを要求することがあります。JSONは、キーと値のデータのペアを含む、フォーマットされたテキスト(ストリング)です。JSONデータは、単一のレベルの場合(例1)や、ネストされている場合(JSON内にJSON)、および角括弧([ ])によって示される、配列が含まれる場合(例2)もあります。JSONは、XMLにほぼ取って代わりました。JSONの方が、サイズがよりコンパクトであり、人間にとって判読しやすいからです。また、JSONは、RPGのデータ構造にきちんとマッピングされます。
01 {
02 "userID":"Tom0121",
03 "hireDate":19900531,
04 "canSeePayroll":true
05 }
例1
01行:JSONストリングは左波括弧({)で始まります。このコードはすっきりしたフォーマットになっています。このコードは、改行やスペースのない1行のコードとしてすべてコーディングすることもできます。JSON <パーサー はどちらでも問題になりません。
{"userID":"Tom0121","hireDate":19900531,"canSeePayroll":true}
02行:キー名は二重引用符で囲みます。ストリング値も二重引用符で囲みます。それぞれのキーと値のペアでは、キーと値はコロンで区切られています。コンマが末尾にある場合は、さらにキーと値のペアが続くことを意味します。
03行:この値は数値なので、引用符で囲みません。
04行:この値はブール値なので、引用符で囲みません。
05行:JSONストリングは右波括弧(})で終わります。
このJSONストリングは、RPGの連結機能を使用するだけで簡単に構築することができます。
以下は、等価となるRPGのデータ構造です。
dcl-ds *n;
userID varchar(50) inz('Tom0121');
hireDate int(10) inz(19900531);
canSeePayroll ind inz(*On);
end-ds;
次のJSONの例には、値の配列が含まれています。
01 {
02 "company":"Kramer Inc",
03 "users":[
04 {"userID":"Tom0121", "hireDate":19900531, "canSeePayroll":true},
05 {"userID":"Bob5678", "hireDate":19920815, "canSeePayroll":false}
06 ]
07 }
例2
01行:JSONストリングの始まり。
02行:会社名は「Kramer Inc」です。
03行:このキーは値の配列を含んでいます。配列の始まりは左角括弧([)で示されています。
04行および05行:ここには配列要素が2つあり、コンマで区切られています。
06行:配列は右角括弧(])で終わります。
07行:JSONストリングの終わり。
エポック
今、何時ですか。単純な質問のように思えますが、答えはもちろん、「それぞれ状況によって異なる」ということになります。コンピューターでタイム ゾーン オフセットを手動で設定しようとすると、西半球における-12:00時間から、東半球における+14:00時間まで、38の異なるタイム ゾーンの選択肢が示されます(図1)。したがって、尋ね方としてより適切なのは、おそらく、「Whose time is it?(それはどこの地域の時刻ですか)」ということになるでしょう。
World Wide Webでは、HTTPリクエストのタイムスタンプの曖昧さを回避するために、GMT(グリニッジ標準時)として知られる共通の時刻基準が使用されることがあります。GMTは、タイム ゾーン オフセットが0であり、本初子午線または経度0度は 英国のグリニッジ を通っています(図2)。そして、GMTを表現するための共通のデータ形式がエポック、ということになります。
エポック (epoch)は、1970年1月1日(GMT)を起点とする経過秒数です。エポックは、10桁または13桁(暗黙の小数部3桁)の数値として表現されます。コンピューターはすべてタイム ゾーン オフセットで構成されているため、ローカル時刻をエポックに変換するのは簡単で、タイム ゾーン オフセットの秒数を差し引くだけです。
01 dcl-s wkEpochSecs uns(10);
02 exec sql values( 86400 *
03 (DAYS(CURRENT TIMESTAMP - CURRENT TIMEZONE) - DAYS('1970-01-01')) +
04 MIDNIGHT_SECONDS(CURRENT TIMESTAMP - CURRENT TIMEZONE) )
05 into :wkEpochSecs ;
01行: この符号なし整数値に、エポック値が格納されます。符号付きエポック整数値は、 2038年に最大値に到達します。
02行: 1日の秒数(24時間 x 60分 x 60秒)。
03行: 1970年1月1日(GMT)からの DAYS (日数)と1日の秒数を掛け合わせます。
ここでは、IBM iのタイム ゾーン オフセットが、ローカル時刻から差し引かれます。つまり、タイム ゾーン オフセットがマイナスである西半球(たとえば米国)では、実際には時間を加算することになります。
04行: MIDNIGHT_SECONDS は、今日の午前零時からの現在までの経過秒数を返すスカラー関数です(このケースではGMT)。この値は03行へ加算されます。
05行: 結果は10桁のエポック整数です。今日が2024年5月27日16:45:59 GMTである場合、エポック値は1716828359ということになります。
エポック値へ変換できたのは素晴らしいことですが、では、エポックはどのような時に必要とされるのでしょうか。エポックは、クライアント(ユーザーまたはマシン)がWebサーバー上のリソースに一時的なアクセスをリクエストしているときに、JWT(JSON Webトークン)の一部として含まれていることがよくあります。認証サーバーは、リクエストされたアクセスが、いつ始まり(今)、いつ終了する(数時間ないしは数分以内)かを知る必要があります。JTWについては、今後の記事で詳しく取り上げる予定です。ここでは、HTTPリクエストのボディで送信できるいくつかの単純なJSONを以下に示します。
01 {
02 "userID":"Tom0121",
03 "iat":1716828359,
04 "exp":1716828659,
05 }
01行: JSONストリングの始まり。
02行: アクセスをリクエストしているクライアント。
03行: 「iat」は「issued at(発行日時)」を意味し、このエポック値は、今、現在のGMT日時を意味します。
04行: 「exp」は有効期限を意味します。04行と03行の差は300秒なので、今から5分後が有効期限ということになります。
05行: JSONストリングの終わり。
メッセージ ダイジェスト
メッセージ ダイジェストは、データの同一性を検証するために、ストリングまたはファイルをより短い表現へ一方向に変換したデータです。既存のメッセージ ダイジェストが、現在計算された最新のメッセージ ダイジェストと比較されることがあります。ストリングまたはファイルのデータが1ビットでも変更されると、メッセージ ダイジェストも変更されます。
Db2にも、様々なファイル タイプ向けに非常によく似たメカニズムがあります。F-仕様書(DCL-F)が含まれているRPGプログラムがコンパイルされるときに、その現行レコード フォーマットIDは、プログラム オブジェクトに保存されます( DSPPGMREFで表示可能)。プログラムが、LVLCHK(*YES)として定義されているそのファイルを開こうとすると、現行レコード フォーマットIDと保存されている値が等しくない場合は、 CPF4131 レベル検査エラーが表示され、何かが変更されていることが警告されます。
メッセージ ダイジェストとして広く使用されているのは、ストリングまたはファイルを256ビット表現(32バイナリー バイト)に変換する SHA256 です。見やすくするために、非テキスト32バイトは、通常、判読しやすい64ニブル値へ変換されます。ここでは、QshellでいくつかのJSONをSHA256へ変換します。5250セッションで、コマンド ラインからSTRQSHを実行して、以下のechoコマンドをQShellへコピー/ペーストします(行番号「01」なしで)。
01 echo '{"userID":"Bob9876","canSeePayroll":false}' | openssl dgst -sha256
02 SHA2-256(stdin)= 2d409491eef33c4ae2ef154c0a361fb94d3cbfc160e692ed76770f3a4240d28e
01行: echoコマンドは、単一引用符内のストリングを画面に出力するだけです。
パイプ(|)文字は、画面出力が、その次のコマンドの入力になるようにリダイレクトします。このケースではopenssl dgst(メッセージ ダイジェスト)です。 Openssl は、Qshellで利用可能な高機能の暗号化ツールです。dgstのオプション、-sha256は、作成する特定のメッセージ ダイジェストのタイプです。
02行: これは、出力メッセージ ダイジェスト値(64文字長)です。メッセージ ダイジェストは、一意の値ではありません。ストリーム ファイルの正確なコピーを作成した場合は、両方のストリーム ファイルは、同じSHA256メッセージ ダイジェストを生成します。
では、payrollフラグをfalseからtrueへ変更したらどうなるか見てみましょう。以下のechoコマンドをQshellにコピー/ペーストします。メッセージ ダイジェストはまったく変わっており、したがって、そのデータが手を加えられていることが分かります。
echo '{"userID":"Bob9876","canSeePayroll":true}' | openssl dgst -sha256
SHA2-256(stdin)= e3f6e8290ec35b9b57aba409d9540d237572fb3a01628ea622e275aded294425
終わりに
パート1でも述べたことですが、重要なので繰り返します。HTTPリクエストがどのようにフォーマットされる必要があるかは、利用すべきWeb APIエンドポイントのスキーマ(ブループリント)によって決まります。たとえばPDFを送信する際に、そのPDFがbase64へ変換され、JSONでの値として組み込まれることをスキーマが求めている場合は、その要求に従う必要があります。
パート3をお楽しみに。base64についてもう一度取り上げてから、秘密鍵と公開鍵のペアを使用して非対称暗号化に取り組む予定です 。