Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 10 additions & 11 deletions app/controllers/pageflow/entries_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,13 @@ def entry_request_scope
end

def handle_public_entry_request(entry)
return if redirect_according_to_entry_redirect(entry)
config = Pageflow.config_for(entry)

return if redirect_according_to_entry_redirect(entry, config)
return if redirect_according_to_public_https_mode
return unless check_entry_password_protection(entry)

delegate_to_entry_type_frontend_app!(entry)
delegate_to_entry_type_frontend_app!(entry, config:)
end

def redirect_according_to_permalink_redirect
Expand All @@ -107,26 +109,21 @@ def redirect_according_to_permalink_redirect
true
end

def redirect_according_to_entry_redirect(entry)
return false unless (redirect_location = entry_redirect(entry))
def redirect_according_to_entry_redirect(entry, config)
return false unless (redirect_location = config.public_entry_redirect.call(entry, request))

redirect_to(redirect_location, status: :moved_permanently, allow_other_host: true)
true
end

def entry_redirect(entry)
Pageflow.config.public_entry_redirect.call(entry, request)
end

def delegate_to_entry_type_frontend_app!(entry, override_status: nil)
def delegate_to_entry_type_frontend_app!(entry, config:, override_status: nil)
EntriesControllerEnvHelper.add_entry_info_to_env(request.env,
entry:,
mode: :published,
embed: params[:embed].present?)

delegate_to_rack_app!(entry.entry_type.frontend_app) do |result|
status, headers, body = result
config = Pageflow.config_for(entry)

allow_iframe_for_embed(headers)
apply_additional_headers(entry, config, headers)
Expand Down Expand Up @@ -158,7 +155,9 @@ def render_custom_or_static_404_error_page

if site&.custom_404_entry&.published_without_password_protection?
entry = PublishedEntry.new(site.custom_404_entry)
delegate_to_entry_type_frontend_app!(entry, override_status: 404)
config = Pageflow.config_for(entry)

delegate_to_entry_type_frontend_app!(entry, config:, override_status: 404)
else
# Fallback to ApplicationController's handler method
render_static_404_error_page
Expand Down
1 change: 1 addition & 0 deletions lib/pageflow/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,7 @@ def enable_all_features
delegate :additional_public_entry_headers, to: :config
delegate :cutoff_modes, to: :config
delegate :entry_translator_url=, to: :config
delegate :public_entry_redirect=, to: :config
delegate :public_entry_url_options=, to: :config

delegate :for_entry_type, to: :config
Expand Down
36 changes: 23 additions & 13 deletions spec/requests/pageflow/entries_index_request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,37 +106,47 @@ module Pageflow

describe 'with configured public_entry_redirect' do
it 'redirects to returned location' do
pageflow_configure do |config|
config.public_entry_redirect = ->(_, _) { '/some_location' }
end

site = create(:site, cname: 'pageflow.example.com')
create(:entry,
:published,
site:,
type_name: 'test',
permalink_attributes: {slug: '', allow_root_path: true})

Pageflow.config.public_entry_redirect = ->(_, _) { '/some_location' }

get('http://pageflow.example.com/')

expect(response).to redirect_to('/some_location')
end

it 'redirects even before https redirect takes place' do
pageflow_configure do |config|
config.public_https_mode = :enforce
config.public_entry_redirect = ->(_, _) { '/some_location' }
end

site = create(:site, cname: 'pageflow.example.com')
create(:entry,
:published,
site:,
type_name: 'test',
permalink_attributes: {slug: '', allow_root_path: true})

Pageflow.config.public_https_mode = :enforce
Pageflow.config.public_entry_redirect = ->(_, _) { '/some_location' }

get('http://pageflow.example.com/')

expect(response).to redirect_to('/some_location')
end

it 'passes entry and request' do
pageflow_configure do |config|
config.public_entry_redirect = lambda do |passed_entry, request|
"#{request.protocol}#{request.host}/#{passed_entry.slug}"
end
end

site = create(:site, cname: 'pageflow.example.com')
entry = create(
:entry,
Expand All @@ -147,40 +157,40 @@ module Pageflow
permalink_attributes: {slug: '', allow_root_path: true}
)

Pageflow.config.public_entry_redirect = lambda do |passed_entry, request|
"#{request.protocol}#{request.host}/#{passed_entry.slug}"
end

get('http://pageflow.example.com/')

expect(response).to redirect_to("http://pageflow.example.com/#{entry.slug}")
end

it 'allows redirecting to other host' do
pageflow_configure do |config|
config.public_entry_redirect = ->(_, _) { 'http://www.example.com/' }
end

site = create(:site, cname: 'pageflow.example.com')
create(:entry,
:published,
site:,
type_name: 'test',
permalink_attributes: {slug: '', allow_root_path: true})

Pageflow.config.public_entry_redirect = ->(_, _) { 'http://www.example.com/' }

get('http://pageflow.example.com/')

expect(response).to redirect_to('http://www.example.com/')
end

it 'does not redirect if nil is returned' do
pageflow_configure do |config|
config.public_entry_redirect = ->(_, _) {}
end

site = create(:site, cname: 'pageflow.example.com')
create(:entry,
:published,
site:,
type_name: 'test',
permalink_attributes: {slug: '', allow_root_path: true})

Pageflow.config.public_entry_redirect = ->(_, _) {}

get('http://pageflow.example.com/')

expect(response.status).to eq(200)
Expand Down
74 changes: 59 additions & 15 deletions spec/requests/pageflow/entries_show_request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ module Pageflow
get(short_entry_url(entry))

expect(response.status).to eq(200)
expect(response.body).to include('some-entry published embed=false rendered by entry type frontend app')
expect(response.body)
.to include('some-entry published embed=false rendered by entry type frontend app')
end

it 'passes embed=true for embed requests' do
Expand All @@ -69,7 +70,8 @@ module Pageflow
get(entry_embed_url(entry))

expect(response.status).to eq(200)
expect(response.body).to include('some-entry published embed=true rendered by entry type frontend app')
expect(response.body)
.to include('some-entry published embed=true rendered by entry type frontend app')
end

it 'supports finding published entry based on permalink' do
Expand Down Expand Up @@ -237,7 +239,8 @@ module Pageflow
get('http://my.example.com/non-existent-entry')

expect(response.status).to eq(404)
expect(response.body).to include('Custom 404 published embed=false rendered by entry type frontend app')
expect(response.body)
.to include('Custom 404 published embed=false rendered by entry type frontend app')
end

it 'falls back to default 404 when site has no custom_404_entry' do
Expand Down Expand Up @@ -353,63 +356,104 @@ module Pageflow

describe 'with configured public_entry_redirect' do
it 'redirects to returned location' do
pageflow_configure do |config|
config.public_entry_redirect = ->(_, _) { '/some_location' }
end

entry = create(:entry, :published,
type_name: 'test')

Pageflow.config.public_entry_redirect = ->(_, _) { '/some_location' }

get(short_entry_url(entry))

expect(response).to redirect_to('/some_location')
end

it 'redirects even before https redirect takes place' do
pageflow_configure do |config|
config.public_https_mode = :enforce
config.public_entry_redirect = ->(_, _) { '/some_location' }
end

entry = create(:entry, :published,
type_name: 'test')

Pageflow.config.public_https_mode = :enforce
Pageflow.config.public_entry_redirect = ->(_, _) { '/some_location' }

get(short_entry_url(entry))

expect(response).to redirect_to('/some_location')
end

it 'passes entry and request' do
pageflow_configure do |config|
config.public_entry_redirect = lambda do |passed_entry, request|
"#{request.protocol}#{request.host}/#{passed_entry.slug}"
end
end

create(:entry, :published,
title: 'some-entry',
type_name: 'test')

Pageflow.config.public_entry_redirect = lambda do |passed_entry, request|
"#{request.protocol}#{request.host}/#{passed_entry.slug}"
end

get('http://www.example.com/some-entry')

expect(response).to redirect_to('http://www.example.com/some-entry')
end

it 'allows redirecting to other host' do
pageflow_configure do |config|
config.public_entry_redirect = ->(_, _) { 'http://www.example.com/' }
end

entry = create(:entry, :published,
type_name: 'test')

Pageflow.config.public_entry_redirect = ->(_, _) { 'http://www.example.com/' }

get(short_entry_url(entry), headers: {'HTTP_HOST' => 'pageflow.example.com'})

expect(response).to redirect_to('http://www.example.com/')
end

it 'does not redirect if nil is returned' do
pageflow_configure do |config|
config.public_entry_redirect = ->(_, _) {}
end

entry = create(:entry, :published,
type_name: 'test')

Pageflow.config.public_entry_redirect = ->(_, _) {}
get(short_entry_url(entry))

expect(response.status).to eq(200)
end

it 'does not use redirect from feature flag by default' do
pageflow_configure do |config|
config.features.register('redirect_feature') do |feature_config|
feature_config.public_entry_redirect = ->(_, _) { '/redirected' }
end
end

entry = create(:entry, :published,
type_name: 'test')

get(short_entry_url(entry))

expect(response.status).to eq(200)
end

it 'uses redirect from feature flag if enabled' do
pageflow_configure do |config|
config.features.register('redirect_feature') do |feature_config|
feature_config.public_entry_redirect = ->(_, _) { '/redirected' }
end
end

entry = create(:entry, :published,
type_name: 'test',
with_feature: 'redirect_feature')

get(short_entry_url(entry))

expect(response).to redirect_to('/redirected')
end
end

describe 'X-Frame-Options header' do
Expand Down
Loading