1 /**
  2  * @fileOverview AWS Blob.
  3  */
  4 
  5 (function () {
  6   var util = require('util'),
  7     utils = require("../../../utils"),
  8     CloudError = require("../../../errors").CloudError,
  9     ReadStream = require("../../../stream").ReadStream,
 10     WriteStream = require("../../../stream").WriteStream,
 11     BaseBlob = require("../../../base/blob").Blob,
 12     AwsBlob;
 13 
 14   /**
 15    * Blob class.
 16    *
 17    * @param {base.Container} cont       Container object.
 18    * @param {Object}      attrs         Attributes.
 19    * @config {string}     name          Name.
 20    * @config {string}     created       Creation date.
 21    * @config {string}     lastModified  Last modified date.
 22    * @config {number}     size          Byte size of object.
 23    * @config {string}     etag          ETag.
 24    * @extends base.blob.Blob
 25    * @exports AwsBlob as provider.aws.blob.Blob
 26    * @constructor
 27    */
 28   AwsBlob = function () {
 29     BaseBlob.apply(this, arguments);
 30   };
 31 
 32   util.inherits(AwsBlob, BaseBlob);
 33 
 34   /**
 35    * @private
 36    */
 37   AwsBlob.prototype._errorFnRequest = function () {
 38     var conn = this.container.connection;
 39     return function (err, request, response) {
 40       var translated = conn._translateErrors(err, request, response);
 41       request.emit('error', translated || err);
 42     };
 43   };
 44 
 45   /**
 46    * @private
 47    */
 48   AwsBlob.prototype._errorFnStream = function () {
 49     var conn = this.container.connection;
 50     return function (err, stream, response) {
 51       var translated = conn._translateErrors(err, stream.request, response);
 52       stream.emit('error', translated || err);
 53     };
 54   };
 55 
 56   /**
 57    * Common request wrapper.
 58    *
 59    * @param {string} method     HTTP verb.
 60    * @param {Object} [options]  Request options.
 61    * @param {Object} [extra]    Extra Auth Request configs.
 62    * @private
 63    */
 64   AwsBlob.prototype._basicRequest = function (method, options, extra) {
 65     options = options || {};
 66     extra = extra || {};
 67     var self = this,
 68       auth = self.container.connection.authentication,
 69       meta = utils.extractMeta(options);
 70 
 71     if (!method) { throw new CloudError("Method required."); }
 72 
 73     return auth.createRequest(utils.extend(meta, {
 74       method: method,
 75       encoding: 'utf8',
 76       path: "/" + self.name,
 77       headers: utils.extend(options.headers, {
 78         'host': auth.authUrl(self.container.name)
 79       }),
 80       resultsFn: extra.resultsFn || function () {
 81         return {
 82           blob: self
 83         };
 84       },
 85       errorFn: extra.errorFn || self._errorFnRequest()
 86     }));
 87   };
 88 
 89   /**
 90    * @see base.blob.Blob#get
 91    */
 92   AwsBlob.prototype.get = function (options) {
 93     options = options || {};
 94     var self = this,
 95       conn = self.container.connection,
 96       auth = conn.authentication,
 97       meta = utils.extractMeta(options),
 98       encoding = options.encoding || null,
 99       stream;
100 
101     stream = new ReadStream(auth.createRequest(utils.extend(meta, {
102       encoding: encoding,
103       path: "/" + self.name,
104       headers: utils.extend(options.headers, {
105         'host': auth.authUrl(self.container.name)
106       })
107     })), {
108       errorFn: self._errorFnStream(),
109       endFn: function () {
110         return {
111           blob: self
112         };
113       }
114     });
115     return stream;
116   };
117 
118   /**
119    * @see base.blob.Blob#head
120    */
121   AwsBlob.prototype.head = function (options) {
122     return this._basicRequest("HEAD", options);
123   };
124 
125   /**
126    * @see base.blob.Blob#put
127    */
128   AwsBlob.prototype.put = function (options) {
129     options = options || {};
130     var self = this,
131       auth = self.container.connection.authentication,
132       meta = utils.extractMeta(options),
133       encoding = options.encoding || null;
134 
135     return new WriteStream(auth.createRequest(utils.extend(meta, {
136       method: "PUT",
137       encoding: encoding,
138       path: "/" + self.name,
139       headers: utils.extend(options.headers, {
140         'host': auth.authUrl(self.container.name)
141       })
142     })), {
143       errorFn: self._errorFnStream(),
144       endFn: function () {
145         return {
146           blob: self
147         };
148       }
149     });
150   };
151 
152   /**
153    * @see base.blob.Blob#del
154    */
155   AwsBlob.prototype.del = function (options) {
156     var self = this,
157       conn = self.container.connection,
158       notFound = false,
159       getResults;
160 
161     /** @private */
162     getResults = function () {
163       return {
164         blob: self,
165         notFound: notFound
166       };
167     };
168 
169     return this._basicRequest("DELETE", options, {
170       resultsFn: getResults,
171       errorFn: function (err, request, response) {
172         var translated = conn._translateErrors(err, request, response);
173         if (translated && translated.isNotFound()) {
174           // NotFound is OK.
175           notFound = true;
176           request.emit('end', getResults());
177         } else {
178           request.emit('error', translated || err);
179         }
180       }
181     });
182   };
183 
184   module.exports.Blob = AwsBlob;
185 }());
186