From 90be15e0b5e8270b995e081adf9b16a808d1a6fb Mon Sep 17 00:00:00 2001 From: evazion Date: Sat, 22 Jan 2022 16:52:20 -0600 Subject: [PATCH] Fix #4973: Wiki pages json index returns 404. Fix regression introduced in 0db20e0ca. Setting `format: false` on the wiki pages resource disabled format negotiation on all wiki page routes, not just the show page, which meant /wiki_pages.json no longer worked. The fix to monkey patch the internal Rails method that parses the file extension from the URL, and have it ignore everything but the .html, .json, .js, and .xml extensions. This is really hacky and may break in future Rails releases. --- app/controllers/wiki_pages_controller.rb | 9 --------- config/initializers/core_extensions.rb | 17 +++++++++++++++++ config/routes.rb | 2 +- test/functional/wiki_pages_controller_test.rb | 7 +++++++ 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/app/controllers/wiki_pages_controller.rb b/app/controllers/wiki_pages_controller.rb index f9f6ece3f..7386018b1 100644 --- a/app/controllers/wiki_pages_controller.rb +++ b/app/controllers/wiki_pages_controller.rb @@ -30,15 +30,6 @@ class WikiPagesController < ApplicationController end def show - if params[:format].present? - request.format = params[:format] - elsif params[:id].ends_with?(".html", ".json", ".xml") - request.format = params[:id].split(".").last - params[:id].delete_suffix!(".#{request.format.symbol}") - else - request.format = "html" - end - @wiki_page, found_by = WikiPage.find_by_id_or_title(params[:id]) if request.format.html? && @wiki_page.blank? && found_by == :title diff --git a/config/initializers/core_extensions.rb b/config/initializers/core_extensions.rb index 3cb5d9f70..ef828ddde 100644 --- a/config/initializers/core_extensions.rb +++ b/config/initializers/core_extensions.rb @@ -63,6 +63,23 @@ class String include Danbooru::Extensions::String end +module MimeNegotationExtension + # Ignore all file extensions except for .html, .js, .json, and .xml when + # parsing the file extension from the URL. Needed for wiki pages (e.g. + # /wiki_pages/rnd.jpg). + private def format_from_path_extension + mime = super + + if mime&.symbol.in?(%i[html js json xml]) + mime + else + nil + end + end +end + +ActionDispatch::Http::MimeNegotiation.prepend(MimeNegotationExtension) + # Make Symbol#to_s return a frozen string. This reduces allocations, but may be # incompatible with some libraries. # diff --git a/config/routes.rb b/config/routes.rb index 950025f90..0f19afcd5 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -280,7 +280,7 @@ Rails.application.routes.draw do resources :webhooks do post :receive, on: :collection end - resources :wiki_pages, id: /.+/, format: false do + resources :wiki_pages, id: /.+?(?=\.json|\.xml|\.html)|.+/ do put :revert, on: :member get :search, on: :collection get :show_or_new, on: :collection diff --git a/test/functional/wiki_pages_controller_test.rb b/test/functional/wiki_pages_controller_test.rb index 92f7f1135..1aa0b386e 100644 --- a/test/functional/wiki_pages_controller_test.rb +++ b/test/functional/wiki_pages_controller_test.rb @@ -31,6 +31,13 @@ class WikiPagesControllerTest < ActionDispatch::IntegrationTest assert_equal(WikiPage.count, response.parsed_body.css("urlset url loc").size) end + should "render for a JSON response" do + get wiki_pages_path(format: :json) + + assert_response :success + assert_equal("application/json", response.media_type) + end + should "redirect the legacy title param to the show page" do get wiki_pages_path(title: "tagme") assert_redirected_to wiki_pages_path(search: { title_normalize: "tagme" }, redirect: true)