mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-10 23:36:14 -05:00
Merge pull request #2677 from jaswilli/issue-2635
Add location header to response when new object is created
This commit is contained in:
commit
acd71d423e
5 changed files with 218 additions and 3 deletions
|
@ -55,6 +55,33 @@ function cacheInvalidationHeader(req, result) {
|
|||
return when(cacheInvalidate);
|
||||
}
|
||||
|
||||
// if api request results in the creation of a new object, construct
|
||||
// a Location: header that points to the new resource.
|
||||
//
|
||||
// arguments: request object, result object from the api call
|
||||
// returns: a promise that will be fulfilled with the location of the
|
||||
// resource
|
||||
function locationHeader(req, result) {
|
||||
var apiRoot = config.urlFor('api'),
|
||||
location,
|
||||
post,
|
||||
notification,
|
||||
parsedUrl = req._parsedUrl.pathname.replace(/\/$/, '').split('/'),
|
||||
endpoint = parsedUrl[4];
|
||||
|
||||
if (req.method === 'POST') {
|
||||
if (result.hasOwnProperty('posts')) {
|
||||
post = result.posts[0];
|
||||
location = apiRoot + '/posts/' + post.id + '/?status=' + post.status;
|
||||
} else if (endpoint === 'notifications') {
|
||||
notification = result;
|
||||
location = apiRoot + '/notifications/' + notification.id;
|
||||
}
|
||||
}
|
||||
|
||||
return when(location);
|
||||
}
|
||||
|
||||
// ### requestHandler
|
||||
// decorator for api functions which are called via an HTTP request
|
||||
// takes the API method and wraps it so that it gets data from the request and returns a sensible JSON response
|
||||
|
@ -72,7 +99,17 @@ requestHandler = function (apiMethod) {
|
|||
"X-Cache-Invalidate": header
|
||||
});
|
||||
}
|
||||
res.json(result || {});
|
||||
})
|
||||
.then(function () {
|
||||
return locationHeader(req, result).then(function (header) {
|
||||
if (header) {
|
||||
res.set({
|
||||
'Location': header
|
||||
});
|
||||
}
|
||||
|
||||
res.json(result || {});
|
||||
});
|
||||
});
|
||||
}, function (error) {
|
||||
var errorCode = error.code || 500,
|
||||
|
|
|
@ -40,7 +40,8 @@ notifications = {
|
|||
// ```
|
||||
add: function add(notification) {
|
||||
// **returns:** a promise for all notifications as a json object
|
||||
return when(notificationsStore.push(notification));
|
||||
notificationsStore.push(notification);
|
||||
return when(notification);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -103,7 +103,13 @@ function urlFor(context, data, absolute) {
|
|||
var urlPath = '/',
|
||||
secure,
|
||||
knownObjects = ['post', 'tag', 'user'],
|
||||
knownPaths = {'home': '/', 'rss': '/rss/'}; // this will become really big
|
||||
|
||||
// this will become really big
|
||||
knownPaths = {
|
||||
'home': '/',
|
||||
'rss': '/rss/',
|
||||
'api': '/ghost/api/v0.1'
|
||||
};
|
||||
|
||||
// Make data properly optional
|
||||
if (_.isBoolean(data)) {
|
||||
|
|
170
core/test/functional/routes/api/notifications_test.js
Normal file
170
core/test/functional/routes/api/notifications_test.js
Normal file
|
@ -0,0 +1,170 @@
|
|||
var supertest = require('supertest'),
|
||||
express = require('express'),
|
||||
should = require('should'),
|
||||
_ = require('lodash'),
|
||||
testUtils = require('../../../utils'),
|
||||
|
||||
ghost = require('../../../../../core'),
|
||||
|
||||
httpServer,
|
||||
request,
|
||||
agent;
|
||||
|
||||
describe('Notifications API', function () {
|
||||
var user = testUtils.DataGenerator.forModel.users[0],
|
||||
csrfToken = '';
|
||||
|
||||
before(function (done) {
|
||||
var app = express();
|
||||
|
||||
ghost({app: app}).then(function (_httpServer) {
|
||||
httpServer = _httpServer;
|
||||
|
||||
request = supertest.agent(app);
|
||||
|
||||
testUtils.clearData()
|
||||
.then(function () {
|
||||
return testUtils.initData();
|
||||
})
|
||||
.then(function () {
|
||||
return testUtils.insertDefaultFixtures();
|
||||
})
|
||||
.then(function () {
|
||||
request.get('/ghost/signin/')
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
var pattern_meta = /<meta.*?name="csrf-param".*?content="(.*?)".*?>/i;
|
||||
pattern_meta.should.exist;
|
||||
csrfToken = res.text.match(pattern_meta)[1];
|
||||
|
||||
setTimeout(function () {
|
||||
request.post('/ghost/signin/')
|
||||
.set('X-CSRF-Token', csrfToken)
|
||||
.send({email: user.email, password: user.password})
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
request.saveCookies(res);
|
||||
request.get('/ghost/')
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
csrfToken = res.text.match(pattern_meta)[1];
|
||||
done();
|
||||
});
|
||||
});
|
||||
}, 2000);
|
||||
});
|
||||
}, done);
|
||||
}).otherwise(function (e) {
|
||||
console.log('Ghost Error: ', e);
|
||||
console.log(e.stack);
|
||||
});
|
||||
});
|
||||
|
||||
after(function () {
|
||||
httpServer.close();
|
||||
});
|
||||
|
||||
describe('Add', function () {
|
||||
var newNotification = {
|
||||
type: 'info',
|
||||
message: 'test notification',
|
||||
status: 'persistent',
|
||||
id: 'add-test-1'
|
||||
};
|
||||
|
||||
it('creates a new notification', function (done) {
|
||||
request.post(testUtils.API.getApiQuery('notifications/'))
|
||||
.set('X-CSRF-Token', csrfToken)
|
||||
.send(newNotification)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
res.headers['location'].should.equal('/ghost/api/v0.1/notifications/' + newNotification.id);
|
||||
|
||||
var jsonResponse = res.body;
|
||||
|
||||
testUtils.API.checkResponse(jsonResponse, 'notification');
|
||||
|
||||
jsonResponse.type.should.equal(newNotification.type);
|
||||
jsonResponse.message.should.equal(newNotification.message);
|
||||
jsonResponse.status.should.equal(newNotification.status);
|
||||
jsonResponse.id.should.equal(newNotification.id);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Delete', function () {
|
||||
var newNotification = {
|
||||
type: 'info',
|
||||
message: 'test notification',
|
||||
status: 'persistent',
|
||||
id: 'delete-test-1'
|
||||
};
|
||||
|
||||
it('deletes a notification', function (done) {
|
||||
// create the notification that is to be deleted
|
||||
request.post(testUtils.API.getApiQuery('notifications/'))
|
||||
.set('X-CSRF-Token', csrfToken)
|
||||
.send(newNotification)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
var location = res.headers['location'];
|
||||
location.should.equal('/ghost/api/v0.1/notifications/' + newNotification.id);
|
||||
|
||||
var jsonResponse = res.body;
|
||||
|
||||
testUtils.API.checkResponse(jsonResponse, 'notification');
|
||||
|
||||
jsonResponse.type.should.equal(newNotification.type);
|
||||
jsonResponse.message.should.equal(newNotification.message);
|
||||
jsonResponse.status.should.equal(newNotification.status);
|
||||
jsonResponse.id.should.equal(newNotification.id);
|
||||
|
||||
// begin delete test
|
||||
request.del(location)
|
||||
.set('X-CSRF-Token', csrfToken)
|
||||
.expect(200)
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
|
||||
// a delete returns a JSON object containing all notifications
|
||||
// so we can make sure the notification we just deleted isn't
|
||||
// included
|
||||
var notifications = res.body;
|
||||
|
||||
var success;
|
||||
notifications.forEach(function (n) {
|
||||
success = n.id !== newNotification.id;
|
||||
});
|
||||
|
||||
success.should.be.true;
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -334,6 +334,7 @@ describe('Post API', function () {
|
|||
|
||||
res.should.be.json;
|
||||
var draftPost = res.body;
|
||||
res.headers['location'].should.equal('/ghost/api/v0.1/posts/' + draftPost.posts[0].id + '/?status=draft');
|
||||
draftPost.posts.should.exist;
|
||||
draftPost.posts.length.should.be.above(0);
|
||||
draftPost.posts[0].title.should.eql(newTitle);
|
||||
|
|
Loading…
Add table
Reference in a new issue