diff --git a/app/helpers/knowledge_base_helper.rb b/app/helpers/knowledge_base_helper.rb index 5b71afb36..816b04f1b 100644 --- a/app/helpers/knowledge_base_helper.rb +++ b/app/helpers/knowledge_base_helper.rb @@ -12,7 +12,7 @@ module KnowledgeBaseHelper return path if !custom_address custom_path = path.gsub(%r{^/help}, custom_address.path || '').presence || '/' - prefix = full ? knowledge_base.custom_path_prefix(request) : '' + prefix = full ? knowledge_base.custom_address_prefix(request) : '' "#{prefix}#{custom_path}" end diff --git a/app/models/knowledge_base.rb b/app/models/knowledge_base.rb index b6d235a3e..f7ed3da9c 100644 --- a/app/models/knowledge_base.rb +++ b/app/models/knowledge_base.rb @@ -94,8 +94,12 @@ class KnowledgeBase < ApplicationModel end def custom_address_prefix(request) - host = custom_address.host || request.headers.env['SERVER_NAME'] - "#{custom_address.scheme}://#{host}" + host = custom_address_uri.host || request.headers.env['SERVER_NAME'] + port = request.headers.env['SERVER_PORT'] + port_silent = request.ssl? && port == '443' || !request.ssl? && port == '80' + port_string = port_silent ? '' : ":#{port}" + + "#{custom_address_uri.scheme}://#{host}#{port_string}" end def full_destroy! diff --git a/app/models/knowledge_base/locale.rb b/app/models/knowledge_base/locale.rb index cd3d77f00..9732f635d 100644 --- a/app/models/knowledge_base/locale.rb +++ b/app/models/knowledge_base/locale.rb @@ -27,7 +27,7 @@ class KnowledgeBase::Locale < ApplicationModel dependent: :destroy def self.system_with_kb_locales(knowledge_base) - Locale + ::Locale .joins(:knowledge_base_locales) .where(knowledge_base_locales: { knowledge_base: knowledge_base }) .select('locales.*, knowledge_base_locales.id as kb_locale_id, knowledge_base_locales.primary as primary_locale') diff --git a/spec/requests/knowledge_base_public/custom_path_spec.rb b/spec/requests/knowledge_base_public/custom_path_spec.rb new file mode 100644 index 000000000..b12ad9993 --- /dev/null +++ b/spec/requests/knowledge_base_public/custom_path_spec.rb @@ -0,0 +1,89 @@ +require 'rails_helper' + +# Custom subdomain is handled by rewriting at web server +# Calling the original /help URL with a custom URL in header to simulate +RSpec.describe 'KnowledgeBase public custom path', type: :request do + let!(:knowledge_base) { create(:knowledge_base, custom_address: custom_address) } + let(:path) { '/path' } + let(:subdomain) { 'subdomain.example.net' } + let(:locale) { knowledge_base.kb_locales.first.system_locale.locale } + + shared_examples 'accepting original URL' do + before { fetch } + + it { expect(response).to have_http_status(:found) } + it { expect(response).to redirect_to "/help/#{locale}" } + end + + context 'with no custom path' do + let(:custom_address) { nil } + + it_behaves_like 'accepting original URL' + + context 'when called with the subdomain' do + before { fetch subdomain: subdomain, path: '/' } + + it { expect(response).to have_http_status(:found) } + it { expect(response).to redirect_to "/help/#{locale}" } + end + end + + context 'with custom path' do + let(:custom_address) { path } + + it_behaves_like 'accepting original URL' + + context 'when called with the path' do + before { fetch path: path } + + it { expect(response).to have_http_status(:found) } + it { expect(response).to redirect_to "/path/#{locale}" } + end + + context 'when called with a custom port' do + before { fetch path: path, port: 8080 } + + it { expect(response).to have_http_status(:found) } + it { expect(response).to redirect_to ":8080/path/#{locale}" } + end + + context 'when called with the path and subdomain' do + before { fetch path: path, subdomain: subdomain } + + it { expect(response).to have_http_status(:found) } + it { expect(response).to redirect_to "http://subdomain.example.net/path/#{locale}" } + end + end + + context 'with custom subdomain' do + let(:custom_address) { subdomain } + + it_behaves_like 'accepting original URL' + + context 'when called with the subdomain' do + before { fetch subdomain: subdomain, path: '/' } + + it { expect(response).to have_http_status(:found) } + it { expect(response).to redirect_to "http://subdomain.example.net/#{locale}" } + end + end + + context 'with custom subdomain and path' do + let(:custom_address) { "#{subdomain}#{path}" } + + it_behaves_like 'accepting original URL' + + context 'when called with the path and subdomain' do + before { fetch path: path, subdomain: subdomain } + + it { expect(response).to have_http_status(:found) } + it { expect(response).to redirect_to "http://subdomain.example.net/path/#{locale}" } + end + end + + def fetch(path: nil, subdomain: nil, port: nil) + headers = { HTTP_X_ORIGINAL_URL: path, SERVER_NAME: subdomain, SERVER_PORT: port }.compact + + get '/help', headers: headers + end +end