make wellformed CSV and stream back to browser. #9

This commit is contained in:
Simon Tokumine 2012-04-13 15:37:09 +01:00
parent 2f87b54101
commit 4cbdf62cc2
3 changed files with 42 additions and 25 deletions

View File

@ -12,7 +12,6 @@
// - sql only, provided the subdomain exists in CartoDB and the table's sharing options are public
//
// eg. vizzuality.cartodb.com/api/v1/?sql=SELECT * from my_table
var express = require('express')
, app = express.createServer(
express.logger({
@ -20,6 +19,7 @@ var express= require('express')
format: '[:date] :req[X-Real-IP] \033[90m:method\033[0m \033[36m:req[Host]:url\033[0m \033[90m:status :response-time ms -> :res[Content-Type]\033[0m'
}))
, Step = require('step')
, csv = require('csv')
, Meta = require(global.settings.app_root + '/app/models/metadata')
, oAuth = require(global.settings.app_root + '/app/models/oauth')
, PSQL = require(global.settings.app_root + '/app/models/psql')
@ -87,6 +87,23 @@ function handleQuery(req, res){
pg.query(sql, this);
},
function setHeaders(err, result){
if (err) throw err;
// configure headers for geojson/CSV
res.header("Content-Disposition", getContentDisposition(format));
res.header("Content-Type", getContentType(format));
// allow cross site post
setCrossDomain(res);
// set cache headers
res.header('Last-Modified', new Date().toUTCString());
res.header('Cache-Control', 'no-cache,max-age=3600,must-revalidate, public');
res.header('X-Cache-Channel', database);
return result;
},
function packageResults(err, result){
if (err) throw err;
@ -107,18 +124,6 @@ function handleQuery(req, res){
function sendResults(err, out){
if (err) throw err;
// configure headers for geojson
res.header("Content-Disposition", getContentDisposition(format));
res.header("Content-Type", getContentType(format));
// allow cross site post
setCrossDomain(res);
// set cache headers
res.header('Last-Modified', new Date().toUTCString());
res.header('Cache-Control', 'no-cache,max-age=3600,must-revalidate, public');
res.header('X-Cache-Channel', database);
// return to browser
res.send(out);
},
@ -161,16 +166,14 @@ function toGeoJSON(data, res, callback){
function toCSV(data, res, callback){
try{
var out = ""
if (data.rows.length > 0){
out = out + _.keys(data.rows[0]).join(',') + '\n';
_.each(data.rows, function(ele){
out = out + _.values(ele).join(',') + '\n';
});
}
// pull out keys for column headers
var columns = _.keys(data.rows[0]);
// return payload
callback(null, out);
// stream the csv out over http
csv()
.from(data.rows)
.toStream(res, {end: true, columns: columns, header: true});
return true;
} catch (err) {
callback(err,null);
}

View File

@ -19,7 +19,8 @@
"hiredis": "*",
"step": "0.0.x",
"oauth-client": "0.2.0",
"node-uuid":"1.3.3"
"node-uuid":"1.3.3",
"csv":"0.0.13"
},
"devDependencies": {
"expresso": "0.8.x"

View File

@ -166,7 +166,20 @@ tests['GET /api/v1/sql as csv'] = function(){
},{
status: 200
}, function(res){
var body = "cartodb_id,geom\n1,SRID=4326;POINT(-3.699732 40.423012)\n"
var body = "cartodb_id,geom\r\n1,SRID=4326;POINT(-3.699732 40.423012)";
assert.equal(body, res.body);
});
};
tests['GET /api/v1/sql as csv, properly escaped'] = function(){
assert.response(app, {
url: '/api/v1/sql?q=SELECT%20cartodb_id,%20address%20FROM%20untitle_table_4%20LIMIT%201&format=csv',
headers: {host: 'vizzuality.cartodb.com'},
method: 'GET'
},{
status: 200
}, function(res){
var body = 'cartodb_id,address\r\n1,"Calle de Pérez Galdós 9, Madrid, Spain"';
assert.equal(body, res.body);
});
};