middleware to remove the SEO trailing slash
did
committed Feb 19, 2015
commit d242687e92b191208c36bdb19223a451a64a4ec9
Showing 10
changed files with
86 additions
and 19 deletions
Gemfile.lock
+5
-3
| @@ | @@ -19,6 +19,7 @@ PATH |
| moneta (~> 0.8.0) | |
| morphine (~> 0.1.1) | |
| rack-cache (~> 1.2) | |
| + | rack-rewrite (~> 1.5.1) |
| rack_csrf (~> 2.5.0) | |
| sprockets (~> 2.12.3) | |
| sprockets-sass (~> 1.3.1) | |
| @@ | @@ -54,14 +55,14 @@ GEM |
| debugger-linecache (~> 1.2) | |
| slop (~> 3.6) | |
| chronic (0.10.2) | |
| - | chunky_png (1.3.3) |
| + | chunky_png (1.3.4) |
| codeclimate-test-reporter (0.4.6) | |
| simplecov (>= 0.7.1, < 1.0.0) | |
| coderay (1.1.0) | |
| coffee-script (2.3.0) | |
| coffee-script-source | |
| execjs | |
| - | coffee-script-source (1.9.0) |
| + | coffee-script-source (1.9.1) |
| colorize (0.7.5) | |
| columnize (0.9.0) | |
| compass (1.0.3) | |
| @@ | @@ -142,6 +143,7 @@ GEM |
| rack (1.6.0) | |
| rack-cache (1.2) | |
| rack (>= 0.4) | |
| + | rack-rewrite (1.5.1) |
| rack-test (0.6.3) | |
| rack (>= 1.0) | |
| rack_csrf (2.5.0) | |
| @@ | @@ -173,7 +175,7 @@ GEM |
| rspec-mocks (3.1.3) | |
| rspec-support (~> 3.1.0) | |
| rspec-support (3.1.2) | |
| - | sass (3.4.11) |
| + | sass (3.4.12) |
| simplecov (0.9.1) | |
| docile (~> 1.1.0) | |
| multi_json (~> 1.0) | |
locomotive/steam/configuration.rb b/lib/locomotive/steam/configuration.rb
+20
-1
| @@ | @@ -22,7 +22,8 @@ module Locomotive |
| # Manage the list of middlewares used by the rack stack. | |
| # | |
| - | # Examples: |
| + | # Example: |
| + | # |
| # Locomotive::Steam.configure do |config| | |
| # ... | |
| # config.middleware.remove Rack::Lint | |
| @@ | @@ -98,6 +99,24 @@ module Locomotive |
| attr_accessor :moneta | |
| def moneta; @moneta.nil? ? { store: Moneta.new(:Memory, expires: true) } : @moneta; end | |
| + | # Lambda called once a Services instance has been built. |
| + | # It is used when we want to change one of the services |
| + | # |
| + | # Example: |
| + | # |
| + | # Locomotive::Steam.configure do |config| |
| + | # |
| + | # config.services_hook = -> (services) { |
| + | # require 'my_repositories' |
| + | # services.repositories = MyRepositories.new |
| + | # } |
| + | # |
| + | # end |
| + | # |
| + | # default: nil |
| + | # |
| + | attr_accessor :services_hook |
| + | |
| end | |
| end | |
locomotive/steam/decorators/template_decorator.rb b/lib/locomotive/steam/decorators/template_decorator.rb
+2
-0
| @@ | @@ -1,3 +1,5 @@ |
| + | require_relative 'i18n_decorator' |
| + | |
| module Locomotive | |
| module Steam | |
| module Decorators | |
locomotive/steam/middlewares/stack_proxy.rb b/lib/locomotive/steam/middlewares/stack_proxy.rb
+8
-8
| @@ | @@ -9,16 +9,16 @@ module Locomotive::Steam::Middlewares |
| instance_eval(&block) if block_given? | |
| end | |
| - | def use(*args) |
| - | @list << args |
| + | def use(*args, &block) |
| + | @list << [args, block] |
| end | |
| - | def insert_before(index, *args) |
| - | @list.insert(index_of(index), args) |
| + | def insert_before(index, *args, &block) |
| + | @list.insert(index_of(index), [args, block]) |
| end | |
| - | def insert_after(index, *args) |
| - | @list.insert(index_of(index) + 1, args) |
| + | def insert_after(index, *args, &block) |
| + | @list.insert(index_of(index) + 1, [args, block]) |
| end | |
| def delete(index) | |
| @@ | @@ -29,7 +29,7 @@ module Locomotive::Steam::Middlewares |
| def inject(builder) | |
| @list.each do |args| | |
| - | builder.use(*args) |
| + | builder.use(*(args[0]), &args[1]) |
| end | |
| end | |
| @@ | @@ -37,7 +37,7 @@ module Locomotive::Steam::Middlewares |
| if index.is_a?(Integer) | |
| index | |
| else | |
| - | @list.index { |args| args[0] == index } |
| + | @list.index { |args| args[0][0] == index } |
| end | |
| end | |
locomotive/steam/server.rb b/lib/locomotive/steam/server.rb
+2
-0
| @@ | @@ -4,6 +4,7 @@ require 'mimetype_fu' |
| require 'mime-types' | |
| require 'mime/types' | |
| + | require 'rack/rewrite' |
| require 'rack/csrf' | |
| require 'rack/session/moneta' | |
| require 'rack/builder' | |
| @@ | @@ -21,6 +22,7 @@ module Locomotive::Steam |
| server, configuration = self, self.configuration | |
| -> (stack) { | |
| + | use(Rack::Rewrite) { r301 %r{^/(.*)/$}, '/$1' } |
| use Middlewares::Favicon | |
| if configuration.serve_assets | |
locomotive/steam/services.rb b/lib/locomotive/steam/services.rb
+5
-1
| @@ | @@ -7,7 +7,11 @@ module Locomotive |
| module Services | |
| def self.build_instance(request = nil) | |
| - | Instance.new(request) |
| + | Instance.new(request).tap do |service| |
| + | if Locomotive::Steam.configuration.services_hook |
| + | Locomotive::Steam.configuration.services_hook.call(service) |
| + | end |
| + | end |
| end | |
| class Instance < Struct.new(:request) | |
locomotivecms_steam.gemspec
+1
-0
| @@ | @@ -25,6 +25,7 @@ Gem::Specification.new do |spec| |
| spec.add_dependency 'httparty', '~> 0.13.3' | |
| spec.add_dependency 'chronic', '~> 0.10.2' | |
| + | spec.add_dependency 'rack-rewrite', '~> 1.5.1' |
| spec.add_dependency 'rack-cache', '~> 1.2' | |
| spec.add_dependency 'dragonfly', '~> 1.0.7' | |
| spec.add_dependency 'moneta', '~> 0.8.0' | |
spec/integration/server/basic_spec.rb
+12
-0
| @@ | @@ -60,6 +60,18 @@ describe Locomotive::Steam::Server do |
| end | |
| + | describe 'seo trailing slash' do |
| + | |
| + | let(:url) { '/events/' } |
| + | subject { get url; last_response } |
| + | |
| + | it 'redirects to the url without the trailing slash' do |
| + | expect(subject.status).to eq(301) |
| + | expect(subject.location).to eq('/events') |
| + | end |
| + | |
| + | end |
| + | |
| describe 'snippets' do | |
| it 'includes a basic snippet' do | |
spec/unit/middlewares/stack_proxy_spec.rb
+6
-6
| @@ | @@ -16,7 +16,7 @@ describe Locomotive::Steam::Middlewares::StackProxy do |
| it 'adds it to the list' do | |
| expect(subject.list.size).to eq 1 | |
| - | expect(subject.list.first).to eq [DefaultMiddleware] |
| + | expect(subject.list.first).to eq [[DefaultMiddleware], nil] |
| end | |
| end | |
| @@ | @@ -28,7 +28,7 @@ describe Locomotive::Steam::Middlewares::StackProxy do |
| it 'adds it to the operations' do | |
| expect(proxy.list.size).to eq 1 | |
| - | expect(proxy.list.first).to eq [DefaultMiddleware] |
| + | expect(proxy.list.first).to eq [[DefaultMiddleware], nil] |
| end | |
| end | |
| @@ | @@ -49,10 +49,10 @@ describe Locomotive::Steam::Middlewares::StackProxy do |
| it do | |
| is_expected.to eq([ | |
| - | [DefaultMiddleware], |
| - | [FooMiddleware], |
| - | [FancyMiddleware], |
| - | [BarMiddleware, { answer: 42 }] |
| + | [[DefaultMiddleware], nil], |
| + | [[FooMiddleware], nil], |
| + | [[FancyMiddleware], nil], |
| + | [[BarMiddleware, { answer: 42 }], nil] |
| ]) | |
| end | |
spec/unit/services_spec.rb
+25
-0
| @@ | @@ -0,0 +1,25 @@ |
| + | require 'spec_helper' |
| + | |
| + | describe Locomotive::Steam::Services do |
| + | |
| + | subject { Locomotive::Steam::Services.build_instance(nil) } |
| + | |
| + | describe 'configuration with a services hook' do |
| + | |
| + | before do |
| + | Locomotive::Steam.configure do |config| |
| + | config.services_hook = -> (services) { |
| + | services.repositories = MyService.new |
| + | } |
| + | end |
| + | end |
| + | |
| + | after { Locomotive::Steam.configure { |c| c.services_hook = nil } } |
| + | |
| + | it { expect(subject.repositories).to be_instance_of(MyService) } |
| + | |
| + | end |
| + | |
| + | class MyService; end |
| + | |
| + | end |