Commit e7504115 authored by Krasimir Angelov's avatar Krasimir Angelov

Pages API: Make domain lookup case-insensitive

When searching for Pages custom domains in /internal/pages use
case-insensitive search in order to handle custom domains with mixed
case.

Related to https://gitlab.com/gitlab-org/gitlab/issues/207390.
parent bfd6f39a
...@@ -67,6 +67,10 @@ class PagesDomain < ApplicationRecord ...@@ -67,6 +67,10 @@ class PagesDomain < ApplicationRecord
scope :instance_serverless, -> { where(wildcard: true, scope: :instance, usage: :serverless) } scope :instance_serverless, -> { where(wildcard: true, scope: :instance, usage: :serverless) }
def self.find_by_domain_case_insensitive(domain)
find_by("LOWER(domain) = LOWER(?)", domain)
end
def verified? def verified?
!!verified_at !!verified_at
end end
......
---
title: 'Add index on LOWER(domain) for pages_domains'
merge_request: 25664
author:
type: other
# frozen_string_literal: true
class AddIndexOnPagesDomainOnDomainLowercase < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
INDEX_NAME = 'index_pages_domains_on_domain_lowercase'
disable_ddl_transaction!
def up
add_concurrent_index :pages_domains, 'LOWER(domain)', name: INDEX_NAME
end
def down
remove_concurrent_index_by_name :pages_domains, INDEX_NAME
end
end
...@@ -3061,6 +3061,7 @@ ActiveRecord::Schema.define(version: 2020_02_21_144534) do ...@@ -3061,6 +3061,7 @@ ActiveRecord::Schema.define(version: 2020_02_21_144534) do
t.boolean "wildcard", default: false, null: false t.boolean "wildcard", default: false, null: false
t.integer "usage", limit: 2, default: 0, null: false t.integer "usage", limit: 2, default: 0, null: false
t.integer "scope", limit: 2, default: 2, null: false t.integer "scope", limit: 2, default: 2, null: false
t.index "lower((domain)::text)", name: "index_pages_domains_on_domain_lowercase"
t.index ["certificate_source", "certificate_valid_not_after"], name: "index_pages_domains_need_auto_ssl_renewal", where: "(auto_ssl_enabled = true)" t.index ["certificate_source", "certificate_valid_not_after"], name: "index_pages_domains_need_auto_ssl_renewal", where: "(auto_ssl_enabled = true)"
t.index ["domain", "wildcard"], name: "index_pages_domains_on_domain_and_wildcard", unique: true t.index ["domain", "wildcard"], name: "index_pages_domains_on_domain_and_wildcard", unique: true
t.index ["project_id", "enabled_until"], name: "index_pages_domains_on_project_id_and_enabled_until" t.index ["project_id", "enabled_until"], name: "index_pages_domains_on_project_id_and_enabled_until"
......
...@@ -36,7 +36,7 @@ module API ...@@ -36,7 +36,7 @@ module API
present virtual_domain, with: Entities::Internal::Serverless::VirtualDomain present virtual_domain, with: Entities::Internal::Serverless::VirtualDomain
else else
# Handle Pages domains # Handle Pages domains
host = Namespace.find_by_pages_host(params[:host]) || PagesDomain.find_by_domain(params[:host]) host = Namespace.find_by_pages_host(params[:host]) || PagesDomain.find_by_domain_case_insensitive(params[:host])
no_content! unless host no_content! unless host
virtual_domain = host.pages_virtual_domain virtual_domain = host.pages_virtual_domain
......
...@@ -642,4 +642,12 @@ describe PagesDomain do ...@@ -642,4 +642,12 @@ describe PagesDomain do
end end
end end
end end
describe '.find_by_domain_case_insensitive' do
it 'lookup is case-insensitive' do
pages_domain = create(:pages_domain, domain: "Pages.IO")
expect(PagesDomain.find_by_domain_case_insensitive('pages.io')).to eq(pages_domain)
end
end
end end
...@@ -141,21 +141,29 @@ describe API::Internal::Pages do ...@@ -141,21 +141,29 @@ describe API::Internal::Pages do
context 'custom domain' do context 'custom domain' do
let(:namespace) { create(:namespace, name: 'gitlab-org') } let(:namespace) { create(:namespace, name: 'gitlab-org') }
let(:project) { create(:project, namespace: namespace, name: 'gitlab-ce') } let(:project) { create(:project, namespace: namespace, name: 'gitlab-ce') }
let!(:pages_domain) { create(:pages_domain, domain: 'pages.gitlab.io', project: project) } let!(:pages_domain) { create(:pages_domain, domain: 'pages.io', project: project) }
context 'when there are no pages deployed for the related project' do context 'when there are no pages deployed for the related project' do
it 'responds with 204 No Content' do it 'responds with 204 No Content' do
query_host('pages.gitlab.io') query_host('pages.io')
expect(response).to have_gitlab_http_status(:no_content) expect(response).to have_gitlab_http_status(:no_content)
end end
end end
context 'when there are pages deployed for the related project' do context 'when there are pages deployed for the related project' do
it 'domain lookup is case insensitive' do
deploy_pages(project)
query_host('Pages.IO')
expect(response).to have_gitlab_http_status(:ok)
end
it 'responds with the correct domain configuration' do it 'responds with the correct domain configuration' do
deploy_pages(project) deploy_pages(project)
query_host('pages.gitlab.io') query_host('pages.io')
expect(response).to have_gitlab_http_status(:ok) expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('internal/pages/virtual_domain') expect(response).to match_response_schema('internal/pages/virtual_domain')
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment