Among the many cloud services, cloud object storage has perhaps experienced
the most growth. It is commonly used for storing photographs, images,
documents, and audio and video files. Every day, people find new uses for
their favorite object store. Regardless of the purpose of the application
you are developing, understanding cloud object storage services is an
essential part of building a real-world, scalable solution.

Armed with the knowledge learned here, you can develop
great applications very quickly by utilizing IBM Object
Storage.

In this tutorial we show you how to develop a simple application using the
Object Storage service for Bluemix, an OpenStack Swift-based object store
service, and explain how the restful storage APIs can be used. The
application you develop lets users upload, download, and manage their
pictures and documents leveraging the Object Storage service for Bluemix.
You can also download the sample application and view the code. Armed with
the knowledge learned here, you can quickly develop great applications
using the Object Storage service.

What you need to build the sample application in this tutorial

 
  1. A Bluemix account
  2. Basic understanding of the Cloud Foundry
    command line interface
  3. Basic understanding of Node.js. The following documents can be
    helpful:

  4. Basic understanding of Object Storage service application terminology
    (optional)
  5. Basic understanding of the OpenStack Swift API (optional)

Step 1. Create a Node.js application

 
  1. Login to your Bluemix account.
  2. Click CREATE AN APP.
  3. Choose WEB application type.
  4. Select SDK for Node.js and click
    CONTINUE.
  5. Enter an application name that is unique within the Bluemix domain you
    have selected. In this example, we use awesome-store as the
    name of our application.

Step 2. Add a service instance of Object Storage for Bluemix

 
  1. Once the application is created, click the ADD A
    SERVICE
    button.
  2. Scroll down to the Data Management section and click the
    Object Storage icon.
  3. The Object Storage service comes with a fairly detailed Getting
    started with Object Storage
    document, which you can review by
    clicking the VIEW DOCS button. You can also click the
    TERMS button to review the service license
    agreement as well. As you probably noticed, this beta service is
    provided free.
  4. Click the CREATE button and RESTAGE
    your application. You have now created an application by using the
    Bluemix-provided starter Node.js template project, created an Object
    Storage service instance, and bound the instance to the newly-created
    application.
  5. Your application name, awesome-store, is displayed at the top
    of the browser and below the name is a link. To see what the
    application does, click on that link. A window similar to the figure
    below opens. Notice that your browser address area shows
    awesome-store.mybluemix.net. This URL is a combination of
    the application name and the domain that you selected. You can access
    your application from any browser using the URL.
  6. awesome-store.mybluemix.net sample application

  7. Click the Environment Variables link to examine
    VCAP_SERVICES. This is an important piece of information
    that your application needs to make calls to the Object Storage
    service, such as creating an account for the application user, and
    allowing users to upload and download documents. See the figure below
    for an example. The username and password
    were scrambled to increase security.
    Example of environment variables

    Notice that in the credentials section you find
    auth_uri, username, and
    password. These three fields are used to authenticate
    your application with the service, and are referenced as
    auth_uri, username, and password from now
    on. It is very important to know that this username
    and password pair is the credential for your app to
    authenticate with the service. They are not the same as your
    application’s username and password if
    your application supports multiple users.

Step 3. Get the startup code from Bluemix

 
  1. While viewing your awesome-store application on the Bluemix
    screen, click the Start Coding link on the left
    sidebar.
  2. Bluemix dashboard

  3. A few steps regarding the Bluemix application development process are
    on the right. If you have not yet set up the Cloud Foundry command
    line interface in your favorite environment, do it now by following
    the Setup step.
  4. Click Download Starter Code. The downloaded code is
    in a zipped file. When you unzip the file, you see the following
    folders and files structure: Files and folders structure

    Because the purpose of this tutorial is to demonstrate how
    to use the Object Storage service, we do not dive into the details
    of Node.js application programming. Instead we focus on three key
    points necessary for programming the Object Storage service.

    1. We examine how the Object Storage service leverages the
      OpenStack Swift object storage APIs for applications to
      manipulate various entities in its object store.
    2. We show that in order for an application to access Swift
      object storage, the application has to first get an access
      token.
    3. We show how applications then pass this access token in
      requests to manipulate folders and objects.
  5. Though there are many ways to accomplish the tasks set above, to make
    this simple, we developed a few URLs to complete the tasks in this
    Node.js application. These URLs are entered into youAmong the many cloud services, cloud object storage has perhaps experienced
    the most growth. It is commonly used for storing photographs, images,
    documents, and audio and video files. Every day, people find new uses for
    their favorite object store. Regardless of the purpose of the application
    you are developing, understanding cloud object storage services is an
    essential part of building a real-world, scalable solution.r browser as GET
    requests, so you do not need any special tools to test the code. Here
    is the list of the URLs with a brief description of each. Replace the
    variables preceded by a colon with a string of your choice. For
    example, /gettoken/:userid becomes
    /gettoken/tongli.

    • /gettoken/:userid – Retrieve an access token for
      the userid.
    • /listfolders/:userid – List all the folders for
      the userid.
    • /createfolder/:userid/:foldername – Create a
      folder named foldername for the
      userid.
    • /delfolder/:userid/:foldername – Delete a folder
      for the userid and the folder. This one is not implemented in
      the application, you can add the implementation as an
      exercise. The implementation is very similar to the
      deldoc operation.
    • /listdocs/:userid/:foldername – List all the
      documents for the userid and the folder.
    • /createdoc/:userid/:foldername/:docname – Create
      a document named docname for the userid under the
      foldername folder. You may notice that the GET
      request does not really send any content for the document. In
      this application, you just send a hardcoded string.
    • /getdoc/:userid/:foldername/:docname – Retrieve
      the document named docname under the
      userid in the foldername
      folder.
    • /deldoc/:userid/:foldername/:docname – Delete a
      document.
  6. In your views folder, create a Jade template file named layout.jade,
    copy and paste the following code as its content, then save the file.

    		doctype html
    		html
    		  include head
    		  body
    		    table(style="width:100%")
    		      tr
    		        td(style= "width:307px" )
    		          img(src="/images/newapp-icon.png")
    		        td
    		          block content
  7. In your views folder, create another Jade template file named
    results.jade, copy and paste the following code as its content, then
    save the file.

    		extends layout
    		block content
    		  div(id="results")
    		    h2
    		      pre
    		        !=JSON.stringify(body, null, 2)
  8. Open the app.js file and add the following lines after the
    var services line:

    		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: {});
    		});

    The
    new code uses results.jade as a template, passes a
    variable named body to the template, then renders the
    HTML.

  9. These new files and the changes in app.js have prepared
    us to do more. Even though we have not accomplished a whole lot to
    this point, you still can deploy this application and see your new
    code working. Use the cf push command to deploy the
    application onto Bluemix, then point your browser to http://awesome-store.mybluemix.net/gettoken/tong to see
    results similar to this:
    Results of deployed application

    If you see errors, double-check the two files and the
    changes made in the app.js file. Normally the browser
    will display helpful debugging information.

Step 4. Obtain an access token for a user of your
application

 
  1. The Object Storage service supports multiple user accounts per service
    instance. It allows you to easily develop an application that supports
    multiple users because is does the heavy lifting for you. To get an
    access token for a user of your application, send a request by using
    basic authentication to this endpoint:
    auth_uri/<app_userid>. In this example, the URL
    looks like this:

    Notice
    that the URL is not exactly the auth_uri you get from
    the VCAP_SERVICES variable. Rather, it is the
    concatenation of the auth_uri and a userid chosen by
    your application. Your application can support multiple users, and
    you can choose anything as a userid as long as these userids are
    unique across your application. Each userid should uniquely
    identify a user in your application. The basic authentication
    header should follow the standard basic authentication
    protocol.

  2. Since you are going to send HTTP requests in the application, you need
    to include a Node.js HTTP request library. Add the following line in
    the app.js file.

    		The existing code:
    		var express = require('express');
    		
    		The new code to be added after the above line:
    		var request = require('request');
  3. Add the following code in the app.js file to replace the lines added
    earlier in Step 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);
    		});

    In
    the above code, the function set_app_vars takes in
    the values from the variable VCAP_SERVICES and finds
    objectstorage settings for the service instance. It
    also gets the auth_uri, userid, and
    password, then creates a base64 string
    according to the basic authentication protocol and saves it for
    later use.

    The app.get('/gettoken/:userid')
    call sets up a request handler so that all GET requests targeting
    /gettoken/:userid are handled by this code block. In
    this code block, define a response handler and request option to
    get an access token for an endpoint provided by IBM Bluemix Object
    Storage. Once the request is sent, the response handler checks the
    response status code, creates a body variable, and
    passes it on to be rendered as an HTML page according the
    definition found in the results.jade file.

    Also
    notice that the token received is temporarily cached by this
    application for later use. If you are developing a real-world
    application using this service, the token should be cached so you
    do not have to send a request to the service to get an access
    token every time.

  4. Redeploy the application using the cf push command.
  5. Access the same URL you used before. You should see something similar
    to the following. The token was again scrambled for security reasons.

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

  6. The response displays a token and a URL. The token and the URL are the
    two pieces of information your application should keep for creating
    folders (containers) and documents (objects) in a cloud object storage
    service.
  7. When the GET request is sent the first time for a specific user, this
    request may return a 202 status code. This is because the first access
    to object storage will cause the object storage to provision a new
    account for that user, which may take five or ten minutes. If your
    request is not getting the token, you can wait a few minutes and try
    the same request again. Eventually you get a 200 status code for the
    request and the access token, and a URL in the response header. With
    these two pieces of information, you are ready to explore Object
    Storage using the OpenStack Swift API. If you are not familiar with
    the API, you can learn more at http://docs.openstack.org/api/openstack-object-storage/1.0/content/.

Step 5. Create folder for a user with the OpenStack Swift
API

 
  1. In the previous steps, you successfully retrieved an access token for
    the user tong. Now it is time to create a folder for
    tong. The API defined by OpenStack Swift to create a
    folder is a PUT request with the access token in the request header.
    The endpoint is simply the storage URL, which you received when the
    access token was obtained. So to create a folder simply use the access
    token and the storage URL received above to send a PUT request.

    	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. The above code defines a handler for requests coming against the
    endpoint /createfolder/:userid/:foldername. In your own
    application, you can define the URL any way you prefer, but you should
    have a way to get the folder name and the userid. For example, you can
    use session tracking for the userid. Or you can use a form post to get
    the folder name. There are many options available. In this
    application, simply use a parameter in the request path. Once a
    request is received it finds the user information in the cache,
    defines the response handler and request options, then sends the
    request.
  3. Add the above code to the app.js file and redeploy the application.
    When you redeploy the application, the cached user token is lost so
    you need to get the token again with the
    /gettoken/:userid request. Here are the two URLs to try
    things out.

  4. If everything goes well, you see something like this: results succeded message

Step 6. Upload a document for a user with the OpenStack Swift
API

 

In the previous steps, you successfully added functions to get an access
token and create a folder. In this section, add a few more lines of code
to upload a document to the already created folder named newfolder. The
OpenStack Swift upload object API is also a PUT request at the endpoint,
which is made up of the storage URL and the folder name. The access token
must be present in the request header.

Here is the code to upload a document:

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

The above code follows the same pattern as previous code blocks. It first
gets the cached access token for the userid in the request URL, then
defines a response handler and request options, then sends the request.
The only difference is that we added a string
"Some random data" as the content of the object that is
uploaded.

In your application you can provide a variety of ways for users to upload
documents. Since that is not what we are discussing in this tutorial, we
coded sample data for the document content. This makes the code very
simple and direct for demonstration purposes, but of course if the app is
used as is, every document would have the same content.

Conclusion

 

In this tutorial we demonstrated how to create a simple Node.js application
to use the Object Storage service for Bluemix. The application shows how
to obtain access tokens for a user, create a folder, and upload a
document. In the application code, you can also find code blocks to handle
requests such as list folders of a user, list documents in a folder,
delete a document, and other requests. Using what you have learned in this
tutorial, you can quickly and easily develop great applications using
Object Storage.


BLUEMIX SERVICE USED IN THIS TUTORIAL:Object Storage service has built-in support for provisioning independent
object stores and it creates an individual subaccount per object
store.

RELATED TOPIC:Node.js


2 comments on"Building a Cloud Storage Application"

Join The Discussion

Your email address will not be published. Required fields are marked *