diff --git a/lib/travis/web/app.rb b/lib/travis/web/app.rb index f6420ac0..31466a28 100644 --- a/lib/travis/web/app.rb +++ b/lib/travis/web/app.rb @@ -11,12 +11,18 @@ class Travis::Web::App # Simple Rack router that behaves like a hash. # Key is the path, value the response. class Router < DelegateClass(Hash) - def initialize + attr_reader :main_app + def initialize(main_app) + @main_app = main_app super({}) end def call(env) - self[env['PATH_INFO']] + if main_app.custom_branch?(env) + main_app.response_for_custom_branch(env) + else + self[env['PATH_INFO']] + end end end @@ -31,7 +37,7 @@ class Travis::Web::App @options = options @environment = options.fetch(:environment) @root = options.fetch(:root) - @router = Router.new + @router = Router.new(self) @app = builder.to_app @version = File.read File.expand_path('version', root) @last_modified = Time.now @@ -43,16 +49,53 @@ class Travis::Web::App app.call(env) end + def response_for_custom_branch(env) + status, headers, body = response_for File.join(root, 'index.html'), custom_branch: custom_branch(env) + response = Rack::Response.new body, status, headers + + if disable_custom_branch?(env) + response.delete_cookie 'custom_branch' + elsif custom_branch_from_params(env) + response.set_cookie 'custom_branch', value: custom_branch_from_params(env), expires: Time.now + 31536000 + end + + response.finish + end + + def custom_branch?(env) + custom_branch(env) || disable_custom_branch?(env) + end + private + def disable_custom_branch?(env) + env['QUERY_STRING'] =~ /disable[_-]custom[_-]branch/ + end + + def custom_branch_from_params(env) + branch = custom_branch_from_string env['QUERY_STRING'] + end + + def custom_branch_from_cookie(env) + custom_branch_from_string env['HTTP_COOKIE'] + end + + def custom_branch_from_string(string) + $1 if string =~ /(? content.bytesize.to_s, @@ -113,13 +156,18 @@ class Travis::Web::App Rack::Mime.mime_type File.extname(file) end - def set_config(string) + def set_config(string, options = {}) string.gsub! %r(]*>) do %() end - string.gsub! %r{(src|href)="(\/?)((styles|scripts)\/[^"]*)"} do - %(#$1="#$2#{version}/#$3") + string.gsub! %r{(src|href)="(?:\/?)((styles|scripts)\/[^"]*)"} do + if options[:custom_branch] + url = "https://s3.amazonaws.com/travis-web-production/assets/#{options[:custom_branch]}/#{$2}" + %(#$1="#{url}") + else + %(#$1="/#{version}/#$2") + end end end diff --git a/spec/app_spec.rb b/spec/app_spec.rb index 3b4f4698..584616ba 100644 --- a/spec/app_spec.rb +++ b/spec/app_spec.rb @@ -30,4 +30,24 @@ describe Travis::Web::App do example { headers['Cache-Control'].should be == 'no-cache' } example { headers['Vary'].split(',').should_not include('Accept') } end + + describe 'custom branch' do + context 'when passing custom branch as a param' do + before { get('/?custom-branch=foo') } + example { last_response.should be_ok } + example { last_response.body.should include('/assets/foo/styles/app.css') } + example { last_response.body.should include('/assets/foo/scripts/app.js') } + example { headers['Set-Cookie'].should include('custom_branch=foo') } + end + + context 'disabling custom branch' do + before { get('/?disable-custom-branch=true') } + example { last_response.should be_ok } + example { last_response.body.should =~ %r{src="/[^\/]+/scripts/app.js} } + example { last_response.body.should_not include('/assets/true/styles/app.css') } + example { last_response.body.should_not include('/assets/foo/styles/app.css') } + example { last_response.body.should_not include('/assets/foo/scripts/app.js') } + example { headers['Set-Cookie'].should include('custom_branch=;') } + end + end end