目次


クラウド・ストレージ・アプリケーションを作成する

Bluemix の Object Storage サービスを利用して単純な Node.js アプリケーションを作成する

Comments

数多くのクラウド・サービスの中で最も大きな成長を遂げたのは、おそらくクラウド・オブジェクト・ストレージでしょう。クラウド・オブジェクト・ストレージは、写真、画像、文書、そして音声ファイルや動画ファイルを保管するために使用するのが一般的です。人々は日々、お気に入りのオブジェクト・ストアの新しい利用方法を見つけています。作成しているアプリケーションの目的が何であれ、クラウド・オブジェクト・ストレージ・サービスについて理解することは、実際のスケーラブルなソリューションを作成する上で不可欠です。

このチュートリアルで学んだ知識を活かせば、IBM の Object Storage サービスを利用して瞬く間に素晴らしいアプリケーションを作成することができます。

このチュートリアルでは、OpenStack Swift ベースのオブジェクト・ストア・サービスである、Bluemix の Object Storage サービスを利用して単純なアプリケーションを作成する方法を紹介するとともに、RESTful なストレージ API の利用法を説明します。このチュートリアルで Bluemix の Object Storage サービスを利用して作成するのは、ユーザーが写真と文書をアップロード、ダウンロード、そして管理することができるアプリケーションです。このサンプル・アプリケーションをダウンロードして、コードを表示することもできます。このチュートリアルで学んだ知識を活かせば、IBM の Object Storage サービスを利用して瞬く間に素晴らしいアプリケーションを作成することができます。

このチュートリアルのサンプル・アプリケーションを作成するために必要なもの

  1. A Bluemix アカウント
  2. Cloud Foundry コマンド・ライン・インターフェースの基礎知識
  3. Node.js の基礎知識。以下のドキュメントが参考になります。
  4. Object Storage サービスを利用したアプリケーションに関する用語の基礎知識 (オプション)
  5. Object Storage Swift API の基礎知識 (オプション)

ステップ 1. Node.js アプリケーションを作成する

  1. Bluemix アカウントにログインします。
  2. 「CREATE AN APP (アプリの作成)」をクリックします。
  3. アプリケーションのタイプとして「WEB」を選択します。
  4. 「SDK for Node.js」を選択して「CONTINUE (続行)」をクリックします。
  5. 選択した Bluemix ドメイン内で一意となるアプリケーション名を入力します。この例では、アプリケーションに「awesome-store」という名前を付けます。

ステップ 2. Bluemix の Object Storage サービスのインスタンスを追加する

  1. アプリケーションが作成されたら、概要ページで 「ADD A SERVICE OR API (サービスまたは API の追加)」ボタンをクリックします。
  2. 「Data Management (データ管理)」セクションまでスクロールダウンして、「Object Storage」アイコンをクリックします。
  3. Object Storage サービスには、「Getting started with Object Storage」という非常に詳細な資料が用意されています。「VIEW DOCS (資料の表示)」ボタンをクリックすると、この資料に目を通すことができます。また、「TERMS (ご利用条件)」ボタンをクリックすることで、サービスの使用条件を概観することもできます。おそらくお気づきのことと思いますが、このベータ版サービスは無償で提供されています。
  4. 「CREATE (作成)」ボタンをクリックし、アプリケーションの「RESTAGE (再ステージ)」をクリックしてアプリケーションを再ステージングします。ここまでの時点で、Bluemix に用意されている Node.js スターター・テンプレートを利用してアプリケーションを作成しました。また、Object Storage サービス・インスタンスを作成し、新しく作成したアプリケーションにそのインスタンスをバインドする作業が完了しました。
  5. ブラウザー上部にはアプリケーション名 (awesome-store) が表示され、その名前の下にはリンクがあります。このアプリケーションが実行する内容を確認するには、そのリンクをクリックします。すると、以下の図に示すようなウィンドウが開きます。ブラウザーのアドレス領域に awesome-store.mybluemix.net と示されていることに注目してください。この URL は、アプリケーション名と、選択したドメインを結合したものです。この URL を使用して、任意のブラウザーからアプリケーションにアクセスすることができます。awesome-store.mybluemix.net サンプル・アプリケーション
    awesome-store.mybluemix.net サンプル・アプリケーション
  6. アプリケーションの概要ページから「Environment Variables (環境変数)」リンクをクリックして、VCAP_SERVICES を確認します。ここに含まれている情報は、アプリケーションがアプリケーション・ユーザーのアカウントを作成したり、ユーザーに文書のアップロードおよびダウンロードを許可したりするなどのために Object Storage サービスを呼び出す際に必要となる重要な情報です。以下の図に一例を示します。ご覧のとおり、セキュリティーを強化するために usernamepassword にはスクランブルがかけられています。環境変数の例のスクリーンショット
    環境変数の例のスクリーンショット

    credentials セクションに示されている、auth_uriusername、および password に注目してください。この 3 つのフィールドは、アプリケーションをサービスに対して認証するために使用されます (以降、これらをそれぞれ auth_uriusernamepassword と呼びます)。非常に重要な点として、この username と password のペアが、アプリケーションをサービスに対して認証する際の資格情報です。アプリケーションが複数のユーザーをサポートする場合は、アプリケーションの usernamepassword は現在示されているものとは異なります。

ステップ 3. Bluemix からスターター・コードを取得する

  1. awesome-store アプリケーションが Bluemix 画面に表示されているときに左のサイドバーに表示される「Start Coding (コーディングの開始)」をクリックします。Bluemix ダッシュボードで「Start Coding (コーディングの開始)」をクリックすると表示される画面のスクリーンショット
    Bluemix ダッシュボードで「Start Coding (コーディングの開始)」をクリックすると表示される画面のスクリーンショット
  2. 右側に、Bluemix アプリケーションの作成プロセスに関するいくつかのステップが表示されます。お気に入りの環境に Cloud Foundry コマンド・ライン・インターフェースをまだセットアップしていない場合は、この時点で「Setup (セットアップ)」ステップに従ってセットアップします。
  3. 「Download Starter Code (スターター・コードのダウンロード)」をクリックします。ダウンロードされるコードは zip 形式のファイルに含まれています。ダウンロードされたファイルを解凍すると、フォルダーおよびファイルが以下の構造で抽出されます。ファイルおよびフォルダーの構造のスクリーンショット
    ファイルおよびフォルダーの構造のスクリーンショット

    このチュートリアルの目的は Object Storage サービスを利用する方法をデモンストレーションすることなので、Node.js アプリケーション・プログラムの詳細にまでは立ち入りません。代わりに、Object Storage サービスをプログラミングする上で必要となる以下の 3 つのキー・ポイントに焦点を当てます。

    1. Object Storage サービスがアプリケーション用の OpenStack Swift オブジェクト・ストレージ API を利用して、オブジェクト・ストア内の各種エンティティーを操作できるようにする方法を検討します。
    2. アプリケーションが Swift オブジェクト・ストレージにアクセスするには、最初にアクセス・トークンを取得しなければならないことを示します。
    3. アプリケーションがフォルダーとオブジェクトを操作するために、取得したアクセス・トークンをリクエストに含めて渡す方法を紹介します。
  4. 上記の一連の作業を行うにはさまざまな方法がありますが、これらの作業を簡単なものにするために、このNode.js アプリケーションではこれらの作業を行うための URL をいくつか作成しました。これらの URL は、GET リクエストとしてブラウザーに入力するので、コードをテストするための特殊なツールは必要ありません。以下に、これらの URL のリストと、それぞれの URL についての簡単な説明を記載します。コロンで始まる変数は、自分で選択したストリングに置き換えてください。例えば、/gettoken/:userid/gettoken/tongli になるといった具合です。
    • /gettoken/:useriduserid 変数で指定されたユーザーのアクセス・トークンを取得します。
    • /listfolders/:useriduserid 変数で指定されたユーザー用のすべてのフォルダーを一覧表示します。
    • /createfolder/:userid/:foldernameuserid 変数で指定されたユーザー用のフォルダーを foldername 変数で指定された名前で作成します。
    • /delfolder/:userid/:foldername ― userid 変数で指定されたユーザー用の foldername 変数で指定されたフォルダーを削除します。この URL はアプリケーションに実装されていないので、皆さんが演習として実装を追加することができます。この実装は、deldoc 操作によく似ています。
    • /listdocs/:userid/:foldername ― userid 変数で指定されたユーザー用の foldername 変数で指定されたフォルダー内のすべての文書を一覧表示します。
    • /createdoc/:userid/:foldername/:docname ― userid 変数で指定されたユーザー用の foldername 変数で指定されたフォルダーに docname 変数で指定された名前の文書を作成します。お気づきかもしれませんが、GET リクエストは、実際には文書のコンテンツを送信することはありません。このアプリケーションでは、ハードコーディングしたストリングを送信するだけです。
    • /getdoc/:userid/:foldername/:docname ― userid 変数で指定されたユーザー用の foldername 変数で指定されたフォルダー内にある docname 変数で指定された名前の文書を取得します。
    • /deldoc/:userid/:foldername/:docname ― userid 変数で指定されたユーザー用の foldername 変数で指定されたフォルダー内にある docname 変数で指定された名前の文書を削除します。
  5. views フォルダー内に、layout.jade という名前の Jade テンプレート・ファイルを作成し、そのファイルの中身として以下のコードをコピー・アンド・ペーストしてから、ファイルを保存します。
    		doctype html
    		html
    		  include head
    		  body
    		    table(style="width:100%")
    		      tr
    		        td(style= "width:307px" )
    		          img(src="/images/newapp-icon.png")
    		        td
    		          block content
  6. views フォルダー内に、results.jade という名前の別の Jade テンプレート・ファイルを作成し、そのファイルの中身として以下のコードをコピー・アンド・ペーストしてから、ファイルを保存します。
    		extends layout
    		block content
    		  div(id="results")
    		    h2
    		      pre
    		        !=JSON.stringify(body, null, 2)
  7. app.js ファイルを開いて、var services/ 行の後に、以下の app.get 以降の 3 行を追加します。
    		The existing code:
    
    		var services = JSON.parse(process.env.VCAP_SERVICES || "{}");
    		
    		The new code to be added after the above line:
    		
    		app.get('/gettoken/:userid', function(req, res){
    			res.render('results', {body: {});
    		});

    この新しいコードは、results.jade をテンプレートとして使用し、body という名前の変数をテンプレートに渡してから、HTML をレンダリングします。

  8. 上記で作成した新規ファイルと app.js 内の変更により、さらに作業を進める準備が整いました。ここまでの時点ですべての作業を終えたわけではありませんが、このアプリケーションをデプロイして、新しいコードが機能することを確かめられます。cf push コマンドでアプリケーションを Bluemix にデプロイした後、ブラウザーで http://awesome-store.mybluemix.net/gettoken/tong にアクセスして、アプリケーションが以下のように表示されることを確認してください。
    デプロイされたアプリケーションの結果のスクリーンショット
    デプロイされたアプリケーションの結果のスクリーンショット

    エラーが表示された場合は、作成した 2 つのファイルと app.js ファイルで行った変更をダブルチェックしてください。通常は、デバッグに役立つ情報がブラウザーに表示されます。

ステップ 4. アプリケーションのユーザーのアクセス・トークンを取得する

  1. Object Storage サービスは、1 つのサービス・インスタンスに対して、複数のユーザー・アカウントをサポートします。面倒な作業は Object Storage サービスが代わって引き受けてくれるため、複数のユーザーをサポートするアプリケーションを簡単に作成することができます。アプリケーションのユーザーのアクセス・トークンを取得するには、基本認証を使用して、リクエストを auth_uri/<app_userid> エンドポイントに送信します。URL は、この例では以下のようになります。
    https://swift.ng.bluemix.net/auth/e40bf8f2-c3c6-4e51-8cde-476e30574637/fe07a633-61b3-4797-9a4d-c36daee7335b/tong

    URL が VCAP_SERVICES 変数から取得した auth_uri のとおりになっていないことに注意してください。この URL は、 auth_uri と、アプリケーションで選択された userid が連結されたものです。このアプリケーションでは複数のユーザーをサポートすることが可能であり、userid として任意のストリングを選択することができますが、その userid はアプリケーション全体で一意でなければなりません。各 userid によって、アプリケーションのユーザーが一意に識別されるようでなければならないからです。また、基本認証ヘッダーは、標準の基本認証プロトコルに従っている必要があります。

  2. ここではアプリケーションで HTTPリクエストを送信しようとしているので、Node.js HTTP リクエスト・ライブラリーを組み込む必要があります。それには、app.js ファイルに以下の行を追加します。
    		The existing code:
    		var express = require('express');
    		
    		The new code to be added after the above line:
    		var request = require('request');
  3. app.js ファイルに以下の行を追加して、ステップ 3.7 で追加した行を置き換えます。
    var cache = {};
    		var auth = null;
    		
    		var set_app_vars = function() {
    			var credentials = services['objectstorage'][0]['credentials'];
    			auth = {"auth_uri": credentials['auth_uri'],
    				 "userid" : credentials['username'],
    				 "password" : credentials['password'],
    			};
    			auth["secret"] = "Basic " +
    				Buffer(auth.userid + ":" + auth.password).toString("base64");
    		};
    		
    		app.get('/gettoken/:userid', function(req, res){
    			if (!auth) { set_app_vars(); }
    			var res_handler = function(error, response, res_body) {
    				var body = {};
    				if (!error && response.statusCode == 200) {
    					body = {"userid": req.params.userid,
    						 "token": response.headers['x-auth-token'],
    						 "url": response.headers['x-storage-url']};
    					cache[req.params.userid] = body;
    				}
    				else {
    					body = {"token": error, "url": ""};
    				};
    				res.render('results', {"body": body});
    			};
    			var req_options = {
    			    	url: auth.auth_uri + '/' + req.params.userid,
    				headers: {'accept': 'application/json',
    			   	          'Authorization': auth.secret},
    				timeout: 100000,
    				method: 'GET'
    			};
    			request(req_options, res_handler);
    		});

    上記のコードでは、set_app_vars 関数が VCAP_SERVICES 変数から値を取り込んで、サービス・インスタンスの設定値 objectstorage を見つけます。また、auth_uriuseridpassword を取得してから、基本認証プロトコルに従って base64 ストリングを作成し、そのストリングを後で使用できるように保存します。

    app.get('/gettoken/:userid') 呼び出しでリクエスト・ハンドラーをセットアップし、/gettoken/:userid をターゲットとするすべての GET リクエストがこのコード・ブロックで処理されるようにします。このコード・ブロックで、IBM Bluemix の Object Storage サービスが提供するエンドポイントのアクセス・トークンを取得するためのレスポンス・ハンドラーとリクエスト・オプションを定義します。リクエストが送信されると、レスポンス・ハンドラーがレスポンスのステータス・コードをチェックし、body 変数を作成して、その変数を results.jade ファイルでの定義に従って HTML ページとしてレンダリングされるように渡します。

    このアプリケーションでは、受信したトークンは、後で使用できるように一時的にキャッシュに入れられることにも注意してください。このサービスを利用して実際のアプリケーションを作成する場合、毎回リクエストをサービスに送信してアクセス・トークンを取得しなくても済むように、トークンをキャッシュに入れてください。

  4. cf push コマンドを使用してアプリケーションを再デプロイします。
  5. 前に使用した URL に再びアクセスします。すると、以下のような出力が表示されるはずです。ここでも、セキュリティー上の理由からトークンにはスクランブルがかけられています。

    http://awesome-store.mybluemix.net/gettoken/tong

  6. レスポンスには、トークンと URL が表示されます。このトークンと URL は、アプリケーションがクラウド・オブジェクト・ストレージ・サービスの中でフォルダー (コンテナー) と文書 (オブジェクト) を作成するために保持しておかなければならない 2 つの情報です。
  7. 特定のユーザーに対して初めて GET リクエストが送信されると、そのリクエストによって 202 ステータス・コードが返される場合があります。これは、オブジェクト・ストレージへの最初のアクセスでは、オブジェクト・ストレージがそのユーザーの新規アカウントをプロビジョニングするのに 5 分から 10 分かかるためです。リクエストによってトークンが返されなければ、数分待ってから、同じリクエストを再度送信してください。最終的には、リクエストに対する 200 ステータス・コードとアクセス・トークン、そしてレスポンス・ヘッダーに含まれた URL が取得されるはずです。トークンと URL の 2 つの情報を入手した後は、OpenStack Swift API を使用して Object Storage を探ることができます。この API に馴染みがない場合は、http://docs.openstack.org/api/openstack-object-storage/1.0/content/ で詳細を学ぶことができます。

ステップ 5. OpenStack Swift API を使用してユーザー用のフォルダーを作成する

  1. これまでのステップで、ユーザー tong のアクセス・トークンを取得することに成功しました。今度は、tong 用のフォルダーを作成します。OpenStack Swift によってフォルダーを作成するために定義されている API は、リクエスト・ヘッダーにアクセス・トークンを設定した PUT リクエストです。エンドポイントは、アクセス・トークンを取得したときに受信した、単なるストレージ URL なので、アクセス・トークンと先ほど受信した URL を使用して PUT リクエストを送信するだけで、フォルダーを作成することができます。
    	app.get('/createfolder/:userid/:foldername', function(req, res){
    		var user_info = cache[req.params.userid];
    		var res_handler = function(error, response, body) {
    			if (!error && (response.statusCode == 201 ||
    					 response.statusCode == 204)) {
    				res.render('results', {'body': {result: 'Succeeded!'}});
    			}
    			else {
    				res.render('results', {'body': {result: 'Failed!'}});
    			}
    		};
    		var req_options = {
    			url: user_info['url'] + "/" + req.params.foldername,
    			headers: {'accept': 'application/json',
    			  	   'X-Auth-Token': user_info['token']},
    			timeout: 100000,
    			method: 'PUT'
    		};
    		request(req_options, res_handler);
    	});
  2. 上記のコードでは、エンドポイント /createfolder/:userid/:foldername に対して送信されるリクエストのハンドラーを定義しています。皆さん独自のアプリケーションでは、任意の方法で URL を定義することができますが、フォルダー名とユーザー ID を取得する手段が必要です。それには、例えばユーザー ID のセッション・トラッキングを使用したり、フォームの POST 送信を使用してフォルダー名を取得したりするなど、使用できる選択肢は数多くあります。このアプリケーションでは単純に、リクエスト・パスのパラメーターを使用します。アプリケーションはリクエストを受信すると、キャッシュ内でユーザー情報を検索し、その情報を基にレスポンス・ハンドラーとリクエスト・オプションを定義して、リクエストを送信します。
  3. 上記のコードを app.js ファイルに追加して、アプリケーションを再デプロイします。アプリケーションを再デプロイすると、キャッシュに入れられたユーザー・トークンは失われるため、/gettoken/:userid リクエストでトークンを再び取得する必要があります。以下の 2 つの URL で試してみてください。
  4. すべてが問題なければ、以下のような結果が表示されます。結果は成功であることを伝えるメッセージのスクリーンショット
    結果は成功であることを伝えるメッセージのスクリーンショット

ステップ 6. OpenStack Swift API を使用してユーザー用の文書をアップロードする

これまでのステップで、アクセス・トークンを取得するための関数と、フォルダーを作成するための関数を追加することができました。このセクションでは、作成済みの「newfolder」という名前のフォルダーに文書をアップロードするために、さらに数行のコードを追加します。OpenStack Swift のオブジェクトをアップロードするための API も、同じくエンドポイントに対する PUT リクエストです。このエンドポイントは、ストレージ URL とフォルダー名からなります。リクエスト・ヘッダーにはアクセス・トークンが含まれている必要があります。

文書をアップロードするためのコードは以下のとおりです。

		app.get('/createdoc/:userid/:foldername/:docname', function(req, res){
		    var user_info = cache[req.params.userid];
		    var res_handler = function(error, response, body) {
			if (!error && response.statusCode == 201) {
			    res.render('results', {'body': {result: 'Succeeded!'}});
			}
			else {
			    res.render('results', {'body': {result: 'Failed!'}});
			}
		    };
		    var req_options = {
			url: user_info['url'] + "/" + req.params.foldername + "/" +
				req.params.docname,
			headers: {'accept': 'application/json',
				   'X-Auth-Token': user_info['token']},
			timeout: 100000,
			body: "Some random data",
			method: 'PUT'
		    };
		    request(req_options, res_handler);
		});

上記のコードは、前のコード・ブロックと同じパターンに従っています。つまり、最初にリクエスト URL のユーザー ID に対応するアクセス・トークンをキャッシュから取得し、次にレスポンス・ヘッダーとリクエスト・オプションを定義してから、リクエストを送信します。唯一の違いは、アップロードするオブジェクトのコンテンツとして、「Some random data」というストリングを追加しているという点です。

皆さんが作成するアプリケーションでは、さまざまな手段でユーザーが文書をアップロードできるようにすることが可能ですが、それについてはこのチュートリアルでは取り上げないので、文書のコンテンツ用のサンプル・データをコーディングしておきました。そのため、コードはデモンストレーションを目的とした非常に単純で直接的なものになっています。ただし当然のことながら、このアプリケーションをそのままの状態で使用すると、すべての文書が同じコンテンツになります。

まとめ

このチュートリアルでは、Bluemix の Object Storage サービスを利用する単純な Node.js アプリケーションを作成する方法をデモンストレーションしました。このサンプル・アプリケーションに、ユーザーのアクセス・トークンを取得する方法、フォルダーを作成する方法、そして文書をアップロードする方法が示されています。このアプリケーション・コードのなかには、ユーザーのフォルダーを一覧表示するリクエスト、フォルダー内の文書を一覧表示するリクエスト、文書を削除するリクエストをはじめとする各種リクエストを扱うためのコード・ブロックも見つかります。このチュートリアルで学んだことを活かせば、Object Storage サービスを利用して素晴らしいアプリケーションを迅速かつ容易に作成することができます。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Cloud computing, Information Management
ArticleID=1003371
ArticleTitle=クラウド・ストレージ・アプリケーションを作成する
publish-date=04232015