mirror of
https://github.com/strapi/strapi.git
synced 2025-11-01 18:33:55 +00:00
Add responses hook, fix conflicts with last PR
This commit is contained in:
commit
f335d74f3f
@ -21,7 +21,7 @@ module.exports = function (strapi) {
|
||||
|
||||
initialize: function (cb) {
|
||||
if (strapi.config.gzip === true) {
|
||||
strapi.app.use(strapi.middlewares.gzip());
|
||||
strapi.app.use(strapi.middlewares.compress());
|
||||
}
|
||||
|
||||
cb();
|
||||
|
||||
24
lib/configuration/hooks/responses/index.js
Normal file
24
lib/configuration/hooks/responses/index.js
Normal file
@ -0,0 +1,24 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function () {
|
||||
const hook = {
|
||||
|
||||
/**
|
||||
* Default options
|
||||
*/
|
||||
|
||||
defaults: {
|
||||
enabled: true
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize the hook
|
||||
*/
|
||||
|
||||
initialize: function (cb) {
|
||||
cb();
|
||||
}
|
||||
};
|
||||
|
||||
return hook;
|
||||
};
|
||||
22
lib/configuration/hooks/responses/policies/responses.js
Normal file
22
lib/configuration/hooks/responses/policies/responses.js
Normal file
@ -0,0 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
// Public node modules.
|
||||
const _ = require('lodash');
|
||||
|
||||
// Local utilities.
|
||||
const responses = require('../responses/index');
|
||||
|
||||
/**
|
||||
* Policy used to add responses in the `this.response` object.
|
||||
*/
|
||||
|
||||
module.exports = function * (next) {
|
||||
// Add the custom responses to the `this.response` object.
|
||||
this.response = _.merge(this.response, responses);
|
||||
|
||||
yield next;
|
||||
};
|
||||
18
lib/configuration/hooks/responses/responses/badRequest.js
Normal file
18
lib/configuration/hooks/responses/responses/badRequest.js
Normal file
@ -0,0 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Default `badRequest` response.
|
||||
*/
|
||||
|
||||
module.exports = function * badRequest(data) {
|
||||
// Set the status.
|
||||
this.status = 400;
|
||||
|
||||
// Delete the `data` object if the app is used in production environment.
|
||||
if (strapi.config.environment === 'production') {
|
||||
data = undefined;
|
||||
}
|
||||
|
||||
// Finally send the response.
|
||||
this.body = data;
|
||||
};
|
||||
13
lib/configuration/hooks/responses/responses/created.js
Normal file
13
lib/configuration/hooks/responses/responses/created.js
Normal file
@ -0,0 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Default `created` response.
|
||||
*/
|
||||
|
||||
module.exports = function * created(data) {
|
||||
// Set the status.
|
||||
this.status = 201;
|
||||
|
||||
// Finally send the response.
|
||||
this.body = data;
|
||||
};
|
||||
18
lib/configuration/hooks/responses/responses/forbidden.js
Normal file
18
lib/configuration/hooks/responses/responses/forbidden.js
Normal file
@ -0,0 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Default `forbidden` response.
|
||||
*/
|
||||
|
||||
module.exports = function * forbidden(data) {
|
||||
// Set the status.
|
||||
this.status = 403;
|
||||
|
||||
// Delete the `data` object if the app is used in production environment.
|
||||
if (strapi.config.environment === 'production') {
|
||||
data = undefined;
|
||||
}
|
||||
|
||||
// Finally send the response.
|
||||
this.body = data;
|
||||
};
|
||||
14
lib/configuration/hooks/responses/responses/index.js
Normal file
14
lib/configuration/hooks/responses/responses/index.js
Normal file
@ -0,0 +1,14 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Index of the responses hook responses.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
badRequest: require('./badRequest'),
|
||||
created: require('./created'),
|
||||
forbidden: require('./forbidden'),
|
||||
notFound: require('./notFound'),
|
||||
ok: require('./ok'),
|
||||
serverError: require('./serverError')
|
||||
};
|
||||
18
lib/configuration/hooks/responses/responses/notFound.js
Normal file
18
lib/configuration/hooks/responses/responses/notFound.js
Normal file
@ -0,0 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Default `notFound` response.
|
||||
*/
|
||||
|
||||
module.exports = function * notFound(data) {
|
||||
// Set the status.
|
||||
this.status = 404;
|
||||
|
||||
// Delete the `data` object if the app is used in production environment.
|
||||
if (strapi.config.environment === 'production') {
|
||||
data = undefined;
|
||||
}
|
||||
|
||||
// Finally send the response.
|
||||
this.body = data;
|
||||
};
|
||||
13
lib/configuration/hooks/responses/responses/ok.js
Normal file
13
lib/configuration/hooks/responses/responses/ok.js
Normal file
@ -0,0 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Default `ok` response.
|
||||
*/
|
||||
|
||||
module.exports = function sendOk(data) {
|
||||
// Set the status.
|
||||
this.status = 200;
|
||||
|
||||
// Finally send the response.
|
||||
this.body = data;
|
||||
};
|
||||
18
lib/configuration/hooks/responses/responses/serverError.js
Normal file
18
lib/configuration/hooks/responses/responses/serverError.js
Normal file
@ -0,0 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Default `serverError` response.
|
||||
*/
|
||||
|
||||
module.exports = function * serverError(data) {
|
||||
// Set the status.
|
||||
this.status = 500;
|
||||
|
||||
// Delete the `data` object if the app is used in production environment.
|
||||
if (strapi.config.environment === 'production') {
|
||||
data = undefined;
|
||||
}
|
||||
|
||||
// Finally send the response.
|
||||
this.body = data;
|
||||
};
|
||||
@ -40,10 +40,10 @@
|
||||
"koa": "~1.1.2",
|
||||
"koa-bodyparser": "~2.0.1",
|
||||
"koa-compose": "~2.3.0",
|
||||
"koa-compress": "^1.0.9",
|
||||
"koa-cors": "~0.0.16",
|
||||
"koa-favicon": "~1.2.0",
|
||||
"koa-graphql": "^0.4.5",
|
||||
"koa-gzip": "~0.1.0",
|
||||
"koa-i18n": "~1.2.0",
|
||||
"koa-ip": "~0.1.0",
|
||||
"koa-load-middlewares": "~1.0.0",
|
||||
|
||||
262
test/middlewares/compress/index.js
Normal file
262
test/middlewares/compress/index.js
Normal file
@ -0,0 +1,262 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
const should = require('should');
|
||||
const request = require('supertest');
|
||||
|
||||
const assert = require('assert');
|
||||
const http = require('http');
|
||||
const Stream = require('stream');
|
||||
const crypto = require('crypto');
|
||||
const path = require('path');
|
||||
|
||||
const strapi = require('../../..');
|
||||
const Koa = strapi.server;
|
||||
|
||||
describe('compress', function() {
|
||||
|
||||
describe('strapi.middlewares.compress()', function() {
|
||||
it('should work with no options', function() {
|
||||
strapi.middlewares.compress();
|
||||
});
|
||||
});
|
||||
|
||||
const buffer = crypto.randomBytes(1024);
|
||||
const string = buffer.toString('hex');
|
||||
|
||||
function* sendString(next) {
|
||||
this.body = string
|
||||
}
|
||||
|
||||
function* sendBuffer(next) {
|
||||
this.compress = true;
|
||||
this.body = buffer
|
||||
}
|
||||
|
||||
it('should compress strings', function(done) {
|
||||
|
||||
let app = strapi.server();
|
||||
app.use(strapi.middlewares.compress());
|
||||
app.use(sendString);
|
||||
|
||||
request(app.listen()).get('/').expect(200).end(function(err, res) {
|
||||
if (err) return done(err);
|
||||
|
||||
//res.should.have.header('Content-Encoding', 'gzip')
|
||||
res.should.have.header('Transfer-Encoding', 'chunked');
|
||||
res.should.have.header('Vary', 'Accept-Encoding');
|
||||
res.headers.should.not.have.property('content-length');
|
||||
res.text.should.equal(string);
|
||||
|
||||
done()
|
||||
})
|
||||
});
|
||||
|
||||
it('should not compress strings below threshold', function(done) {
|
||||
|
||||
let app = strapi.server();
|
||||
app.use(strapi.middlewares.compress({
|
||||
threshold: '1mb'
|
||||
}));
|
||||
app.use(sendString);
|
||||
|
||||
request(app.listen()).get('/').expect(200).end(function(err, res) {
|
||||
if (err) return done(err);
|
||||
|
||||
res.should.have.header('Content-Length', '2048');
|
||||
res.should.have.header('Vary', 'Accept-Encoding');
|
||||
res.headers.should.not.have.property('content-encoding');
|
||||
res.headers.should.not.have.property('transfer-encoding');
|
||||
res.text.should.equal(string);
|
||||
|
||||
done()
|
||||
})
|
||||
});
|
||||
|
||||
it('should compress JSON body', function(done) {
|
||||
var jsonBody = {
|
||||
'status': 200,
|
||||
'message': 'ok',
|
||||
'data': string
|
||||
};
|
||||
|
||||
let app = strapi.server();
|
||||
app.use(strapi.middlewares.compress());
|
||||
app.use(function*(next) {
|
||||
this.body = jsonBody
|
||||
});
|
||||
|
||||
request(app.listen()).get('/').expect(200).end(function(err, res) {
|
||||
if (err)
|
||||
return done(err);
|
||||
|
||||
res.should.have.header('Transfer-Encoding', 'chunked');
|
||||
res.should.have.header('Vary', 'Accept-Encoding');
|
||||
res.headers.should.not.have.property('content-length');
|
||||
res.text.should.equal(JSON.stringify(jsonBody));
|
||||
|
||||
done()
|
||||
})
|
||||
});
|
||||
|
||||
it('should not compress JSON body below threshold', function(done) {
|
||||
var jsonBody = {
|
||||
'status': 200,
|
||||
'message': 'ok'
|
||||
};
|
||||
|
||||
let app = strapi.server();
|
||||
app.use(strapi.middlewares.compress());
|
||||
app.use(function* sendJSON(next) {
|
||||
this.body = jsonBody
|
||||
});
|
||||
|
||||
request(app.listen()).get('/').expect(200).end(function(err, res) {
|
||||
if (err)
|
||||
return done(err);
|
||||
|
||||
res.should.have.header('Vary', 'Accept-Encoding');
|
||||
res.headers.should.not.have.property('content-encoding');
|
||||
res.headers.should.not.have.property('transfer-encoding');
|
||||
res.text.should.equal(JSON.stringify(jsonBody));
|
||||
|
||||
done()
|
||||
})
|
||||
});
|
||||
|
||||
it('should compress buffers', function(done) {
|
||||
let app = strapi.server();
|
||||
app.use(strapi.middlewares.compress());
|
||||
app.use(sendBuffer);
|
||||
|
||||
request(app.listen()).get('/').expect(200).end(function(err, res) {
|
||||
if (err)
|
||||
return done(err);
|
||||
|
||||
//res.should.have.header('Content-Encoding', 'gzip')
|
||||
res.should.have.header('Transfer-Encoding', 'chunked');
|
||||
res.should.have.header('Vary', 'Accept-Encoding');
|
||||
res.headers.should.not.have.property('content-length');
|
||||
|
||||
done()
|
||||
})
|
||||
});
|
||||
|
||||
it('should compress streams', function(done) {
|
||||
let app = strapi.server();
|
||||
app.use(strapi.middlewares.compress());
|
||||
|
||||
app.use(function*(next) {
|
||||
this.type = 'application/javascript';
|
||||
this.body = fs.createReadStream(path.join(__dirname, 'index.js'))
|
||||
});
|
||||
|
||||
request(app.listen()).get('/').expect(200).end(function(err, res) {
|
||||
if (err)
|
||||
return done(err);
|
||||
|
||||
//res.should.have.header('Content-Encoding', 'gzip')
|
||||
res.should.have.header('Transfer-Encoding', 'chunked');
|
||||
res.should.have.header('Vary', 'Accept-Encoding');
|
||||
res.headers.should.not.have.property('content-length');
|
||||
|
||||
done()
|
||||
})
|
||||
});
|
||||
|
||||
it('should compress when this.compress === true', function(done) {
|
||||
let app = strapi.server();
|
||||
app.use(strapi.middlewares.compress());
|
||||
app.use(sendBuffer);
|
||||
|
||||
request(app.listen()).get('/').expect(200).end(function(err, res) {
|
||||
if (err)
|
||||
return done(err);
|
||||
|
||||
//res.should.have.header('Content-Encoding', 'gzip')
|
||||
res.should.have.header('Transfer-Encoding', 'chunked');
|
||||
res.should.have.header('Vary', 'Accept-Encoding');
|
||||
res.headers.should.not.have.property('content-length');
|
||||
|
||||
done()
|
||||
})
|
||||
});
|
||||
|
||||
it('should not compress when this.compress === false', function(done) {
|
||||
let app = strapi.server();
|
||||
app.use(strapi.middlewares.compress());
|
||||
app.use(function*(next) {
|
||||
this.compress = false;
|
||||
this.body = buffer
|
||||
});
|
||||
|
||||
request(app.listen()).get('/').expect(200).end(function(err, res) {
|
||||
if (err)
|
||||
return done(err);
|
||||
|
||||
res.should.have.header('Content-Length', '1024');
|
||||
res.should.have.header('Vary', 'Accept-Encoding');
|
||||
res.headers.should.not.have.property('content-encoding');
|
||||
res.headers.should.not.have.property('transfer-encoding');
|
||||
|
||||
done()
|
||||
})
|
||||
});
|
||||
|
||||
it('should not compress HEAD requests', function(done) {
|
||||
let app = strapi.server();
|
||||
app.use(strapi.middlewares.compress());
|
||||
app.use(sendString);
|
||||
|
||||
request(app.listen()).head('/').expect(200).expect('', function(err, res) {
|
||||
if (err)
|
||||
return done(err);
|
||||
|
||||
res.headers.should.not.have.property('content-encoding');
|
||||
|
||||
done()
|
||||
})
|
||||
});
|
||||
|
||||
it('should not crash even if accept-encoding: sdch', function(done) {
|
||||
let app = strapi.server();
|
||||
app.use(strapi.middlewares.compress());
|
||||
app.use(sendBuffer);
|
||||
|
||||
request(app.listen()).get('/').set('Accept-Encoding', 'sdch, gzip, deflate').expect(200, done)
|
||||
});
|
||||
|
||||
it('should not crash if no accept-encoding is sent', function(done) {
|
||||
let app = strapi.server();
|
||||
app.use(strapi.middlewares.compress());
|
||||
app.use(sendBuffer);
|
||||
|
||||
request(app.listen()).get('/').expect(200, done)
|
||||
});
|
||||
|
||||
it('should not crash if a type does not pass the filter', function(done) {
|
||||
let app = strapi.server();
|
||||
app.use(strapi.middlewares.compress());
|
||||
app.use(function*() {
|
||||
this.type = 'image/png';
|
||||
this.body = new Buffer(2048)
|
||||
});
|
||||
|
||||
request(app.listen()).get('/').expect(200, done)
|
||||
});
|
||||
|
||||
it('should not compress when transfer-encoding is already set', function(done) {
|
||||
let app = strapi.server();
|
||||
app.use(strapi.middlewares.compress({
|
||||
threshold: 0
|
||||
}));
|
||||
app.use(function*() {
|
||||
this.set('Content-Encoding', 'identity');
|
||||
this.type = 'text';
|
||||
this.body = 'asdf'
|
||||
});
|
||||
|
||||
request(app.listen()).get('/').expect('asdf', done)
|
||||
});
|
||||
});
|
||||
@ -1,172 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
const should = require('should');
|
||||
const request = require('supertest');
|
||||
|
||||
const strapi = require('../../..');
|
||||
const Koa = strapi.server;
|
||||
|
||||
describe('gzip', function () {
|
||||
const options = {};
|
||||
const BODY = 'foo bar string, foo bar string, foo bar string, foo bar string, \
|
||||
foo bar string, foo bar string, foo bar string, foo bar string, foo bar string, foo bar string, \
|
||||
foo bar string, foo bar string, foo bar string, foo bar string, foo bar string, foo bar string';
|
||||
|
||||
let app = strapi.server();
|
||||
|
||||
app.use(strapi.middlewares.gzip(options));
|
||||
app.use(strapi.middlewares.gzip(options));
|
||||
app.use(function * (next) {
|
||||
if (this.url === '/404') {
|
||||
return yield next;
|
||||
}
|
||||
if (this.url === '/small') {
|
||||
return this.body = 'foo bar string';
|
||||
}
|
||||
if (this.url === '/string') {
|
||||
return this.body = BODY;
|
||||
}
|
||||
if (this.url === '/buffer') {
|
||||
return this.body = new Buffer(BODY);
|
||||
}
|
||||
if (this.url === '/object') {
|
||||
return this.body = {
|
||||
foo: BODY
|
||||
};
|
||||
}
|
||||
if (this.url === '/number') {
|
||||
return this.body = 1984;
|
||||
}
|
||||
if (this.url === '/stream') {
|
||||
const stat = fs.statSync(__filename);
|
||||
this.set('content-length', stat.size);
|
||||
return this.body = fs.createReadStream(__filename);
|
||||
}
|
||||
if (this.url === '/exists-encoding') {
|
||||
this.set('content-encoding', 'gzip');
|
||||
return this.body = new Buffer('gzip');
|
||||
}
|
||||
if (this.url === '/error') {
|
||||
return this.throw(new Error('mock error'));
|
||||
}
|
||||
});
|
||||
|
||||
before(function (done) {
|
||||
app = app.listen(0, done);
|
||||
});
|
||||
|
||||
describe('strapi.middlewares.gzip()', function () {
|
||||
it('should work with no options', function () {
|
||||
strapi.middlewares.gzip();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when status 200 and request accept-encoding include gzip', function () {
|
||||
it('should return gzip string body', function (done) {
|
||||
request(app)
|
||||
.get('/string')
|
||||
.set('Accept-Encoding', 'gzip,deflate,sdch')
|
||||
.expect(200)
|
||||
.expect('content-encoding', 'gzip')
|
||||
.expect('content-length', '46')
|
||||
.expect(BODY, done);
|
||||
});
|
||||
|
||||
it('should return raw string body if body smaller than minLength', function (done) {
|
||||
request(app)
|
||||
.get('/small')
|
||||
.set('Accept-Encoding', 'gzip,deflate,sdch')
|
||||
.expect(200)
|
||||
.expect('content-length', '14')
|
||||
.expect('foo bar string', function (err, res) {
|
||||
should.not.exist(err);
|
||||
should.not.exist(res.headers['content-encoding']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return gzip buffer body', function (done) {
|
||||
request(app)
|
||||
.get('/buffer')
|
||||
.set('Accept-Encoding', 'gzip,deflate,sdch')
|
||||
.expect(200)
|
||||
.expect('content-encoding', 'gzip')
|
||||
.expect('content-length', '46')
|
||||
.expect(BODY, done);
|
||||
});
|
||||
|
||||
it('should return gzip stream body', function (done) {
|
||||
request(app)
|
||||
.get('/stream')
|
||||
.set('Accept-Encoding', 'gzip,deflate,sdch')
|
||||
.expect(200)
|
||||
.expect('Content-Encoding', 'gzip')
|
||||
.expect(fs.readFileSync(__filename, 'utf8'),
|
||||
function (err, res) {
|
||||
should.not.exist(err);
|
||||
should.not.exist(res.headers['content-length']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should return gzip json body', function (done) {
|
||||
request(app)
|
||||
.get('/object')
|
||||
.set('Accept-Encoding', 'gzip,deflate,sdch')
|
||||
.expect(200)
|
||||
.expect('Content-Encoding', 'gzip')
|
||||
.expect('content-length', '52')
|
||||
.expect({
|
||||
foo: BODY
|
||||
}, done);
|
||||
});
|
||||
|
||||
it('should return number body', function (done) {
|
||||
request(app)
|
||||
.get('/number')
|
||||
.set('Accept-Encoding', 'gzip,deflate,sdch')
|
||||
.expect('content-length', '4')
|
||||
.expect(200, function (err, res) {
|
||||
should.not.exist(err);
|
||||
res.body.should.equal(1984);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when status 200 and request accept-encoding exclude gzip', function () {
|
||||
it('should return raw body', function (done) {
|
||||
request(app)
|
||||
.get('/string')
|
||||
.set('Accept-Encoding', 'deflate,sdch')
|
||||
.expect(200)
|
||||
.expect('content-length', '' + BODY.length)
|
||||
.expect(BODY,
|
||||
function (err, res) {
|
||||
should.not.exist(err);
|
||||
should.not.exist(res.headers['content-encoding']);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when status non 200', function () {
|
||||
it('should return 404', function (done) {
|
||||
request(app)
|
||||
.get('/404')
|
||||
.set('Accept-Encoding', 'gzip,deflate,sdch')
|
||||
.expect(404)
|
||||
.expect('Not Found', done);
|
||||
});
|
||||
|
||||
it('should return 500', function (done) {
|
||||
request(app)
|
||||
.get('/error')
|
||||
.set('Accept-Encoding', 'gzip,deflate,sdch')
|
||||
.expect(500)
|
||||
.expect('Internal Server Error', done);
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user