From 6ac9c7d2315e19f3d90702edd119f139ceccc569 Mon Sep 17 00:00:00 2001 From: Lay Date: Thu, 8 Apr 2021 16:28:57 +0800 Subject: [PATCH] pref: RSS/Atom (#1342) * 1.Add the lastBuildDate in RSS. 2.Add the updated in Atom. 3.Change the date format in RSS and Atom 4.Add the lastModified in the response header. * fix code style --- .../content/ContentFeedController.java | 64 +++++++++++++++---- .../resources/templates/common/web/atom.ftl | 2 +- .../resources/templates/common/web/rss.ftl | 4 +- 3 files changed, 57 insertions(+), 13 deletions(-) diff --git a/src/main/java/run/halo/app/controller/content/ContentFeedController.java b/src/main/java/run/halo/app/controller/content/ContentFeedController.java index d67201715..822f992de 100644 --- a/src/main/java/run/halo/app/controller/content/ContentFeedController.java +++ b/src/main/java/run/halo/app/controller/content/ContentFeedController.java @@ -5,7 +5,12 @@ import static org.springframework.data.domain.Sort.Direction.DESC; import freemarker.template.Template; import freemarker.template.TemplateException; import java.io.IOException; +import java.sql.Timestamp; +import java.text.SimpleDateFormat; import java.util.List; +import java.util.Locale; +import java.util.OptionalLong; +import javax.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.RegExUtils; import org.springframework.data.domain.Page; @@ -47,6 +52,8 @@ public class ContentFeedController { private static final String XML_MEDIA_TYPE = MediaType.APPLICATION_XML_VALUE + UTF_8_SUFFIX; + private static final String LAST_MODIFIED_HEADER = "Last-Modified"; + private final PostService postService; private final CategoryService categoryService; @@ -70,7 +77,7 @@ public class ContentFeedController { } /** - * Get post rss + * Get post rss. * * @param model model * @return rss xml content @@ -79,8 +86,13 @@ public class ContentFeedController { */ @GetMapping(value = {"feed", "feed.xml", "rss", "rss.xml"}, produces = XML_MEDIA_TYPE) @ResponseBody - public String feed(Model model) throws IOException, TemplateException { - model.addAttribute("posts", buildPosts(buildPostPageable(optionService.getRssPageSize()))); + public String feed(Model model, HttpServletResponse response) + throws IOException, TemplateException { + List posts = buildPosts(buildPostPageable(optionService.getRssPageSize())); + model.addAttribute("posts", posts); + Timestamp lastModified = this.getLastModifiedTime(posts); + this.lastModified2ResponseHeader(response, lastModified); + model.addAttribute("lastModified", lastModified); Template template = freeMarker.getConfiguration().getTemplate("common/web/rss.ftl"); return FreeMarkerTemplateUtils.processTemplateIntoString(template, model); } @@ -97,13 +109,18 @@ public class ContentFeedController { @GetMapping(value = {"feed/categories/{slug}", "feed/categories/{slug}.xml"}, produces = XML_MEDIA_TYPE) @ResponseBody - public String feed(Model model, @PathVariable(name = "slug") String slug) + public String feed(Model model, @PathVariable(name = "slug") String slug, + HttpServletResponse response) throws IOException, TemplateException { Category category = categoryService.getBySlugOfNonNull(slug); CategoryDTO categoryDTO = categoryService.convertTo(category); + List posts = + buildCategoryPosts(buildPostPageable(optionService.getRssPageSize()), categoryDTO); model.addAttribute("category", categoryDTO); - model.addAttribute("posts", - buildCategoryPosts(buildPostPageable(optionService.getRssPageSize()), categoryDTO)); + model.addAttribute("posts", posts); + Timestamp lastModified = this.getLastModifiedTime(posts); + this.lastModified2ResponseHeader(response, lastModified); + model.addAttribute("lastModified", lastModified); Template template = freeMarker.getConfiguration().getTemplate("common/web/rss.ftl"); return FreeMarkerTemplateUtils.processTemplateIntoString(template, model); } @@ -118,8 +135,13 @@ public class ContentFeedController { */ @GetMapping(value = {"atom", "atom.xml"}, produces = XML_MEDIA_TYPE) @ResponseBody - public String atom(Model model) throws IOException, TemplateException { - model.addAttribute("posts", buildPosts(buildPostPageable(optionService.getRssPageSize()))); + public String atom(Model model, HttpServletResponse response) + throws IOException, TemplateException { + List posts = buildPosts(buildPostPageable(optionService.getRssPageSize())); + model.addAttribute("posts", posts); + Timestamp lastModified = this.getLastModifiedTime(posts); + this.lastModified2ResponseHeader(response, lastModified); + model.addAttribute("lastModified", lastModified); Template template = freeMarker.getConfiguration().getTemplate("common/web/atom.ftl"); return FreeMarkerTemplateUtils.processTemplateIntoString(template, model); } @@ -136,13 +158,18 @@ public class ContentFeedController { @GetMapping(value = {"atom/categories/{slug}", "atom/categories/{slug}.xml"}, produces = XML_MEDIA_TYPE) @ResponseBody - public String atom(Model model, @PathVariable(name = "slug") String slug) + public String atom(Model model, @PathVariable(name = "slug") String slug, + HttpServletResponse response) throws IOException, TemplateException { Category category = categoryService.getBySlugOfNonNull(slug); CategoryDTO categoryDTO = categoryService.convertTo(category); + List posts = + buildCategoryPosts(buildPostPageable(optionService.getRssPageSize()), categoryDTO); model.addAttribute("category", categoryDTO); - model.addAttribute("posts", - buildCategoryPosts(buildPostPageable(optionService.getRssPageSize()), categoryDTO)); + model.addAttribute("posts", posts); + Timestamp lastModified = this.getLastModifiedTime(posts); + this.lastModified2ResponseHeader(response, lastModified); + model.addAttribute("lastModified", lastModified); Template template = freeMarker.getConfiguration().getTemplate("common/web/atom.ftl"); return FreeMarkerTemplateUtils.processTemplateIntoString(template, model); } @@ -248,4 +275,19 @@ public class ContentFeedController { }); return posts.getContent(); } + + private Timestamp getLastModifiedTime(List posts) { + OptionalLong lastModifiedTimestamp = + posts.stream().mapToLong(post -> post.getEditTime().getTime()).max(); + if (lastModifiedTimestamp.isEmpty()) { + return new Timestamp(System.currentTimeMillis()); + } + return new Timestamp(lastModifiedTimestamp.getAsLong()); + } + + private void lastModified2ResponseHeader(HttpServletResponse response, Timestamp time) { + SimpleDateFormat dateFormat = + new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.ENGLISH); + response.setHeader(LAST_MODIFIED_HEADER, dateFormat.format(time)); + } } diff --git a/src/main/resources/templates/common/web/atom.ftl b/src/main/resources/templates/common/web/atom.ftl index fdf599093..6f12b992e 100644 --- a/src/main/resources/templates/common/web/atom.ftl +++ b/src/main/resources/templates/common/web/atom.ftl @@ -14,7 +14,7 @@ ${user.description!} - ${.now?iso_local} + ${lastModified?iso_local} <#if category??> ${category.fullPath!} <#else> diff --git a/src/main/resources/templates/common/web/rss.ftl b/src/main/resources/templates/common/web/rss.ftl index 2139f15d5..6619206aa 100644 --- a/src/main/resources/templates/common/web/rss.ftl +++ b/src/main/resources/templates/common/web/rss.ftl @@ -1,4 +1,5 @@ +<#setting locale="en_US"> <#if category??> @@ -21,6 +22,7 @@ Halo ${version!} + ${lastModified?string('EEE, dd MMM yyyy HH:mm:ss z')} <#if posts?? && posts?size gt 0> <#list posts as post> @@ -35,7 +37,7 @@ - ${post.createTime?iso_local} + ${post.createTime?string('EEE, dd MMM yyyy HH:mm:ss z')}