diff --git a/app/controllers/sitemaps_controller.rb b/app/controllers/sitemaps_controller.rb index 17a5760ca..71cdcb615 100644 --- a/app/controllers/sitemaps_controller.rb +++ b/app/controllers/sitemaps_controller.rb @@ -2,8 +2,28 @@ class SitemapsController < ApplicationController before_action :set_cache_control_headers, only: %i[show] SITEMAP_REGEX = /\Asitemap-(?[A-Z][a-z][a-z]-\d{4})\.xml\z/ + RESULTS_LIMIT = Rails.env.production? ? 10_000 : 5 def show + if params[:sitemap].start_with? "sitemap-posts" + posts_sitemap + else + monthly_sitemap + end + set_cache_control_headers(@max_age, + stale_while_revalidate: @stale_while_revalidate, + stale_if_error: @stale_if_error) + render layout: false + end + + private + + def posts_sitemap + @articles = Article.published.order("published_at DESC").limit(RESULTS_LIMIT).offset(offset).pluck(:path, :last_comment_at) + set_surrogate_controls(Time.now) + end + + def monthly_sitemap match = params[:sitemap].match(SITEMAP_REGEX) not_found unless match && match[:date_string] begin @@ -18,14 +38,8 @@ class SitemapsController < ApplicationController .pluck(:path, :last_comment_at) set_surrogate_controls(date) - set_cache_control_headers(@max_age, - stale_while_revalidate: @stale_while_revalidate, - stale_if_error: @stale_if_error) - render layout: false end - private - def set_surrogate_controls(date) @stale_if_error = "86400" if date > 1.month.ago @@ -36,4 +50,8 @@ class SitemapsController < ApplicationController @stale_while_revalidate = "432000" # five days end end + + def offset + params[:sitemap].split("-")[2].to_i * RESULTS_LIMIT # elvaluates to 0 if not present or not a number + end end diff --git a/spec/requests/sitemaps_spec.rb b/spec/requests/sitemaps_spec.rb index 8807ea85f..8b92ab1a7 100644 --- a/spec/requests/sitemaps_spec.rb +++ b/spec/requests/sitemaps_spec.rb @@ -40,5 +40,39 @@ RSpec.describe "Sitemaps", type: :request do expect(response.body).not_to include(articles.last.path) expect(response.media_type).to eq("application/xml") end + + it "renders most recent posts if /sitemap-posts", :aggregate_failures do + create_list(:article, 8) + get "/sitemap-posts.xml" + expect(response.body).to include(Article.order("published_at DESC").first.path) + expect(response.body).not_to include(Article.order("published_at DESC").last.path) + end + + it "renders second page if /sitemap-posts-1", :aggregate_failures do + create_list(:article, 8) + get "/sitemap-posts-1.xml" + expect(response.body).not_to include(Article.order("published_at DESC").first.path) + expect(response.body).to include(Article.order("published_at DESC").last.path) + end + + it "renders first page if /sitemap-posts-randomn0tnumber", :aggregate_failures do + create_list(:article, 8) + get "/sitemap-posts-randomn0tnumber.xml" + expect(response.body).to include(Article.order("published_at DESC").first.path) + expect(response.body).not_to include(Article.order("published_at DESC").last.path) + end + + it "renders empty if /sitemap-posts-2", :aggregate_failures do + # no posts this far down. + create_list(:article, 8) + get "/sitemap-posts-2.xml" + expect(response.body).not_to include(Article.order("published_at DESC").first.path) + expect(response.body).not_to include(Article.order("published_at DESC").last.path) + end + + it "renders 'recent' version of surrogate control" do + get "/sitemap-posts-2.xml" + expect(response.header["Surrogate-Control"]).to include("8640") + end end end