mongodb-rest
Advanced tools
Comparing version 0.10.6 to 0.10.7
@@ -14,5 +14,13 @@ { | ||
}, | ||
"mongoOptions": { | ||
"serverOptions": { | ||
}, | ||
"dbOptions": { | ||
"w": 1 | ||
} | ||
}, | ||
"flavor": "regular", | ||
"debug": true, | ||
"humanReadableOutput": true | ||
"humanReadableOutput": true, | ||
"collectionOutputType": "json" | ||
} |
464
lib/rest.js
@@ -5,2 +5,3 @@ /* | ||
Maintained by Ashley Davis 2014-07-02 | ||
Created by Tom de Grunt on 2010-10-03. | ||
@@ -15,37 +16,71 @@ Copyright (c) 2010 Tom de Grunt. | ||
var util = require("./util")(config); | ||
var util = require("./util")(config); | ||
var extend = require("extend"); | ||
// | ||
// Parameters for connection to the server. | ||
// http://mongodb.github.io/node-mongodb-native/api-generated/server.html | ||
// | ||
var serverParams = { | ||
auto_reconnect: true, | ||
}; | ||
var collectionOutputType = config.collectionOutputType || "json"; | ||
var transformCollection = config.transformCollection; | ||
if (!transformCollection) { | ||
if (collectionOutputType === 'json') { | ||
// By default, don't transform json data. | ||
transformCollection = function (input) { | ||
return input; | ||
}; | ||
} | ||
else if (collectionOutputType === 'csv') { | ||
// Convert input array of objects into an array of rows/columns for csv output. | ||
transformCollection = function (input) { | ||
if (input.length == 0) { | ||
return []; | ||
} | ||
// | ||
// Parameters for connection to the database. | ||
// http://mongodb.github.io/node-mongodb-native/api-generated/db.html | ||
// | ||
var dbParams = { | ||
w: 1, // Default write concern. | ||
} | ||
var keys = Object.keys(input[0]); | ||
return [keys].concat( | ||
input.map(function (dataItem) { | ||
return keys.map(function (key) { | ||
return dataItem[key]; | ||
}); | ||
}) | ||
); | ||
}; | ||
} | ||
} | ||
// | ||
// Get database names. | ||
// | ||
app.get('/dbs', function(req, res) { | ||
// | ||
// Parameters for connection to the server. | ||
// http://mongodb.github.io/node-mongodb-native/api-generated/server.html | ||
// | ||
var defaultServerParams = { | ||
auto_reconnect: true, | ||
}; | ||
var serverParams = defaultServerParams; | ||
if (config.mongoOptions && config.mongoOptions.serverOptions) { | ||
serverParams = extend(false, defaultServerParams, config.mongoOptions.serverOptions); | ||
} | ||
var db = new mongo.Db('none', new mongo.Server(config.db.host, config.db.port, serverParams), dbParams); | ||
db.open(function(err,db) { | ||
if (err) { | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
console.log("Database server options: "); | ||
console.log(serverParams); | ||
// Use the admin database for the operation | ||
var adminDb = db.admin(); | ||
// | ||
// Parameters for connection to the database. | ||
// http://mongodb.github.io/node-mongodb-native/api-generated/db.html | ||
// | ||
var defaultDbParams = { | ||
w: 1, // Default write concern. | ||
} | ||
var dbParams = defaultDbParams; | ||
if (config.mongoOptions && config.mongoOptions.dbOptions) { | ||
dbParams = config.mongoOptions.dbOptions; | ||
} | ||
// List all the available databases | ||
adminDb.listDatabases(function(err, dbs) { | ||
console.log("Database options: "); | ||
console.log(dbParams); | ||
// | ||
// Get database names. | ||
// | ||
app.get('/dbs', function(req, res) { | ||
var db = new mongo.Db('none', new mongo.Server(config.db.host, config.db.port, serverParams), dbParams); | ||
db.open(function(err,db) { | ||
if (err) { | ||
@@ -57,219 +92,238 @@ db.close(); | ||
var dbNames = dbs.databases.map(function (db) { | ||
return db.name; | ||
}); | ||
// Use the admin database for the operation | ||
var adminDb = db.admin(); | ||
res.json(dbNames); | ||
db.close(); | ||
}); | ||
}); | ||
}); | ||
// List all the available databases | ||
adminDb.listDatabases(function(err, dbs) { | ||
if (err) { | ||
db.close(); | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
// | ||
// Get names of all collections in specified database. | ||
// | ||
app.get('/:db', function (req, res) { | ||
var dbNames = dbs.databases.map(function (db) { | ||
return db.name; | ||
}); | ||
var db = new mongo.Db(req.params.db, new mongo.Server(config.db.host, config.db.port, serverParams), dbParams); | ||
db.open(function(err,db) { | ||
if (err) { | ||
db.close(); | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
db.collectionNames(function (err, collections) { | ||
if (err) { | ||
db.close(); | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
var collectionNames = collections.map(function (collection) { | ||
// Pull out the name of the collection and chop off the database name. | ||
return collection.name.substring(req.params.db.length+1); | ||
res.json(dbNames); | ||
db.close(); | ||
}); | ||
}); | ||
res.json(collectionNames); | ||
db.close(); | ||
}); | ||
}); | ||
}); | ||
// | ||
// Get names of all collections in specified database. | ||
// | ||
app.get('/:db', function (req, res) { | ||
/** | ||
* Query | ||
*/ | ||
app.get('/:db/:collection/:id?', function(req, res) { | ||
var query = req.query.query ? JSON.parse(req.query.query) : {}; | ||
// Providing an id overwrites giving a query in the URL | ||
if (req.params.id) { | ||
query = {'_id': new BSON.ObjectID(req.params.id)}; | ||
} | ||
var options = req.params.options || {}; | ||
var test = ['limit','sort','fields','skip','hint','explain','snapshot','timeout']; | ||
for( o in req.query ) { | ||
if( test.indexOf(o) >= 0 ) { | ||
options[o] = req.query[o]; | ||
} | ||
} | ||
var db = new mongo.Db(req.params.db, new mongo.Server(config.db.host, config.db.port, serverParams), dbParams); | ||
db.open(function(err,db) { | ||
if (err) { | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
db.authenticate(config.db.username, config.db.password, function () { | ||
db.collection(req.params.collection, function(err, collection) { | ||
if (err) { | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
collection.find(query, options, function(err, cursor) { | ||
var db = new mongo.Db(req.params.db, new mongo.Server(config.db.host, config.db.port, serverParams), dbParams); | ||
db.open(function(err,db) { | ||
if (err) { | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
cursor.toArray(function(err, docs){ | ||
if (err) { | ||
db.close(); | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
} | ||
var result = []; | ||
if(req.params.id) { | ||
if(docs.length > 0) { | ||
result = util.flavorize(docs[0], "out"); | ||
res.send(result); | ||
} else { | ||
res.status(404).send({ ok: 0 }); | ||
db.collectionNames(function (err, collections) { | ||
if (err) { | ||
db.close(); | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
} else { | ||
docs.forEach(function(doc){ | ||
result.push(util.flavorize(doc, "out")); | ||
var collectionNames = collections.map(function (collection) { | ||
// Pull out the name of the collection and chop off the database name. | ||
return collection.name.substring(req.params.db.length+1); | ||
}); | ||
res.send(result); | ||
} | ||
db.close(); | ||
res.json(collectionNames); | ||
db.close(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
/** | ||
* Insert | ||
*/ | ||
app.post('/:db/:collection', function(req, res) { | ||
if(req.body) { | ||
var db = new mongo.Db(req.params.db, new mongo.Server(config.db.host, config.db.port, serverParams), dbParams); | ||
db.open(function(err, db) { | ||
if (err) { | ||
res.status(500).send(err.message); | ||
return; | ||
/** | ||
* Query | ||
*/ | ||
app.get('/:db/:collection/:id?', function(req, res) { | ||
var query = req.query.query ? JSON.parse(req.query.query) : {}; | ||
// Providing an id overwrites giving a query in the URL | ||
if (req.params.id) { | ||
query = {'_id': new BSON.ObjectID(req.params.id)}; | ||
} | ||
var options = req.params.options || {}; | ||
db.authenticate(config.db.username, config.db.password, function () { | ||
var test = ['limit','sort','fields','skip','hint','explain','snapshot','timeout']; | ||
db.collection(req.params.collection, function(err, collection) { | ||
for( o in req.query ) { | ||
if( test.indexOf(o) >= 0 ) { | ||
options[o] = req.query[o]; | ||
} | ||
} | ||
var db = new mongo.Db(req.params.db, new mongo.Server(config.db.host, config.db.port, serverParams), dbParams); | ||
db.open(function(err,db) { | ||
if (err) { | ||
res.status(500).send(err.message); | ||
return; | ||
db.close(); | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
// We only support inserting one document at a time | ||
collection.insert( | ||
Array.isArray(req.body) ? req.body[0] : req.body, | ||
function(err, docs) { | ||
db.authenticate(config.db.username, config.db.password, function () { | ||
db.collection(req.params.collection, function(err, collection) { | ||
if (err) { | ||
db.close(); | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
collection.find(query, options, function(err, cursor) { | ||
if (err) { | ||
db.close(); | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
cursor.toArray(function(err, docs){ | ||
if (err) { | ||
db.close(); | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
var result = []; | ||
if(req.params.id) { | ||
if(docs.length > 0) { | ||
result = util.flavorize(docs[0], "out"); | ||
res.json(result); | ||
} else { | ||
res.status(404).json({ ok: 0 }); | ||
} | ||
} else { | ||
docs.forEach(function(doc) { | ||
result.push(util.flavorize(doc, "out")); | ||
}); | ||
result = transformCollection(result) | ||
res[collectionOutputType](result); | ||
} | ||
db.close(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
/** | ||
* Insert | ||
*/ | ||
app.post('/:db/:collection', function(req, res) { | ||
if(req.body) { | ||
var db = new mongo.Db(req.params.db, new mongo.Server(config.db.host, config.db.port, serverParams), dbParams); | ||
db.open(function(err, db) { | ||
if (err) { | ||
res.status(500).send(err.message); | ||
return; | ||
db.close(); | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
res.header('Location', '/'+req.params.db+'/'+req.params.collection+'/'+docs[0]._id.toHexString()); | ||
res.status(201).send({ ok: 1 }); | ||
db.close(); | ||
} | ||
); | ||
}); | ||
}); | ||
}); | ||
} else { | ||
res.send({ ok: 1 }); | ||
} | ||
}); | ||
db.authenticate(config.db.username, config.db.password, function () { | ||
db.collection(req.params.collection, function(err, collection) { | ||
if (err) { | ||
db.close(); | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
/** | ||
* Update | ||
*/ | ||
app.put('/:db/:collection/:id', function(req, res) { | ||
var spec = {'_id': new BSON.ObjectID(req.params.id)}; | ||
// We only support inserting one document at a time | ||
collection.insert( | ||
Array.isArray(req.body) ? req.body[0] : req.body, | ||
function(err, docs) { | ||
if (err) { | ||
db.close(); | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
var db = new mongo.Db(req.params.db, new mongo.Server(config.db.host, config.db.port, serverParams), dbParams); | ||
db.open(function(err, db) { | ||
if (err) { | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
res.header('Location', '/'+req.params.db+'/'+req.params.collection+'/'+docs[0]._id.toHexString()); | ||
res.status(201).json({ ok: 1 }); | ||
db.close(); | ||
} | ||
); | ||
}); | ||
}); | ||
}); | ||
} else { | ||
res.json({ ok: 1 }); | ||
} | ||
}); | ||
db.authenticate(config.db.username, config.db.password, function () { | ||
/** | ||
* Update | ||
*/ | ||
app.put('/:db/:collection/:id', function(req, res) { | ||
var spec = {'_id': new BSON.ObjectID(req.params.id)}; | ||
db.collection(req.params.collection, function(err, collection) { | ||
if (err) { | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
var db = new mongo.Db(req.params.db, new mongo.Server(config.db.host, config.db.port, serverParams), dbParams); | ||
db.open(function(err, db) { | ||
if (err) { | ||
db.close(); | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
collection.update(spec, req.body, true, function(err, docs) { | ||
res.send({ ok: 1 }); | ||
db.close(); | ||
}); | ||
db.authenticate(config.db.username, config.db.password, function () { | ||
db.collection(req.params.collection, function(err, collection) { | ||
if (err) { | ||
db.close(); | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
collection.update(spec, req.body, true, function(err, docs) { | ||
res.json({ ok: 1 }); | ||
db.close(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
/** | ||
* Delete | ||
*/ | ||
app.delete('/:db/:collection/:id', function(req, res) { | ||
var spec = {'_id': new BSON.ObjectID(req.params.id)}; | ||
var db = new mongo.Db(req.params.db, new mongo.Server(config.db.host, config.db.port, serverParams), dbParams); | ||
db.open(function(err, db) { | ||
if (err) { | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
/** | ||
* Delete | ||
*/ | ||
app.delete('/:db/:collection/:id', function(req, res) { | ||
var spec = {'_id': new BSON.ObjectID(req.params.id)}; | ||
db.authenticate(config.db.username, config.db.password, function () { | ||
db.collection(req.params.collection, function(err, collection) { | ||
if (err) { | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
collection.remove(spec, function(err, docs) { | ||
var db = new mongo.Db(req.params.db, new mongo.Server(config.db.host, config.db.port, serverParams), dbParams); | ||
db.open(function(err, db) { | ||
if (err) { | ||
res.status(500).send(err.message); | ||
return; | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
res.send({ ok: 1 }); | ||
db.close(); | ||
}); | ||
db.authenticate(config.db.username, config.db.password, function () { | ||
db.collection(req.params.collection, function(err, collection) { | ||
if (err) { | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
collection.remove(spec, function(err, docs) { | ||
if (err) { | ||
res.status(500).send(err.message); | ||
return; | ||
} | ||
res.json({ ok: 1 }); | ||
db.close(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}; |
{ | ||
"name": "mongodb-rest", | ||
"description": "REST API Server for MongoDB", | ||
"version": "0.10.6", | ||
"version": "0.10.7", | ||
"author": "Ashley Davis <ashleydavis@insanefx.com>", | ||
@@ -25,3 +25,5 @@ "contributors": [ | ||
"mongodb": "= 1.4.7", | ||
"body-parser": "^1.4.3" | ||
"body-parser": "^1.4.3", | ||
"extend": "^1.3.0", | ||
"express-csv": "^0.6.0" | ||
}, | ||
@@ -28,0 +30,0 @@ "keywords": [ |
@@ -17,2 +17,3 @@ This project is no longer abandoned! | ||
REST API output is now human readable by default.<br/> | ||
MongoBD server and database options can now be specified in the config file.<br/> | ||
@@ -89,6 +90,27 @@ Name | ||
} | ||
"mongoOptions": { | ||
"serverOptions": { | ||
}, | ||
"dbOptions": { | ||
"w": 1 | ||
} | ||
}, | ||
"humanReadableOutput": true | ||
} | ||
`mongoOptions` specifies MongoDB server and database connection parameters. These are passed directly to the MongoDB API. | ||
Valid options under `serverOptions` are documented here: http://mongodb.github.io/node-mongodb-native/api-generated/server.html. | ||
`auto_reconnect` is automatically enabled, don't override this or mongodb-rest may not work as expected. | ||
Valid options under `dbOptions` are documented here: http://mongodb.github.io/node-mongodb-native/api-generated/db.html. | ||
`w` (write concern) is set to 1 so that acknowledgement of the write is recieved by mongodb-rest, currently this must be enabled for error checking. | ||
Set `collectionOutputType` to `csv` to returns collections as csv data rather than json. | ||
If you are configuring the server procedurally you can assign a Javascript function to `transformCollection` which will transform each collection before returning it via HTTP. | ||
Supported REST API | ||
@@ -95,0 +117,0 @@ ------------------ |
@@ -5,2 +5,3 @@ /* | ||
Maintained by Ashley Davis 2014-07-02 | ||
Created by Tom de Grunt on 2010-10-03. | ||
@@ -17,17 +18,25 @@ Copyright (c) 2010 Tom de Grunt. | ||
var defaultConfig = { | ||
"db": { | ||
'port': 27017, | ||
'host': "localhost" | ||
"db": { | ||
'port': 27017, | ||
'host': "localhost" | ||
}, | ||
'server': { | ||
'port': 3000, | ||
'address': "0.0.0.0" | ||
}, | ||
"accessControl": { | ||
"allowOrigin": "*", | ||
"allowMethods": "GET,POST,PUT,DELETE,HEAD,OPTIONS" | ||
}, | ||
'flavor': "regular", | ||
'debug': true, | ||
'humanReadableOutput': true | ||
'server': { | ||
'port': 3000, | ||
'address': "0.0.0.0" | ||
}, | ||
"accessControl": { | ||
"allowOrigin": "*", | ||
"allowMethods": "GET,POST,PUT,DELETE,HEAD,OPTIONS" | ||
}, | ||
"mongoOptions": { | ||
"serverOptions": { | ||
}, | ||
"dbOptions": { | ||
"w": 1 | ||
} | ||
}, | ||
'flavor': "regular", | ||
'debug': true, | ||
'humanReadableOutput': true, | ||
collectionOutputType: "json" | ||
}; | ||
@@ -45,3 +54,3 @@ | ||
console.log("Current directory: " + curDir); | ||
if (!config) { | ||
@@ -61,2 +70,3 @@ var configFilePath = path.join(curDir, "config.json"); | ||
var app = express(); | ||
require('express-csv'); | ||
@@ -74,2 +84,6 @@ app.use(require('body-parser')()); | ||
app.get('/favicon.ico', function (req, res) { | ||
res.status(404); | ||
}); | ||
require('./lib/rest')(app, config); | ||
@@ -76,0 +90,0 @@ |
@@ -39,7 +39,7 @@ 'use strict'; | ||
beforeEach(function () { | ||
var init = function (config) { | ||
// Open the rest server for each test. | ||
restServer.startServer(); | ||
}); | ||
restServer.startServer(config); | ||
}; | ||
@@ -54,2 +54,4 @@ afterEach(function () { | ||
init(); | ||
dropDatabase(testDbName) | ||
@@ -79,2 +81,4 @@ .then(function () { | ||
init(); | ||
var testcol1 = "testcol1"; | ||
@@ -113,2 +117,4 @@ var testcol2 = "testcol2"; | ||
init(); | ||
dropAndLoad(testDbName, testCollectionName, []) | ||
@@ -129,2 +135,4 @@ .then(function () { | ||
init(); | ||
var testData = [ | ||
@@ -162,2 +170,4 @@ { | ||
init(); | ||
dropAndLoad(testDbName, testCollectionName, []) | ||
@@ -179,2 +189,4 @@ .then(function () { | ||
init(); | ||
var itemID = ObjectID(); | ||
@@ -210,4 +222,81 @@ | ||
it('can retreive csv format data from db collection', function (done) { | ||
init({ | ||
db: { | ||
port: 27017, | ||
host: "localhost" | ||
}, | ||
server: { | ||
port: 3000, | ||
address: "0.0.0.0" | ||
}, | ||
"accessControl": { | ||
"allowOrigin": "*", | ||
"allowMethods": "GET,POST,PUT,DELETE,HEAD,OPTIONS" | ||
}, | ||
"mongoOptions": { | ||
"serverOptions": { | ||
}, | ||
"dbOptions": { | ||
"w": 1 | ||
} | ||
}, | ||
"flavor": "regular", | ||
"debug": true, | ||
"humanReadableOutput": true, | ||
collectionResponseType: 'csv', | ||
}); | ||
var testData = [ | ||
{ | ||
item: 1, | ||
}, | ||
{ | ||
item: 2, | ||
}, | ||
{ | ||
item: 3, | ||
}, | ||
]; | ||
dropAndLoad(testDbName, testCollectionName, testData) | ||
.then(function () { | ||
return requestHttp(collectionUrl); | ||
}) | ||
.then(function (result) { | ||
var lines = result.data.trim().split('\r\n'); | ||
expect(lines.length).toBe(4); | ||
var headerRow = lines[0].split(','); | ||
expect(headerRow[0]).toEqual("\"item\""); | ||
expect(headerRow[1]).toEqual("\"_id\""); | ||
lines.shift(); // Remove header line. | ||
var items = lines.map(function (line) { | ||
var columns = line.split(','); | ||
return { | ||
item: parseInt(columns[0].substring(1,columns[0].length-1)), | ||
}; | ||
}); | ||
items.sort(function (a, b) { return a.item-b.item; }); // Sort results, can't guarantee order otherwise. | ||
expect(items[0].item).toBe(1); | ||
expect(items[1].item).toBe(2); | ||
expect(items[2].item).toBe(3); | ||
done(); | ||
}) | ||
.catch(function (err) { | ||
done(err); | ||
}); | ||
}); | ||
it('can retreive single document from db collection', function (done) { | ||
init(); | ||
var itemID = ObjectID(); | ||
@@ -246,2 +335,4 @@ | ||
init(); | ||
var postData = { | ||
@@ -273,2 +364,4 @@ value: "hi there", | ||
init(); | ||
var itemID = ObjectID(); | ||
@@ -318,2 +411,4 @@ | ||
init(); | ||
var itemID = ObjectID(); | ||
@@ -320,0 +415,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1037
166
48860
5
12
+ Addedexpress-csv@^0.6.0
+ Addedextend@^1.3.0
+ Addedexpress-csv@0.6.0(transitive)
+ Addedextend@1.3.0(transitive)