diff --git a/app/controllers/list_controller.rb b/app/controllers/list_controller.rb index 6fc25d672e3..a5fd0c52a9b 100644 --- a/app/controllers/list_controller.rb +++ b/app/controllers/list_controller.rb @@ -360,7 +360,7 @@ class ListController < ApplicationController current_slug = current_slug.split("/").map { |slug| CGI.escape(slug) }.join("/") end real_slug = @category.full_slug("/") - if current_slug != real_slug + if CGI.unescape(current_slug) != CGI.unescape(real_slug) url = request.fullpath.gsub(current_slug, real_slug) if ActionController::Base.config.relative_url_root url = url.sub(ActionController::Base.config.relative_url_root, "") diff --git a/spec/requests/list_controller_spec.rb b/spec/requests/list_controller_spec.rb index a1ad838fa63..6dc85dc8456 100644 --- a/spec/requests/list_controller_spec.rb +++ b/spec/requests/list_controller_spec.rb @@ -759,6 +759,37 @@ RSpec.describe ListController do get "/c/hello/world/bye/#{subsubcategory.id}" expect(response.status).to eq(301) expect(response).to redirect_to("/c/#{category.slug}/#{subcategory.slug}/#{subsubcategory.slug}/#{subsubcategory.id}") + + get "/c/#{category.slug}/#{subcategory.slug}/#{subsubcategory.slug}/#{subsubcategory.id}" + expect(response.status).to eq(200) + end + + it "redirects to URL with correct case slug" do + category.update!(slug: "hello") + + get "/c/Hello/#{category.id}" + expect(response).to redirect_to("/c/hello/#{category.id}") + + get "/c/hello/#{category.id}" + expect(response.status).to eq(200) + end + + context "does not create a redirect loop" do + it "with encoded slugs" do + category = Fabricate(:category) + category.update_columns(slug: CGI.escape("systèmes")) + + get "/c/syst%C3%A8mes/#{category.id}" + expect(response.status).to eq(200) + end + + it "with lowercase encoded slugs" do + category = Fabricate(:category) + category.update_columns(slug: CGI.escape("systèmes").downcase) + + get "/c/syst%C3%A8mes/#{category.id}" + expect(response.status).to eq(200) + end end context "with subfolder" do