diff --git a/assets/javascripts/app/router.coffee b/assets/javascripts/app/router.coffee index 9497e33c..d86b9881 100644 --- a/assets/javascripts/app/router.coffee +++ b/assets/javascripts/app/router.coffee @@ -107,16 +107,23 @@ class app.Router if (path = location.pathname.replace /^\/{2,}/g, '/') isnt location.pathname page.replace path + location.search + location.hash, null, true - # When the path is "/#/path", replace it with "/path" - if @isRoot() and path = @getInitialPath() - page.replace path + location.search, null, true + if @isRoot() + if path = @getInitialPathFromHash() + page.replace path + location.search, null, true + else if path = @getInitialPathFromCookie() + page.replace path + location.search + location.hash, null, true return - getInitialPath: -> + getInitialPathFromHash: -> try (new RegExp "#/(.+)").exec(decodeURIComponent location.hash)?[1] catch + getInitialPathFromCookie: -> + if path = Cookies.get('initial_path') + Cookies.expire('initial_path') + path + replaceHash: (hash) -> page.replace location.pathname + location.search + (hash or ''), null, true return diff --git a/lib/app.rb b/lib/app.rb index f05c0e77..23359126 100644 --- a/lib/app.rb +++ b/lib/app.rb @@ -157,6 +157,15 @@ class App < Sinatra::Application def dark_theme? app_theme == 'dark' end + + def redirect_via_js(path) # courtesy of HTML5 App Cache + response.set_cookie :initial_path, value: path, expires: Time.now + 15, path: '/' + redirect '/', 302 + end + + def supports_js_redirection? + browser.modern? && !cookies.empty? + end end before do @@ -170,13 +179,17 @@ class App < Sinatra::Application end get '/' do - return redirect '/' unless request.query_string.empty? + return redirect '/' unless request.query_string.empty? # courtesy of HTML5 App Cache erb :index end %w(offline about news help).each do |page| get "/#{page}" do - redirect "/#/#{page}", 302 + if supports_js_redirection? + redirect_via_js "/#{page}" + else + redirect "/#/#{page}", 302 + end end end @@ -228,8 +241,8 @@ class App < Sinatra::Application redirect "/#{doc}#{type}/#{query_string_for_redirection}" elsif rest.length > 1 && rest.end_with?('/') redirect "/#{doc}#{type}#{rest[0...-1]}#{query_string_for_redirection}" - elsif docs.include?(doc) && browser.modern? - redirect "/##{request.path}", 302 + elsif docs.include?(doc) && supports_js_redirection? + redirect_via_js(request.path) else erb :other end diff --git a/test/app_test.rb b/test/app_test.rb index 9c0cf42e..94512900 100644 --- a/test/app_test.rb +++ b/test/app_test.rb @@ -5,6 +5,8 @@ require 'app' class AppTest < MiniTest::Spec include Rack::Test::Methods + MODERN_BROWSER = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:39.0) Gecko/20100101 Firefox/39.0' + def app App end @@ -40,13 +42,23 @@ class AppTest < MiniTest::Spec end describe "/[static-page]" do - it "redirects to /#/[static-page]" do + it "redirects to /#/[static-page] by default" do %w(offline about news help).each do |page| - get "/#{page}" + get "/#{page}", {}, 'HTTP_USER_AGENT' => MODERN_BROWSER assert last_response.redirect? assert_equal "http://example.org/#/#{page}", last_response['Location'] end end + + it "redirects via JS cookie when a cookie exists" do + %w(offline about news help).each do |page| + set_cookie('foo=bar') + get "/#{page}", {}, 'HTTP_USER_AGENT' => MODERN_BROWSER + assert last_response.redirect? + assert_equal 'http://example.org/', last_response['Location'] + assert last_response['Set-Cookie'].start_with?("initial_path=%2F#{page}; path=/; expires=") + end + end end describe "/search" do @@ -109,15 +121,16 @@ class AppTest < MiniTest::Spec describe "/[doc]" do it "renders when the doc exists and isn't enabled" do set_cookie('docs=css') - get '/html/', {}, 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:39.0) Gecko/20100101 Firefox/39.0' + get '/html/', {}, 'HTTP_USER_AGENT' => MODERN_BROWSER assert last_response.ok? end - it "redirects to root when the doc exists and is enabled" do + it "redirects via JS cookie when the doc exists and is enabled" do set_cookie('docs=html') - get '/html/', {}, 'HTTP_USER_AGENT' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:39.0) Gecko/20100101 Firefox/39.0' + get '/html/', {}, 'HTTP_USER_AGENT' => MODERN_BROWSER assert last_response.redirect? - assert_equal 'http://example.org/#/html/', last_response['Location'] + assert_equal 'http://example.org/', last_response['Location'] + assert last_response['Set-Cookie'].start_with?("initial_path=%2Fhtml%2F; path=/; expires=") end it "renders when the doc exists and is enabled, and the request is from Googlebot" do