UNPKG

swish-http

Version:

A Swish implementation that tunnels over HTTP

125 lines (118 loc) 5.92 kB
var client = require('./client'); var parseQuery = client.parseQuery, createQuery = client.createQuery; function SwishWrapper(store, options) { if (!(this instanceof SwishWrapper)) return new SwishWrapper(store, options); this.store = store; this.options = options || {}; } SwishWrapper.prototype = { express: function () { var store = this.store; function collectJsonBody(request, callback) { var data = []; request.on('data', function (d) { data.push(d); }); request.on('end', function () { data = Buffer.concat(data); try { data = JSON.parse(data.toString('utf-8')); } catch (e) { return callback(e); } return callback(null, data); }); request.on('error', function (e) { return callback(e); }); } return function (request, response) { // Don't do fancy decode - just want the raw query string var query = {}; var queryString = request.url.split('?').slice(1).join('?'); (queryString.match(/[^&=]+(=[^&]*)?/g) || []).forEach(function (pair) { var key = pair.split('=', 1)[0], value = pair.substring(key.length + 1); key = decodeURIComponent(key); value = decodeURIComponent(value); if (key in query) { query[key] = [].concat(query[key]).concat(value); } else { query[key] = value; } }); var obj = parseQuery(query); if (obj.error) return response.status(400).json(obj); var schema = obj.schema, options = obj.options; if (request.method === 'GET') { if (!schema) return response.status(400).json('Invalid search query'); store.search(schema, options, function (error, results, continueOptions) { if (error) return response.status(400).json(error.message); if (continueOptions) { var nextQuery = createQuery(schema, continueOptions); var queryParts = []; for (var key in nextQuery) { queryParts.push(encodeURIComponent(key) + '=' + encodeURIComponent(nextQuery[key])); } var nextUrl = request.originalUrl.replace(/\?.*/, '') + '?' + queryParts.join('&'); response.links({ 'next': nextUrl }); } response.json(results); }); } else if (request.method === 'PUT') { if (!schema) return response.status(400).json('Invalid search query'); collectJsonBody(request, function (error, data) { if (error) return response.status(400).json(error.message); store.replace(schema, data, function (error, result) { if (error) return response.status(400).json(result || error.message); response.json(result); }); }); } else if (request.method === 'DELETE') { if (!schema) return response.status(400).json('Invalid search query'); store.remove(schema, function (error, result) { if (error) return response.status(400).json(result || error.message); response.json(result); }); } else if (request.method === 'PATCH') { if (!schema) return response.status(400).json('Invalid search query'); collectJsonBody(request, function (error, data) { if (error) return response.status(400).json(error.message); var contentType = request.headers['content-type'].replace(/;.*/, ''); if (contentType === 'application/merge-patch+json') { store.update(schema, data, function (error, result) { if (error) return response.status(400).json(result || error.message); response.json(result); }); } else if (contentType === 'application/json-patch+json') { store.patch(schema, data, function (error, result) { if (error) return response.status(400).json(result || error.message); response.json(result); }); } else { response.status(415).json("Invalid PATCH type: " + contentType); } }); } else if (request.method === 'POST') { collectJsonBody(request, function (error, data) { if (error) return response.status(400).json(error.message); if (Array.isArray(data)) { store.createMultiple(data, options, function (error, result) { if (error) return response.status(400).json(result || error.message); response.json(result); }); } else { store.create(data, options, function (error, result) { if (error) return response.status(400).json(result || error.message); response.json(result); }); } }); } else { return response.status(405).json('Unknown method: ' + request.method); } }; } }; module.exports = SwishWrapper;