blockstack-storage
Version:
The Blockstack Javascript library for storage.
130 lines (110 loc) • 3.71 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.httpRequest = httpRequest;
var _schemas = require('./schemas');
var assert = require('assert');
var Ajv = require('ajv');
var http = require('http');
var Promise = require('promise');
var jsontokens = require('jsontokens');
var urlparse = require('url');
/*
* Helper method to validate a JSON response
* against a schema. Returns the validated object
* on success, and throw an exception on error.
*/
function validateJSONResponse(resp, result_schema) {
var ajv = new Ajv();
if (result_schema) {
try {
var valid = ajv.validate(result_schema, resp);
assert(valid);
return resp;
} catch (e) {
try {
// error message
var _valid = ajv.validate(_schemas.CORE_ERROR_SCHEMA, resp);
assert(_valid);
return resp;
} catch (e2) {
console.log("Failed to validate with desired schema");
console.log(e.stack);
console.log("Failed to validate with error schema");
console.log(e2.stack);
console.log("Desired schema:");
console.log(result_schema);
console.log("Parsed message:");
console.log(resp);
throw new Error("Invalid core message");
}
}
} else {
return resp;
}
}
/*
* Helper method to issue an HTTP request.
* @param options (Object) set of HTTP request options
* @param result_schema (Object) JSON schema of the expected result
*
* Returns a structured JSON response on success, conformant to the result_schema.
* Returns plaintext on success if the content-type is application/octet-stream
* Returns a structured {'error': ...} object on client-side error
* Throws on server-side error
*/
function httpRequest(options, result_schema, body) {
assert(options['method'], 'No method');
assert(options['host'], 'No host');
assert(options['port'], 'No port');
assert(options['path'], 'No path');
if (!options['headers']) {
options['headers'] = {};
}
if (!options['scheme']) {
options['scheme'] = 'http';
}
if (body) {
assert(options['headers']['Content-Type'], 'No content-type');
options['body'] = body;
options['headers']['Accept'] = '*/*';
}
options['headers']['Origin'] = 'http://localhost:8888';
// extract URL
var url = options.scheme + '://' + options.host + ':' + options.port + options.path;
delete options['scheme'];
delete options['host'];
delete options['port'];
delete options['path'];
console.log(url);
console.log(JSON.stringify(options));
return fetch(url, options).then(function (response) {
if (response.status >= 500) {
throw new Error(response.statusText);
}
if (response.status === 404) {
return { 'error': 'No such file or directory', 'errno': 'ENOENT' };
}
if (response.status === 403) {
return { 'error': 'Access denied', 'errno': 'EACCES' };
}
if (response.status === 401) {
return { 'error': 'Invalid request', 'errno': 'EINVAL' };
}
if (response.status === 400) {
return { 'error': 'Operation not permitted', 'errno': 'EPERM' };
}
var resp = null;
if (response.headers.get('content-type') === 'application/json') {
return response.json().then(function (resp) {
return validateJSONResponse(resp, result_schema);
});
} else {
return response.text();
}
}).catch(function (error) {
console.log('Failed to fetch ' + url + ': ' + error);
throw error;
});
}