diff --git a/Gruntfile.js b/Gruntfile.js index 825d5e71c9e724341635a23941e12864e84005cd..b66fc9e3fb0ad04a8957d50c0b6b67951f454862 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -169,6 +169,7 @@ module.exports = function (grunt) { 'src/jio.storage/uuidstorage.js', 'src/jio.storage/memorystorage.js', 'src/jio.storage/zipstorage.js', + 'src/jio.storage/httpstorage.js', 'src/jio.storage/dropboxstorage.js', 'src/jio.storage/davstorage.js', 'src/jio.storage/gdrivestorage.js', diff --git a/src/jio.storage/httpstorage.js b/src/jio.storage/httpstorage.js new file mode 100644 index 0000000000000000000000000000000000000000..1ca49afeb47ed3a4cc2b4991d0d17c1db6c16309 --- /dev/null +++ b/src/jio.storage/httpstorage.js @@ -0,0 +1,94 @@ +/*global RSVP, Blob*/ +/*jslint nomen: true*/ +(function (jIO, RSVP, Blob) { + "use strict"; + + function HttpStorage(spec) { + if (spec.hasOwnProperty('catch_error')) { + this._catch_error = spec.catch_error; + } else { + this._catch_error = false; + } + } + + HttpStorage.prototype.get = function (id) { + var context = this; + return new RSVP.Queue() + .push(function () { + return jIO.util.ajax({ + type: 'HEAD', + url: id + }); + }) + .push(undefined, function (error) { + if (context._catch_error) { + return error; + } + if ((error.target !== undefined) && + (error.target.status === 404)) { + throw new jIO.util.jIOError("Cannot find url " + id, 404); + } + throw error; + }) + .push(function (response) { + + var key_list = ["Content-Disposition", "Content-Type", "Date", + "Last-Modified", "Vary", "Cache-Control", "Etag", + "Accept-Ranges", "Content-Range"], + i, + key, + value, + result = {}; + result.Status = response.target.status; + for (i = 0; i < key_list.length; i += 1) { + key = key_list[i]; + value = response.target.getResponseHeader(key); + if (value !== null) { + result[key] = value; + } + } + return result; + }); + }; + + HttpStorage.prototype.allAttachments = function () { + return {enclosure: {}}; + }; + + HttpStorage.prototype.getAttachment = function (id, name) { + var context = this; + if (name !== 'enclosure') { + throw new jIO.util.jIOError("Forbidden attachment: " + + id + " , " + name, + 400); + } + return new RSVP.Queue() + .push(function () { + return jIO.util.ajax({ + type: 'GET', + url: id, + dataType: "blob" + }); + }) + .push(undefined, function (error) { + if (context._catch_error) { + return error; + } + if ((error.target !== undefined) && + (error.target.status === 404)) { + throw new jIO.util.jIOError("Cannot find url " + id, 404); + } + throw error; + }) + .push(function (response) { + return new Blob( + [response.target.response || response.target.responseText], + {"type": response.target.getResponseHeader('Content-Type') || + "application/octet-stream"} + ); + }); + }; + + jIO.addStorage('http', HttpStorage); + +}(jIO, RSVP, Blob)); \ No newline at end of file diff --git a/test/jio.storage/httpstorage.tests.js b/test/jio.storage/httpstorage.tests.js new file mode 100644 index 0000000000000000000000000000000000000000..18403cd4ec043fac1c3d0b85de1af86aa3787359 --- /dev/null +++ b/test/jio.storage/httpstorage.tests.js @@ -0,0 +1,336 @@ +/*jslint nomen: true */ +/*global Blob, sinon*/ +(function (jIO, QUnit, Blob, sinon) { + "use strict"; + var test = QUnit.test, + stop = QUnit.stop, + start = QUnit.start, + ok = QUnit.ok, + expect = QUnit.expect, + deepEqual = QUnit.deepEqual, + equal = QUnit.equal, + module = QUnit.module, + domain = "https://example.org"; + + ///////////////////////////////////////////////////////////////// + // davStorage constructor + ///////////////////////////////////////////////////////////////// + module("httpStorage.constructor"); + + test("default parameters", function () { + var jio = jIO.createJIO({ + type: "http" + }); + + equal(jio.__type, "http"); + deepEqual(jio.__storage._catch_error, false); + }); + + test("Storage store catch_error", function () { + var jio = jIO.createJIO({ + type: "http", + catch_error: true + }); + + equal(jio.__type, "http"); + deepEqual(jio.__storage._catch_error, true); + }); + + ///////////////////////////////////////////////////////////////// + // httpStorage.get + ///////////////////////////////////////////////////////////////// + module("httpStorage.get", { + setup: function () { + + this.server = sinon.fakeServer.create(); + this.server.autoRespond = true; + this.server.autoRespondAfter = 5; + + this.jio = jIO.createJIO({ + type: "http" + }); + }, + teardown: function () { + this.server.restore(); + delete this.server; + } + }); + + test("get document", function () { + var id = domain + "/id1/"; + this.server.respondWith("HEAD", id, [200, { + "Content-Type": "text/xml-foo" + }, '']); + stop(); + expect(1); + + this.jio.get(id) + .then(function (result) { + deepEqual(result, { + "Content-Type": "text/xml-foo", + "Status": 200 + }, "Check document"); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("get document with a not expected status", function () { + var id = domain + "/id1/"; + this.server.respondWith("HEAD", id, [500, { + "Content-Type": "text/xml-foo" + }, '']); + stop(); + expect(1); + + this.jio.get(id) + .then(function (result) { + ok(false, result); + }) + .fail(function (error) { + equal(error.target.status, 500); + }) + .always(function () { + start(); + }); + }); + + test("get document with 404 status", function () { + var id = domain + "/id1/"; + + stop(); + expect(3); + + this.jio.get(id) + .then(function (result) { + ok(false, result); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find url " + id); + equal(error.status_code, 404); + }) + .always(function () { + start(); + }); + }); + + test("get document with a not expected status and catch error", function () { + var id = domain + "/id1/"; + this.server.respondWith("HEAD", id, [500, { + "Content-Type": "text/xml-foo" + }, '']); + + this.jio = jIO.createJIO({ + type: "http", + catch_error: true + }); + + stop(); + expect(1); + + this.jio.get(id) + .then(function (result) { + deepEqual(result, { + "Content-Type": "text/xml-foo", + "Status": 500 + }, "Check document"); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + ///////////////////////////////////////////////////////////////// + // httpStorage.allAttachments + ///////////////////////////////////////////////////////////////// + module("httpStorage.allAttachments", { + setup: function () { + + this.server = sinon.fakeServer.create(); + this.server.autoRespond = true; + this.server.autoRespondAfter = 5; + + this.jio = jIO.createJIO({ + type: "http" + }); + }, + teardown: function () { + this.server.restore(); + delete this.server; + } + }); + + test("get document with attachment", function () { + stop(); + expect(1); + + this.jio.allAttachments('/id') + .then(function (result) { + deepEqual(result, { + enclosure: {} + }, "Check document"); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + ///////////////////////////////////////////////////////////////// + // httpStorage.getAttachment + ///////////////////////////////////////////////////////////////// + module("httpStorage.getAttachment", { + setup: function () { + + this.server = sinon.fakeServer.create(); + this.server.autoRespond = true; + this.server.autoRespondAfter = 5; + + this.jio = jIO.createJIO({ + type: "http" + }); + }, + teardown: function () { + this.server.restore(); + delete this.server; + } + }); + + test("forbidden attachment", function () { + var id = domain + "/id1/"; + + stop(); + expect(3); + + this.jio.getAttachment( + id, + "attachment1" + ) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal( + error.message, + "Forbidden attachment: https://example.org/id1/ , attachment1" + ); + equal(error.status_code, 400); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + test("get attachment", function () { + var id = domain + "/id1/"; + + this.server.respondWith("GET", id, [200, { + "Content-Type": "text/xml-foo" + }, "foo\nbaré"]); + + stop(); + expect(3); + + this.jio.getAttachment(id, 'enclosure') + .then(function (result) { + ok(result instanceof Blob, "Data is Blob"); + deepEqual(result.type, "text/xml-foo", "Check mimetype"); + return jIO.util.readBlobAsText(result); + }) + .then(function (result) { + equal(result.target.result, "foo\nbaré", + "Attachment correctly fetched"); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + + + test("get attachment with a not expected status", function () { + var id = domain + "/id1/"; + this.server.respondWith("GET", id, [500, { + "Content-Type": "text/xml-foo" + }, '']); + stop(); + expect(1); + + this.jio.getAttachment(id, 'enclosure') + .then(function (result) { + ok(false, result); + }) + .fail(function (error) { + equal(error.target.status, 500); + }) + .always(function () { + start(); + }); + }); + + test("get attachment with 404 status", function () { + var id = domain + "/id1/"; + + stop(); + expect(3); + + this.jio.getAttachment(id, 'enclosure') + .then(function (result) { + ok(false, result); + }) + .fail(function (error) { + ok(error instanceof jIO.util.jIOError); + equal(error.message, "Cannot find url " + id); + equal(error.status_code, 404); + }) + .always(function () { + start(); + }); + }); + + test("get attachment with unexpected status and catch error", function () { + var id = domain + "/id1/"; + this.server.respondWith("GET", id, [500, { + "Content-Type": "text/xml-foo" + }, 'foo\nbaré']); + + this.jio = jIO.createJIO({ + type: "http", + catch_error: true + }); + + stop(); + expect(3); + + this.jio.getAttachment(id, 'enclosure') + .then(function (result) { + ok(result instanceof Blob, "Data is Blob"); + deepEqual(result.type, "text/xml-foo", "Check mimetype"); + return jIO.util.readBlobAsText(result); + }) + .then(function (result) { + equal(result.target.result, "foo\nbaré", + "Attachment correctly fetched"); + }) + .fail(function (error) { + ok(false, error); + }) + .always(function () { + start(); + }); + }); + +}(jIO, QUnit, Blob, sinon)); diff --git a/test/tests.html b/test/tests.html index d72908a44131a56327876941b756716c7e5e9e18..9c76b2d42961112958e23345c4af93b2edd027c0 100644 --- a/test/tests.html +++ b/test/tests.html @@ -51,6 +51,7 @@ <script src="jio.storage/zipstorage.tests.js"></script> <script src="jio.storage/gdrivestorage.tests.js"></script> <script src="jio.storage/websqlstorage.tests.js"></script> + <script src="jio.storage/httpstorage.tests.js"></script> <!--script src="../lib/jquery/jquery.min.js"></script> <script src="../src/jio.storage/xwikistorage.js"></script> <script src="jio.storage/xwikistorage.tests.js"></script-->