summaryrefslogtreecommitdiff
path: root/client/js/api.js
diff options
context:
space:
mode:
authorrr- <rr-@sakuya.pl>2017-01-07 14:28:36 +0100
committerrr- <rr-@sakuya.pl>2017-01-08 10:25:29 +0100
commit5bf3d5da44f9a60b826a963e20abc470703f5ef9 (patch)
tree70f35dcd2bfc639e37a68ca7839dc37a9a55be44 /client/js/api.js
parentbe6f8d7f465dd75932b77e5f8d6a7a18209ded8b (diff)
client/api: use temporary upload api
Diffstat (limited to 'client/js/api.js')
-rw-r--r--client/js/api.js217
1 files changed, 141 insertions, 76 deletions
diff --git a/client/js/api.js b/client/js/api.js
index 740051a..4f1a05c 100644
--- a/client/js/api.js
+++ b/client/js/api.js
@@ -6,6 +6,8 @@ const request = require('superagent');
const config = require('./config.js');
const events = require('./events.js');
+// TODO: fix abort misery
+
class Api extends events.EventTarget {
constructor() {
super();
@@ -39,7 +41,7 @@ class Api extends events.EventTarget {
resolve(this.cache[url]);
});
}
- return this._process(url, request.get, {}, {}, options)
+ return this._wrappedRequest(url, request.get, {}, {}, options)
.then(response => {
this.cache[url] = response;
return Promise.resolve(response);
@@ -48,89 +50,17 @@ class Api extends events.EventTarget {
post(url, data, files, options) {
this.cache = {};
- return this._process(url, request.post, data, files, options);
+ return this._wrappedRequest(url, request.post, data, files, options);
}
put(url, data, files, options) {
this.cache = {};
- return this._process(url, request.put, data, files, options);
+ return this._wrappedRequest(url, request.put, data, files, options);
}
delete(url, data, options) {
this.cache = {};
- return this._process(url, request.delete, data, {}, options);
- }
-
- _process(url, requestFactory, data, files, options) {
- options = options || {};
- data = Object.assign({}, data);
- const [fullUrl, query] = this._getFullUrl(url);
-
- let abortFunction = null;
-
- let promise = new Promise((resolve, reject) => {
- let req = requestFactory(fullUrl);
-
- req.set('Accept', 'application/json');
- if (query) {
- req.query(query);
- }
- if (files) {
- for (let key of Object.keys(files)) {
- const value = files[key];
- if (value.constructor === String) {
- data[key + 'Url'] = value;
- } else {
- req.attach(key, value || new Blob());
- }
- }
- }
- if (data) {
- req.attach('metadata', new Blob([JSON.stringify(data)]));
- }
- try {
- if (this.userName && this.userPassword) {
- req.auth(
- this.userName,
- encodeURIComponent(this.userPassword)
- .replace(/%([0-9A-F]{2})/g, (match, p1) => {
- return String.fromCharCode('0x' + p1);
- }));
- }
- } catch (e) {
- reject({
- title: 'Authentication error',
- description: 'Malformed credentials'});
- }
-
- if (!options.noProgress) {
- nprogress.start();
- }
-
- abortFunction = () => {
- req.abort(); // does *NOT* call the callback passed in .end()
- nprogress.done();
- reject({
- title: 'Cancelled',
- description:
- 'The request was aborted due to user cancel.'});
- };
-
- req.end((error, response) => {
- nprogress.done();
- if (error) {
- reject(response && response.body ? response.body : {
- title: 'Networking error',
- description: error.message});
- } else {
- resolve(response.body);
- }
- });
- });
-
- promise.abort = () => abortFunction();
-
- return promise;
+ return this._wrappedRequest(url, request.delete, data, {}, options);
}
hasPrivilege(lookup) {
@@ -222,6 +152,141 @@ class Api extends events.EventTarget {
const request = matches[2];
return [baseUrl, request];
}
+
+ _wrappedRequest(url, requestFactory, data, files, options) {
+ // transform the request: upload each file, then make the request use
+ // its tokens.
+ data = Object.assign({}, data);
+ let promise = Promise.resolve();
+ let abortFunction = () => {};
+ if (files) {
+ for (let key of Object.keys(files)) {
+ let file = files[key];
+ if (file.token) {
+ data[key + 'Token'] = file.token;
+ } else {
+ promise = promise
+ .then(() => {
+ let returnedPromise = this._upload(file);
+ abortFunction = () => { returnedPromise.abort(); };
+ return returnedPromise;
+ })
+ .then(token => {
+ abortFunction = () => {};
+ file.token = token;
+ data[key + 'Token'] = token;
+ return Promise.resolve();
+ });
+ }
+ }
+ }
+ promise = promise.then(() => {
+ return this._rawRequest(url, requestFactory, data, {}, options);
+ }, errorMessage => {
+ // TODO: check if the error is because of expired uploads
+ return Promise.reject(errorMessage);
+ });
+ promise.abort = () => abortFunction();
+ return promise;
+ }
+
+ _upload(file, options) {
+ let abortFunction = () => {};
+ let returnedPromise = new Promise((resolve, reject) => {
+ let apiPromise = this._rawRequest(
+ '/uploads', request.post, {}, {content: file}, options);
+ abortFunction = () => apiPromise.abort();
+ return apiPromise.then(
+ response => {
+ resolve(response.token);
+ abortFunction = () => {};
+ },
+ errorMessage => reject(errorMessage));
+ });
+ returnedPromise.abort = () => abortFunction();
+ return returnedPromise;
+ }
+
+ _rawRequest(url, requestFactory, data, files, options) {
+ options = options || {};
+ data = Object.assign({}, data);
+ const [fullUrl, query] = this._getFullUrl(url);
+
+ let abortFunction = null;
+
+ let promise = new Promise((resolve, reject) => {
+ let req = requestFactory(fullUrl);
+
+ req.set('Accept', 'application/json');
+
+ if (query) {
+ req.query(query);
+ }
+
+ if (files) {
+ for (let key of Object.keys(files)) {
+ const value = files[key];
+ if (value.constructor === String) {
+ data[key + 'Url'] = value;
+ } else {
+ req.attach(key, value || new Blob());
+ }
+ }
+ }
+
+ if (data) {
+ if (files && Object.keys(files).length) {
+ req.attach('metadata', new Blob([JSON.stringify(data)]));
+ } else {
+ req.set('Content-Type', 'application/json');
+ req.send(data);
+ }
+ }
+
+ try {
+ if (this.userName && this.userPassword) {
+ req.auth(
+ this.userName,
+ encodeURIComponent(this.userPassword)
+ .replace(/%([0-9A-F]{2})/g, (match, p1) => {
+ return String.fromCharCode('0x' + p1);
+ }));
+ }
+ } catch (e) {
+ reject({
+ title: 'Authentication error',
+ description: 'Malformed credentials'});
+ }
+
+ if (!options.noProgress) {
+ nprogress.start();
+ }
+
+ abortFunction = () => {
+ req.abort(); // does *NOT* call the callback passed in .end()
+ nprogress.done();
+ reject({
+ title: 'Cancelled',
+ description:
+ 'The request was aborted due to user cancel.'});
+ };
+
+ req.end((error, response) => {
+ nprogress.done();
+ if (error) {
+ reject(response && response.body ? response.body : {
+ title: 'Networking error',
+ description: error.message});
+ } else {
+ resolve(response.body);
+ }
+ });
+ });
+
+ promise.abort = () => abortFunction();
+
+ return promise;
+ }
}
module.exports = new Api();