Permalink
Browse files

implements client

  • Loading branch information...
1 parent aba400a commit 70b97f40346b3401044762a316ffb941238a4049 Ian Hansen committed Jul 25, 2012
Showing with 211 additions and 63 deletions.
  1. +117 −21 lib/assembly.js
  2. +91 −40 lib/transloadit.js
  3. +3 −2 package.json
View
@@ -1,12 +1,28 @@
-function Assembly(transloadit) {
+var nop = function() {};
+
+function Assembly(transloadit, options) {
+ options = options || {};
+
this._transloadit = transloadit;
this._templateId = null;
this._steps = {};
this._fields = {};
this._files = {};
this._streams = {};
+ this._refreshCount = 0;
+ this._maxRefresh = options.maxRefresh || 20;
+ this._refreshDelay = options.refreshDelay || 250;
+
this._response = null;
+
+ // reponse handlers
+ this._update = nop;
+ this._success = nop;
+ this._error = nop;
+ this._complete = nop;
+
+ process.nextTick(this._run.bind(this));
}
Assembly.prototype.step = function(name, robot, params) {
@@ -31,42 +47,122 @@ Assembly.prototype.templateId = function(templateId) {
return this;
};
-// Assembly.prototype.file = function(name, path) {
-// if (arguments.length === 0) return this._files[name];
+Assembly.prototype.file = function(name, path, filename) {
+ if (arguments.length === 1) return this._files[name];
-// this._files[name] = path;
-// return this;
-// };
+ this._files[name] = {
+ path: path,
+ filename: filename
+ };
-// Assembly.prototype.stream = function(name, stream) {
-// if (arguments.length === 0) return this._streams[name];
+ return this;
+};
-// this._streams[name] = stream;
-// return this;
-// };
+Assembly.prototype.stream = function(name, filename, mimeType, stream) {
+ if (arguments.length === 1) return this._streams[name];
-Assembly.prototype.run = function(options) {
- this._transloadit._multipart({
- path: '/assemblies',
- params: {
- test: 'value'
- },
- streams: {}
- }, function handleMultipart(err, response) {
- console.log('multipart', arguments);
- });
+ this._streams[name] = {
+ filename: filename,
+ mimeType: mimeType,
+ stream: stream
+ };
+
+ return this;
};
Assembly.prototype.error = function(cb) {
this._error = cb;
+
+ return this;
+};
+
+Assembly.prototype.complete = function(cb) {
+ this._complete = cb;
+
+ return this;
};
Assembly.prototype.success = function(cb) {
this._success = cb;
+
+ return this;
};
Assembly.prototype.update = function(cb) {
this._update = cb;
+
+ return this;
+};
+
+Assembly.prototype._run = function() {
+ var params = {}
+ , options
+ ;
+
+ params.steps = this._steps;
+ if (this._fields) params.fields = this._fields;
+ if (this._templateId) params.template_id = this._templateId;
+
+ this._transloadit._multipart({
+ path: '/assemblies',
+ sign: true,
+ params: params,
+ streams: this._streams,
+ files: this._files
+ }, (function handleMultipart(err, response) {
+ if (err) return this._error(err, response);
+ return this._handleResponse(response);
+ }).bind(this));
+};
+
+Assembly.prototype._handleResponse = function(response) {
+ this._response = response;
+ if (response.error) {
+ this._error(response.error, response);
+ this._complete(response);
+ return;
+ }
+
+ if (response.ok && response.ok === 'ASSEMBLY_COMPLETED') {
+ this._success(response);
+ this._complete(response);
+ return;
+ }
+
+ switch (response.ok) {
+ // terminal status codes that are not error or success
+ case 'REQUEST_ABORTED':
+ case 'ASSEMBLY_CANCELED':
+ this._update(response);
+ this._complete(response);
+ break;
+
+ default:
+ this._update(response);
+ this._refresh();
+ }
+};
+
+Assembly.prototype._refresh = function() {
+ var assemblyUrl;
+
+ if (++this._refreshCount > this._maxRefresh) {
+ return this._error('MAX_REFRESH', this._response);
+ }
+
+ if (this._response && this._response.assembly_url) assemblyUrl = this._response.assembly_url;
+
+ if (!assemblyUrl) {
+ return this._error('NO_ASSEMBLY_URL', this._response);
+ }
+
+ setTimeout(
+ (function doRefresh() {
+ this._transloadit.getAssemblyStatus(assemblyUrl, (function handleGetAssemblyStatus(err, response) {
+ if (err) return this._error(err);
+ return this._handleResponse(response);
+ }).bind(this));
+ }).bind(this), this._refreshDelay);
};
module.exports = Assembly;
View
@@ -1,5 +1,6 @@
-var multiparter = require('multiparter')
- , http = require('http')
+var request = require('request')
+ , crypto = require('crypto')
+ , MultipartStream = require('multipart-form-stream')
, Assembly = require('./assembly')
, API_HOST = 'api2.transloadit.com'
, nop = function() {}
@@ -11,65 +12,115 @@ function Transloadit(options) {
this._secret = options.secret;
};
-/**
- * options - {
- * steps: {} - assembly steps
- * templateId: (optional) string template id
- * fields: {} (optional) variables to be used in the assembly
- * files: {} (optional) hash {name: filepath}
- * auth: {key: String, secret: String} - (optional) use transloadit constructor values by default
- * redirect_url: (optional) no redirect url by default
- * notify_url: (optional) no notify url by default
- * success: (optional) callback to trigger when the assembly completes successfully
- * error: (optional) callback to trigger on error
- * change: (optional) callback to trigger when the state of the assembly changes
- * }
- */
Transloadit.prototype.createAssembly = function(options) {
- if (!options) return new Assembly(this);
+ return new Assembly(this);
+};
+Transloadit.prototype.getAssemblyStatus = function(assemblyUrl, cb) {
+ request.get({
+ uri: assemblyUrl
+ }, function handleResponse(err, response) {
+ var body;
+
+ if (err) return cb(err);
- request({
- url: 'http://' + API_HOST + '/assemblies',
- method: 'POST',
- json: options.params || {},
- })
+ response = response || {};
+ response.body = response.body || '{}';
+
+ try {
+ body = JSON.parse(response.body);
+ return cb(null, body);
+ } catch (err) {
+ return cb(err);
+ }
+ });
};
-Transloadit.prototype.getAssemblyStatus = function() {};
-
/**
* options - {
* path: '/assemblies',
+ * sign: false (set true to sign request)
* params: { - hash of name/value parameters
* signature: 'Test'
* },
* streams: { - hash of streams
- * name: {
- * fileName,
+ * field: {
+ * filename,
* mimeType,
- * streamLength,
* stream
* }
+ * },
+ * files: {
+ * field: {
+ * path,
+ * filename (optional)
+ * }
* }
* }
*/
Transloadit.prototype._multipart = function(options, cb) {
- var request = new multiparter.request(http, {
- host: API_HOST,
- port: 80,
- path: options.path,
- method: 'POST'
- });
- Object.keys(options.params).forEach(function(key) {
- request.setParam(key, options.params[key]);
+ var stream
+ , json_params
+ , hmac
+ , expires
+ ;
+
+ options = options || {};
+ options.params = options.params || {};
+ options.streams = options.streams || {};
+ options.files = options.files || {};
+ stream = new MultipartStream();
+
+ // add params
+ options.params.auth = {
+ key: this._key
+ };
+ if(options.sign) {
+ expires = new Date();
+ expires.setDate(expires.getDate() + 1);
+ options.params.auth.expires = expires.toISOString();
+ json_params = JSON.stringify(options.params);
+ hmac = crypto.createHmac('sha1', this._secret);
+ hmac.update(json_params);
+ stream.addField('signature', hmac.digest('hex'));
+ } else {
+ json_params = JSON.stringify(options.params);
+ }
+ stream.addField('params', json_params);
+
+ // add streams
+ Object.keys(options.streams).forEach(function streamKey(key) {
+ var currentStream = options.streams[key];
+ stream.addStream(key, currentStream.filename, currentStream.mimeType, currentStream.stream);
});
- Object.keys(options.streams).forEach(function(key) {
- var stream = options.streams[key];
- request.addStream(key, stream.fileName, stream.mimeType, stream.streamLength, stream.stream);
+
+ // add files
+ Object.keys(options.files).forEach(function fileKey(key) {
+ var file = options.files[key];
+ stream.addFile(key, file.path, file.filename);
});
- request.send(cb);
+ // make streaming request
+ stream.pipe(request.post({
+ uri: 'http://' + API_HOST + options.path,
+ headers: {
+ 'Content-Type': 'multipart/form-data; boundary=' + stream.getBoundary()
+ }
+ }, function handleResponse(err, response) {
+ var body;
+
+ if (err) return cb(err);
+
+ response = response || {};
+ response.body = response.body || '{}';
+
+ try {
+ body = JSON.parse(response.body);
+ return cb(null, body);
+ } catch (err) {
+ return cb(err);
+ }
+ }));
};
-module.exports = Transloadit;
+module.exports = Transloadit;
View
@@ -5,10 +5,11 @@
"version": "0.0.0",
"repository": {
"type": "git",
- "url": "git://github.com/SuperShabam/transloadit.git"
+ "url": "git://github.com/supershabam/transloadit.git"
},
"dependencies": {
- "multiparter": "~0.1.4"
+ "request": "~2.9.203",
+ "multipart-form-stream": "0.0.0"
},
"devDependencies": {},
"optionalDependencies": {},

0 comments on commit 70b97f4

Please sign in to comment.