2011-06-20 21:39:12 +08:00
|
|
|
var express= require('express')
|
|
|
|
, app = express.createServer(
|
|
|
|
//TODO: make logs async background + 1min or so
|
2011-07-05 19:01:34 +08:00
|
|
|
express.logger({buffer:true,
|
|
|
|
format:'[:remote-addr :date] \033[90m:method\033[0m \033[36m:url\033[0m \033[90m:status :response-timems -> :res[Content-Type]\033[0m'})
|
2011-06-20 21:39:12 +08:00
|
|
|
)
|
2011-07-05 19:01:34 +08:00
|
|
|
|
2011-06-13 11:23:02 +08:00
|
|
|
, Step = require(global.settings.app_root + '/lib/step')
|
|
|
|
, oAuth = require(global.settings.app_root + '/app/models/oauth')
|
|
|
|
, PSQL = require(global.settings.app_root + '/app/models/psql')
|
|
|
|
, _ = require('underscore');
|
|
|
|
_.mixin(require('underscore.string'));
|
|
|
|
|
|
|
|
|
|
|
|
// CartoDB v1 SQL API
|
|
|
|
//
|
|
|
|
// all requests expect the following URL args:
|
|
|
|
// - `sql` {String} SQL to execute
|
|
|
|
//
|
|
|
|
// for private (read/write) queries:
|
|
|
|
// - `auth_token` {String} oAuth API token from CartoDB. In URL or request header.
|
|
|
|
//
|
2011-07-04 23:28:39 +08:00
|
|
|
// eg. /api/v1/?sql=SELECT 1 as one&auth_token=my_token
|
2011-06-13 11:23:02 +08:00
|
|
|
//
|
|
|
|
// for public (read only) queries:
|
|
|
|
// - `database` {String} The database to execute queries on
|
|
|
|
//
|
2011-07-04 23:28:39 +08:00
|
|
|
// eg. /api/v1/?sql=SELECT 1 as one&database=my_public_db
|
2011-06-13 11:23:02 +08:00
|
|
|
//
|
2011-07-04 23:28:39 +08:00
|
|
|
// NOTE: private queries can only be ran on databases the oAuth key gives access to.
|
|
|
|
app.get('/api/v1/', function(req, res){
|
|
|
|
|
2011-06-13 11:23:02 +08:00
|
|
|
//sanitize input
|
2011-06-13 20:07:21 +08:00
|
|
|
var sql = req.query.sql;
|
2011-07-06 00:31:01 +08:00
|
|
|
var database = req.query.database;
|
2011-07-06 00:56:31 +08:00
|
|
|
var limit = parseInt(req.query.rows_per_page);
|
|
|
|
var offset = parseInt(req.query.page);
|
2011-07-06 00:31:01 +08:00
|
|
|
|
|
|
|
sql = (sql == "") ? null : sql;
|
|
|
|
database = (database == "") ? null : database;
|
2011-07-06 00:56:31 +08:00
|
|
|
limit = (_.isNumber(limit)) ? limit : null;
|
|
|
|
offset = (_.isNumber(offset)) ? offset * limit : null;
|
2011-07-06 00:31:01 +08:00
|
|
|
|
2011-07-02 02:43:42 +08:00
|
|
|
var start = new Date().getTime();
|
2011-06-13 20:07:21 +08:00
|
|
|
|
2011-06-13 11:23:02 +08:00
|
|
|
try {
|
|
|
|
if (!_.isString(sql)) throw new Error("You must indicate a sql query");
|
|
|
|
var pg;
|
|
|
|
|
|
|
|
Step(
|
2011-06-20 21:39:12 +08:00
|
|
|
function getUser() {
|
2011-06-17 00:23:38 +08:00
|
|
|
oAuth.authorize(req, this);
|
2011-06-13 11:23:02 +08:00
|
|
|
},
|
|
|
|
function querySql(err, user_id){
|
|
|
|
if (err) throw err;
|
2011-07-06 00:31:01 +08:00
|
|
|
pg = new PSQL(user_id, database, limit, offset);
|
2011-06-13 11:23:02 +08:00
|
|
|
pg.query(sql, this);
|
|
|
|
},
|
|
|
|
function packageResults(err, result){
|
|
|
|
if (err) throw err;
|
2011-07-02 02:43:42 +08:00
|
|
|
var end = new Date().getTime();
|
|
|
|
res.send({'time' : ((end - start)/1000),
|
|
|
|
'total_rows': result.rows.length,
|
|
|
|
'rows' : result.rows});
|
2011-06-13 11:23:02 +08:00
|
|
|
},
|
|
|
|
function exceptionHandle(err, result){
|
2011-06-13 20:07:21 +08:00
|
|
|
handleException(res,err);
|
2011-06-13 11:23:02 +08:00
|
|
|
}
|
|
|
|
);
|
|
|
|
} catch (err) {
|
2011-06-13 20:07:21 +08:00
|
|
|
handleException(res,err);
|
2011-06-13 11:23:02 +08:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2011-06-13 20:07:21 +08:00
|
|
|
function handleException(res, err){
|
|
|
|
var msg = (global.settings.environment == 'development') ? {error:[err.message], stack: err.stack} : {error:[err.message]}
|
|
|
|
res.send(msg, 400);
|
|
|
|
}
|
|
|
|
|
2011-06-20 21:39:12 +08:00
|
|
|
//app.listen(global.settings.node_port);
|
|
|
|
|
|
|
|
// Think of putting it behind a cluster in production
|
|
|
|
module.exports = app;
|