Skip to content

Commit f34f522

Browse files
committed
Allow public_entry_redirect in feature blocks
This enables configuring entry redirects per feature flag, consistent with other entry-specific config options like cache control headers.
1 parent 001d51d commit f34f522

File tree

4 files changed

+93
-39
lines changed

4 files changed

+93
-39
lines changed

app/controllers/pageflow/entries_controller.rb

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,13 @@ def entry_request_scope
8585
end
8686

8787
def handle_public_entry_request(entry)
88-
return if redirect_according_to_entry_redirect(entry)
88+
config = Pageflow.config_for(entry)
89+
90+
return if redirect_according_to_entry_redirect(entry, config)
8991
return if redirect_according_to_public_https_mode
9092
return unless check_entry_password_protection(entry)
9193

92-
delegate_to_entry_type_frontend_app!(entry)
94+
delegate_to_entry_type_frontend_app!(entry, config:)
9395
end
9496

9597
def redirect_according_to_permalink_redirect
@@ -107,26 +109,21 @@ def redirect_according_to_permalink_redirect
107109
true
108110
end
109111

110-
def redirect_according_to_entry_redirect(entry)
111-
return false unless (redirect_location = entry_redirect(entry))
112+
def redirect_according_to_entry_redirect(entry, config)
113+
return false unless (redirect_location = config.public_entry_redirect.call(entry, request))
112114

113115
redirect_to(redirect_location, status: :moved_permanently, allow_other_host: true)
114116
true
115117
end
116118

117-
def entry_redirect(entry)
118-
Pageflow.config.public_entry_redirect.call(entry, request)
119-
end
120-
121-
def delegate_to_entry_type_frontend_app!(entry, override_status: nil)
119+
def delegate_to_entry_type_frontend_app!(entry, config:, override_status: nil)
122120
EntriesControllerEnvHelper.add_entry_info_to_env(request.env,
123121
entry:,
124122
mode: :published,
125123
embed: params[:embed].present?)
126124

127125
delegate_to_rack_app!(entry.entry_type.frontend_app) do |result|
128126
status, headers, body = result
129-
config = Pageflow.config_for(entry)
130127

131128
allow_iframe_for_embed(headers)
132129
apply_additional_headers(entry, config, headers)
@@ -158,7 +155,9 @@ def render_custom_or_static_404_error_page
158155

159156
if site&.custom_404_entry&.published_without_password_protection?
160157
entry = PublishedEntry.new(site.custom_404_entry)
161-
delegate_to_entry_type_frontend_app!(entry, override_status: 404)
158+
config = Pageflow.config_for(entry)
159+
160+
delegate_to_entry_type_frontend_app!(entry, config:, override_status: 404)
162161
else
163162
# Fallback to ApplicationController's handler method
164163
render_static_404_error_page

lib/pageflow/configuration.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,7 @@ def enable_all_features
733733
delegate :additional_public_entry_headers, to: :config
734734
delegate :cutoff_modes, to: :config
735735
delegate :entry_translator_url=, to: :config
736+
delegate :public_entry_redirect=, to: :config
736737
delegate :public_entry_url_options=, to: :config
737738

738739
delegate :for_entry_type, to: :config

spec/requests/pageflow/entries_index_request_spec.rb

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -106,37 +106,47 @@ module Pageflow
106106

107107
describe 'with configured public_entry_redirect' do
108108
it 'redirects to returned location' do
109+
pageflow_configure do |config|
110+
config.public_entry_redirect = ->(_, _) { '/some_location' }
111+
end
112+
109113
site = create(:site, cname: 'pageflow.example.com')
110114
create(:entry,
111115
:published,
112116
site:,
113117
type_name: 'test',
114118
permalink_attributes: {slug: '', allow_root_path: true})
115119

116-
Pageflow.config.public_entry_redirect = ->(_, _) { '/some_location' }
117-
118120
get('http://pageflow.example.com/')
119121

120122
expect(response).to redirect_to('/some_location')
121123
end
122124

123125
it 'redirects even before https redirect takes place' do
126+
pageflow_configure do |config|
127+
config.public_https_mode = :enforce
128+
config.public_entry_redirect = ->(_, _) { '/some_location' }
129+
end
130+
124131
site = create(:site, cname: 'pageflow.example.com')
125132
create(:entry,
126133
:published,
127134
site:,
128135
type_name: 'test',
129136
permalink_attributes: {slug: '', allow_root_path: true})
130137

131-
Pageflow.config.public_https_mode = :enforce
132-
Pageflow.config.public_entry_redirect = ->(_, _) { '/some_location' }
133-
134138
get('http://pageflow.example.com/')
135139

136140
expect(response).to redirect_to('/some_location')
137141
end
138142

139143
it 'passes entry and request' do
144+
pageflow_configure do |config|
145+
config.public_entry_redirect = lambda do |passed_entry, request|
146+
"#{request.protocol}#{request.host}/#{passed_entry.slug}"
147+
end
148+
end
149+
140150
site = create(:site, cname: 'pageflow.example.com')
141151
entry = create(
142152
:entry,
@@ -147,40 +157,40 @@ module Pageflow
147157
permalink_attributes: {slug: '', allow_root_path: true}
148158
)
149159

150-
Pageflow.config.public_entry_redirect = lambda do |passed_entry, request|
151-
"#{request.protocol}#{request.host}/#{passed_entry.slug}"
152-
end
153-
154160
get('http://pageflow.example.com/')
155161

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

159165
it 'allows redirecting to other host' do
166+
pageflow_configure do |config|
167+
config.public_entry_redirect = ->(_, _) { 'http://www.example.com/' }
168+
end
169+
160170
site = create(:site, cname: 'pageflow.example.com')
161171
create(:entry,
162172
:published,
163173
site:,
164174
type_name: 'test',
165175
permalink_attributes: {slug: '', allow_root_path: true})
166176

167-
Pageflow.config.public_entry_redirect = ->(_, _) { 'http://www.example.com/' }
168-
169177
get('http://pageflow.example.com/')
170178

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

174182
it 'does not redirect if nil is returned' do
183+
pageflow_configure do |config|
184+
config.public_entry_redirect = ->(_, _) {}
185+
end
186+
175187
site = create(:site, cname: 'pageflow.example.com')
176188
create(:entry,
177189
:published,
178190
site:,
179191
type_name: 'test',
180192
permalink_attributes: {slug: '', allow_root_path: true})
181193

182-
Pageflow.config.public_entry_redirect = ->(_, _) {}
183-
184194
get('http://pageflow.example.com/')
185195

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

spec/requests/pageflow/entries_show_request_spec.rb

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ module Pageflow
6060
get(short_entry_url(entry))
6161

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

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

7172
expect(response.status).to eq(200)
72-
expect(response.body).to include('some-entry published embed=true rendered by entry type frontend app')
73+
expect(response.body)
74+
.to include('some-entry published embed=true rendered by entry type frontend app')
7375
end
7476

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

239241
expect(response.status).to eq(404)
240-
expect(response.body).to include('Custom 404 published embed=false rendered by entry type frontend app')
242+
expect(response.body)
243+
.to include('Custom 404 published embed=false rendered by entry type frontend app')
241244
end
242245

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

354357
describe 'with configured public_entry_redirect' do
355358
it 'redirects to returned location' do
359+
pageflow_configure do |config|
360+
config.public_entry_redirect = ->(_, _) { '/some_location' }
361+
end
362+
356363
entry = create(:entry, :published,
357364
type_name: 'test')
358365

359-
Pageflow.config.public_entry_redirect = ->(_, _) { '/some_location' }
360-
361366
get(short_entry_url(entry))
362367

363368
expect(response).to redirect_to('/some_location')
364369
end
365370

366371
it 'redirects even before https redirect takes place' do
372+
pageflow_configure do |config|
373+
config.public_https_mode = :enforce
374+
config.public_entry_redirect = ->(_, _) { '/some_location' }
375+
end
376+
367377
entry = create(:entry, :published,
368378
type_name: 'test')
369379

370-
Pageflow.config.public_https_mode = :enforce
371-
Pageflow.config.public_entry_redirect = ->(_, _) { '/some_location' }
372-
373380
get(short_entry_url(entry))
374381

375382
expect(response).to redirect_to('/some_location')
376383
end
377384

378385
it 'passes entry and request' do
386+
pageflow_configure do |config|
387+
config.public_entry_redirect = lambda do |passed_entry, request|
388+
"#{request.protocol}#{request.host}/#{passed_entry.slug}"
389+
end
390+
end
391+
379392
create(:entry, :published,
380393
title: 'some-entry',
381394
type_name: 'test')
382395

383-
Pageflow.config.public_entry_redirect = lambda do |passed_entry, request|
384-
"#{request.protocol}#{request.host}/#{passed_entry.slug}"
385-
end
386-
387396
get('http://www.example.com/some-entry')
388397

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

392401
it 'allows redirecting to other host' do
402+
pageflow_configure do |config|
403+
config.public_entry_redirect = ->(_, _) { 'http://www.example.com/' }
404+
end
405+
393406
entry = create(:entry, :published,
394407
type_name: 'test')
395408

396-
Pageflow.config.public_entry_redirect = ->(_, _) { 'http://www.example.com/' }
397-
398409
get(short_entry_url(entry), headers: {'HTTP_HOST' => 'pageflow.example.com'})
399410

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

403414
it 'does not redirect if nil is returned' do
415+
pageflow_configure do |config|
416+
config.public_entry_redirect = ->(_, _) {}
417+
end
418+
404419
entry = create(:entry, :published,
405420
type_name: 'test')
406421

407-
Pageflow.config.public_entry_redirect = ->(_, _) {}
422+
get(short_entry_url(entry))
423+
424+
expect(response.status).to eq(200)
425+
end
426+
427+
it 'does not use redirect from feature flag by default' do
428+
pageflow_configure do |config|
429+
config.features.register('redirect_feature') do |feature_config|
430+
feature_config.public_entry_redirect = ->(_, _) { '/redirected' }
431+
end
432+
end
433+
434+
entry = create(:entry, :published,
435+
type_name: 'test')
408436

409437
get(short_entry_url(entry))
410438

411439
expect(response.status).to eq(200)
412440
end
441+
442+
it 'uses redirect from feature flag if enabled' do
443+
pageflow_configure do |config|
444+
config.features.register('redirect_feature') do |feature_config|
445+
feature_config.public_entry_redirect = ->(_, _) { '/redirected' }
446+
end
447+
end
448+
449+
entry = create(:entry, :published,
450+
type_name: 'test',
451+
with_feature: 'redirect_feature')
452+
453+
get(short_entry_url(entry))
454+
455+
expect(response).to redirect_to('/redirected')
456+
end
413457
end
414458

415459
describe 'X-Frame-Options header' do

0 commit comments

Comments
 (0)