Commit f8dd1195 authored by Adam Niedzielski's avatar Adam Niedzielski

Test all enabled routes in ETag caching middleware and fix pipeline routes

Extract route matching logic to Gitlab::EtagCaching::Router.

Fix pipeline routes:
1. "project_pipelines" has to come after "commit_pipelines" and
"merge_request_pipelines" because it is more generic
2. "commit_pipelines": "\s" (any whitespace character) => "\S"
(any non-whitespace character).
parent c98add15
module Gitlab module Gitlab
module EtagCaching module EtagCaching
class Middleware class Middleware
RESERVED_WORDS = NamespaceValidator::WILDCARD_ROUTES.map { |word| "/#{word}/" }.join('|')
ROUTES = [
{
regexp: %r(^(?!.*(#{RESERVED_WORDS})).*/noteable/issue/\d+/notes\z),
name: 'issue_notes'
},
{
regexp: %r(^(?!.*(#{RESERVED_WORDS})).*/issues/\d+/rendered_title\z),
name: 'issue_title'
},
{
regexp: %r(^(?!.*(#{RESERVED_WORDS})).*/pipelines\.json\z),
name: 'project_pipelines'
},
{
regexp: %r(^(?!.*(#{RESERVED_WORDS})).*/commit/\s+/pipelines\.json\z),
name: 'commit_pipelines'
},
{
regexp: %r(^(?!.*(#{RESERVED_WORDS})).*/merge_requests/new\.json\z),
name: 'new_merge_request_pipelines'
},
{
regexp: %r(^(?!.*(#{RESERVED_WORDS})).*/merge_requests/\d+/pipelines\.json\z),
name: 'merge_request_pipelines'
}
].freeze
def initialize(app) def initialize(app)
@app = app @app = app
end end
def call(env) def call(env)
route = match_current_route(env) route = Gitlab::EtagCaching::Router.match(env)
return @app.call(env) unless route return @app.call(env) unless route
track_event(:etag_caching_middleware_used, route) track_event(:etag_caching_middleware_used, route)
...@@ -55,10 +27,6 @@ module Gitlab ...@@ -55,10 +27,6 @@ module Gitlab
private private
def match_current_route(env)
ROUTES.find { |route| route[:regexp].match(env['PATH_INFO']) }
end
def get_etag(env) def get_etag(env)
cache_key = env['PATH_INFO'] cache_key = env['PATH_INFO']
store = Gitlab::EtagCaching::Store.new store = Gitlab::EtagCaching::Store.new
...@@ -95,7 +63,7 @@ module Gitlab ...@@ -95,7 +63,7 @@ module Gitlab
end end
def track_event(name, route) def track_event(name, route)
Gitlab::Metrics.add_event(name, endpoint: route[:name]) Gitlab::Metrics.add_event(name, endpoint: route.name)
end end
end end
end end
......
module Gitlab
module EtagCaching
class Router
Route = Struct.new(:regexp, :name)
RESERVED_WORDS = NamespaceValidator::WILDCARD_ROUTES.map { |word| "/#{word}/" }.join('|')
ROUTES = [
Gitlab::EtagCaching::Router::Route.new(
%r(^(?!.*(#{RESERVED_WORDS})).*/noteable/issue/\d+/notes\z),
'issue_notes'
),
Gitlab::EtagCaching::Router::Route.new(
%r(^(?!.*(#{RESERVED_WORDS})).*/issues/\d+/rendered_title\z),
'issue_title'
),
Gitlab::EtagCaching::Router::Route.new(
%r(^(?!.*(#{RESERVED_WORDS})).*/commit/\S+/pipelines\.json\z),
'commit_pipelines'
),
Gitlab::EtagCaching::Router::Route.new(
%r(^(?!.*(#{RESERVED_WORDS})).*/merge_requests/new\.json\z),
'new_merge_request_pipelines'
),
Gitlab::EtagCaching::Router::Route.new(
%r(^(?!.*(#{RESERVED_WORDS})).*/merge_requests/\d+/pipelines\.json\z),
'merge_request_pipelines'
),
Gitlab::EtagCaching::Router::Route.new(
%r(^(?!.*(#{RESERVED_WORDS})).*/pipelines\.json\z),
'project_pipelines'
)
].freeze
def self.match(env)
ROUTES.find { |route| route.regexp.match(env['PATH_INFO']) }
end
end
end
end
require 'spec_helper'
describe Gitlab::EtagCaching::Router do
it 'matches issue notes endpoint' do
env = build_env(
'/my-group/and-subgroup/here-comes-the-project/noteable/issue/1/notes'
)
result = described_class.match(env)
expect(result).to be_present
expect(result.name).to eq 'issue_notes'
end
it 'matches issue title endpoint' do
env = build_env(
'/my-group/my-project/issues/123/rendered_title'
)
result = described_class.match(env)
expect(result).to be_present
expect(result.name).to eq 'issue_title'
end
it 'matches project pipelines endpoint' do
env = build_env(
'/my-group/my-project/pipelines.json'
)
result = described_class.match(env)
expect(result).to be_present
expect(result.name).to eq 'project_pipelines'
end
it 'matches commit pipelines endpoint' do
env = build_env(
'/my-group/my-project/commit/aa8260d253a53f73f6c26c734c72fdd600f6e6d4/pipelines.json'
)
result = described_class.match(env)
expect(result).to be_present
expect(result.name).to eq 'commit_pipelines'
end
it 'matches new merge request pipelines endpoint' do
env = build_env(
'/my-group/my-project/merge_requests/new.json'
)
result = described_class.match(env)
expect(result).to be_present
expect(result.name).to eq 'new_merge_request_pipelines'
end
it 'matches merge request pipelines endpoint' do
env = build_env(
'/my-group/my-project/merge_requests/234/pipelines.json'
)
result = described_class.match(env)
expect(result).to be_present
expect(result.name).to eq 'merge_request_pipelines'
end
it 'does not match blob with confusing name' do
env = build_env(
'/my-group/my-project/blob/master/pipelines.json'
)
result = described_class.match(env)
expect(result).to be_blank
end
def build_env(path)
{ 'PATH_INFO' => path }
end
end
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