Merge pull request #591 from CartoDB/copyto-post

Implement POST for copyto endpoint
This commit is contained in:
Daniel G. Aubert 2019-06-03 12:38:25 +02:00 committed by GitHub
commit 9e5cb0328d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 4 deletions

View File

@ -15,6 +15,7 @@ const Throttler = require('../services/throttler-stream');
const zlib = require('zlib');
const { PassThrough } = require('stream');
const handleQueryMiddleware = require('../middlewares/handle-query');
const bodyParserMiddleware = require('../middlewares/body-parser');
function CopyController(metadataBackend, userDatabaseService, userLimitsService, logger) {
this.metadataBackend = metadataBackend;
@ -44,6 +45,7 @@ CopyController.prototype.route = function (app) {
const copyToMiddlewares = endpointGroup => {
return [
bodyParserMiddleware(),
initializeProfilerMiddleware('copyto'),
userMiddleware(this.metadataBackend),
rateLimitsMiddleware(this.userLimitsService, endpointGroup),
@ -51,6 +53,7 @@ CopyController.prototype.route = function (app) {
connectionParamsMiddleware(this.userDatabaseService),
validateCopyQuery(),
handleQueryMiddleware(),
getFilenameParam(),
handleCopyTo(this.logger),
errorHandler(this.logger),
errorMiddleware()
@ -59,13 +62,12 @@ CopyController.prototype.route = function (app) {
app.post(`${base_url}/sql/copyfrom`, copyFromMiddlewares(RATE_LIMIT_ENDPOINTS_GROUPS.COPY_FROM));
app.get(`${base_url}/sql/copyto`, copyToMiddlewares(RATE_LIMIT_ENDPOINTS_GROUPS.COPY_TO));
app.post(`${base_url}/sql/copyto`, copyToMiddlewares(RATE_LIMIT_ENDPOINTS_GROUPS.COPY_TO));
};
function handleCopyTo (logger) {
return function handleCopyToMiddleware (req, res, next) {
const { sql, userDbParams, user } = res.locals;
const filename = req.query.filename || 'carto-sql-copyto.dmp';
const { sql, filename, userDbParams, user } = res.locals;
// it is not sure, nginx may choose not to compress the body
// but we want to know it and save it in the metrics
@ -167,9 +169,23 @@ function handleCopyFrom (logger) {
};
}
function getFilenameParam () {
return function getFilenameParamMiddleware (req, res, next) {
let filename = (req.query && req.query.filename) || (req.body && req.body.filename);
if (!filename) {
filename = 'carto-sql-copyto.dmp';
}
res.locals.filename = filename;
next();
};
}
function validateCopyQuery () {
return function validateCopyQueryMiddleware (req, res, next) {
const sql = req.query.q;
const sql = (req.query && req.query.q) || (req.body && req.body.q);
if (!sql) {
return next(new Error("SQL is missing"));

View File

@ -170,6 +170,46 @@ describe('copy-endpoints', function() {
});
});
it('should work with copyto endpoint and POST method', function(done){
assert.response(server, {
url: "/api/v1/sql/copyfrom?" + querystring.stringify({
q: "COPY copy_endpoints_test (id, name) FROM STDIN WITH (FORMAT CSV, DELIMITER ',', HEADER true)"
}),
data: fs.createReadStream(__dirname + '/../support/csv/copy_test_table.csv'),
headers: {
host: 'vizzuality.cartodb.com'
},
method: 'POST'
}, {}, function(err) {
assert.ifError(err);
assert.response(server, {
url: '/api/v1/sql/copyto',
data: querystring.stringify({
q: 'COPY copy_endpoints_test TO STDOUT',
filename: '/tmp/output.dmp'
}),
headers: {
host: 'vizzuality.cartodb.com',
'Content-Type': 'application/x-www-form-urlencoded'
},
method: 'POST'
}, {}, function(err, res) {
assert.ifError(err);
assert.strictEqual(
res.body,
'11\tPaul\t10\n12\tPeter\t10\n13\tMatthew\t10\n14\t\\N\t10\n15\tJames\t10\n16\tJohn\t10\n'
);
assert.equal(res.headers['content-disposition'], 'attachment; filename=%2Ftmp%2Foutput.dmp');
assert.equal(res.headers['content-type'], 'application/octet-stream');
done();
});
});
});
it('should fail with copyto endpoint and without sql', function(done){
assert.response(server, {
url: "/api/v1/sql/copyto?" + querystring.stringify({