Skip to content

Commit 340192c

Browse files
committed
Cache invalidation for post update
closes #2833 - Handle status change of post
1 parent 1ae98df commit 340192c

File tree

3 files changed

+104
-14
lines changed

3 files changed

+104
-14
lines changed

core/server/api/index.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,24 +55,25 @@ cacheInvalidationHeader = function (req, result) {
5555
cacheInvalidate,
5656
jsonResult = result.toJSON ? result.toJSON() : result,
5757
post,
58-
wasPublished,
59-
wasDeleted;
58+
hasStatusChanged,
59+
wasDeleted,
60+
wasPublishedUpdated;
6061

6162
if (method === 'POST' || method === 'PUT' || method === 'DELETE') {
6263
if (endpoint === 'settings' || endpoint === 'users' || endpoint === 'db') {
6364
cacheInvalidate = '/*';
6465
} else if (endpoint === 'posts') {
6566
post = jsonResult.posts[0];
66-
wasPublished = post.statusChanged && post.status === 'published';
67+
hasStatusChanged = post.statusChanged;
6768
wasDeleted = method === 'DELETE';
69+
// Invalidate cache when post was updated but not when post is draft
70+
wasPublishedUpdated = method === 'PUT' && post.status === 'published';
6871

6972
// Remove the statusChanged value from the response
70-
if (post.statusChanged) {
71-
delete post.statusChanged;
72-
}
73+
delete post.statusChanged;
7374

7475
// Don't set x-cache-invalidate header for drafts
75-
if (wasPublished || wasDeleted) {
76+
if (hasStatusChanged || wasDeleted || wasPublishedUpdated) {
7677
cacheInvalidate = '/, /page/*, /rss/, /rss/*, /tag/*';
7778
if (id && post.slug) {
7879
return config.urlForPost(settings, post).then(function (postUrl) {

core/server/api/posts.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ posts = {
114114
if (result) {
115115
var post = result.toJSON();
116116

117-
// If previously was not published and now is, signal the change
117+
// If previously was not published and now is (or vice versa), signal the change
118+
post.statusChanged = false;
118119
if (result.updated('status') !== result.get('status')) {
119120
post.statusChanged = true;
120121
}

core/test/functional/routes/api/posts_test.js

Lines changed: 94 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,8 @@ describe('Post API', function () {
411411
}
412412

413413
var updatedPost = res.body;
414-
_.has(res.headers, 'x-cache-invalidate').should.equal(false);
414+
// Require cache invalidation when post was updated and published
415+
_.has(res.headers, 'x-cache-invalidate').should.equal(true);
415416
res.should.be.json;
416417

417418
updatedPost.should.exist;
@@ -458,7 +459,7 @@ describe('Post API', function () {
458459
}
459460

460461
var putBody = res.body;
461-
_.has(res.headers, 'x-cache-invalidate').should.equal(false);
462+
_.has(res.headers, 'x-cache-invalidate').should.equal(true);
462463
res.should.be.json;
463464
putBody.should.exist;
464465
putBody.posts[0].title.should.eql(changedValue);
@@ -469,6 +470,93 @@ describe('Post API', function () {
469470
});
470471
});
471472

473+
it('can edit a new draft and update post', function (done) {
474+
var newTitle = 'My Post',
475+
newTagName = 'My Tag',
476+
publishedState = 'published',
477+
newTag = {id: null, name: newTagName},
478+
newPost = {posts: [{status: 'draft', title: newTitle, markdown: 'my post', tags: [newTag]}]};
479+
480+
request.post(testUtils.API.getApiQuery('posts/?include=tags'))
481+
.set('X-CSRF-Token', csrfToken)
482+
.send(newPost)
483+
.expect(201)
484+
.end(function (err, res) {
485+
if (err) {
486+
return done(err);
487+
}
488+
489+
res.should.be.json;
490+
var draftPost = res.body;
491+
res.headers['location'].should.equal('/ghost/api/v0.1/posts/' + draftPost.posts[0].id + '/?status=draft');
492+
draftPost.posts.should.exist;
493+
draftPost.posts.length.should.be.above(0);
494+
draftPost.posts[0].title.should.eql(newTitle);
495+
testUtils.API.checkResponse(draftPost.posts[0], 'post');
496+
497+
draftPost.posts[0].title = 'Vote for Casper in red';
498+
499+
request.put(testUtils.API.getApiQuery('posts/' + draftPost.posts[0].id + '/?include=tags'))
500+
.set('X-CSRF-Token', csrfToken)
501+
.send(draftPost)
502+
.expect(200)
503+
.end(function (err, res) {
504+
if (err) {
505+
return done(err);
506+
}
507+
508+
// Updating a draft should not send x-cache-invalidate headers
509+
_.has(res.headers, 'x-cache-invalidate').should.equal(false);
510+
done();
511+
});
512+
});
513+
});
514+
515+
it('can edit a new published post and unpublish', function (done) {
516+
var newTitle = 'My Post',
517+
newTagName = 'My Tag',
518+
draftState = 'draft',
519+
newTag = {id: null, name: newTagName},
520+
newPost = {posts: [{status: 'published', title: newTitle, markdown: 'my post', tags: [newTag]}]};
521+
522+
request.post(testUtils.API.getApiQuery('posts/?include=tags'))
523+
.set('X-CSRF-Token', csrfToken)
524+
.send(newPost)
525+
.expect(201)
526+
.end(function (err, res) {
527+
if (err) {
528+
return done(err);
529+
}
530+
531+
res.should.be.json;
532+
var draftPost = res.body;
533+
res.headers['location'].should.equal('/ghost/api/v0.1/posts/' + draftPost.posts[0].id + '/?status=published');
534+
draftPost.posts.should.exist;
535+
draftPost.posts.length.should.be.above(0);
536+
draftPost.posts[0].title.should.eql(newTitle);
537+
testUtils.API.checkResponse(draftPost.posts[0], 'post');
538+
539+
draftPost.posts[0].title = 'Vote for Casper in red';
540+
draftPost.posts[0].status = draftState;
541+
542+
request.put(testUtils.API.getApiQuery('posts/' + draftPost.posts[0].id + '/?include=tags'))
543+
.set('X-CSRF-Token', csrfToken)
544+
.send(draftPost)
545+
.expect(200)
546+
.end(function (err, res) {
547+
if (err) {
548+
return done(err);
549+
}
550+
551+
552+
var unpublishedPost = res.body;
553+
// Unpublishing a post should send x-cache-invalidate headers
554+
_.has(res.headers, 'x-cache-invalidate').should.equal(true);
555+
done();
556+
});
557+
});
558+
});
559+
472560
it('can change a post to a static page', function (done) {
473561
request.get(testUtils.API.getApiQuery('posts/1/?include=tags'))
474562
.end(function (err, res) {
@@ -492,7 +580,7 @@ describe('Post API', function () {
492580
}
493581

494582
var putBody = res.body;
495-
_.has(res.headers, 'x-cache-invalidate').should.equal(false);
583+
_.has(res.headers, 'x-cache-invalidate').should.equal(true);
496584
res.should.be.json;
497585
putBody.should.exist;
498586
putBody.posts[0].page.should.eql(changedValue);
@@ -527,7 +615,7 @@ describe('Post API', function () {
527615

528616
var putBody = res.body;
529617

530-
_.has(res.headers, 'x-cache-invalidate').should.equal(false);
618+
_.has(res.headers, 'x-cache-invalidate').should.equal(true);
531619
res.should.be.json;
532620
putBody.should.exist;
533621
putBody.posts[0].page.should.eql(changedValue);
@@ -615,7 +703,7 @@ describe('Post API', function () {
615703
}
616704

617705
var putBody = res.body;
618-
_.has(res.headers, 'x-cache-invalidate').should.equal(false);
706+
_.has(res.headers, 'x-cache-invalidate').should.equal(true);
619707
res.should.be.json;
620708
putBody.should.exist;
621709
putBody.posts.should.exist;
@@ -843,7 +931,7 @@ describe('Post API', function () {
843931
yyyy = today.getFullYear(),
844932
postLink = '/' + yyyy + '/' + mm + '/' + dd + '/' + putBody.posts[0].slug + '/';
845933

846-
_.has(res.headers, 'x-cache-invalidate').should.equal(false);
934+
_.has(res.headers, 'x-cache-invalidate').should.equal(true);
847935
res.should.be.json;
848936
putBody.should.exist;
849937
putBody.posts[0].title.should.eql(changedValue);

0 commit comments

Comments
 (0)