diff --git a/lib/shrimp.rb b/lib/shrimp.rb index f12222d..953bab0 100644 --- a/lib/shrimp.rb +++ b/lib/shrimp.rb @@ -2,4 +2,5 @@ require 'shrimp/source' require 'shrimp/phantom' require 'shrimp/middleware' +require 'shrimp/stateless_middleware' require 'shrimp/configuration' diff --git a/lib/shrimp/middleware.rb b/lib/shrimp/middleware.rb index 96e8050..9111c7a 100644 --- a/lib/shrimp/middleware.rb +++ b/lib/shrimp/middleware.rb @@ -92,29 +92,33 @@ def rendering_in_progress? end def render_as_pdf? - request_path_is_pdf = !!@request.path.match(%r{\.pdf$}) + return false unless request_path_is_pdf + return false if only_guard(:only, :path) + return false if except_guard(:except, :path) + return false if only_guard(:only_hosts, :host) + return false if except_guard(:except_hosts, :host) + true + end - if request_path_is_pdf && @conditions[:only] - rules = [@conditions[:only]].flatten - rules.any? do |pattern| - if pattern.is_a?(Regexp) - @request.path =~ pattern - else - @request.path[0, pattern.length] == pattern - end - end - elsif request_path_is_pdf && @conditions[:except] - rules = [@conditions[:except]].flatten - rules.map do |pattern| - if pattern.is_a?(Regexp) - return false if @request.path =~ pattern - else - return false if @request.path[0, pattern.length] == pattern - end + def request_path_is_pdf + !!@request.path.match(%r{\.pdf$}) + end + + def only_guard(guard, meth) + @conditions[guard] && !guard(guard, meth) + end + + def except_guard(guard, meth) + @conditions[guard] && guard(guard, meth) + end + + def guard(guard, meth) + [@conditions[guard]].flatten.any? do |pattern| + if pattern.is_a?(Regexp) + @request.send(meth) =~ pattern + else + @request.send(meth).send(:[], 0, pattern.length) == pattern end - return true - else - request_path_is_pdf end end diff --git a/lib/shrimp/stateless_middleware.rb b/lib/shrimp/stateless_middleware.rb new file mode 100644 index 0000000..d6a91d0 --- /dev/null +++ b/lib/shrimp/stateless_middleware.rb @@ -0,0 +1,56 @@ +module Shrimp + class StatelessMiddleware + def initialize(app, options = { }, conditions = { }) + @app = app + @options = options + @conditions = conditions + end + + def call(env) + @request = Rack::Request.new(env) + if render_as_pdf? + body = Phantom.new(@request.url.sub(%r{\.pdf$}, ''), @options, @request.cookies).to_string + response = [body] + headers = { } + headers["Content-Length"] = (body.respond_to?(:bytesize) ? body.bytesize : body.size).to_s + headers["Content-Type"] = "application/pdf" + [200, headers, response] + else + @app.call(env) + end + end + + private + + def render_as_pdf? + return false unless request_path_is_pdf + return false if only_guard(:only, :path) + return false if except_guard(:except, :path) + return false if only_guard(:only_hosts, :host) + return false if except_guard(:except_hosts, :host) + true + end + + def request_path_is_pdf + !!@request.path.match(%r{\.pdf$}) + end + + def only_guard(guard, meth) + @conditions[guard] && !guard(guard, meth) + end + + def except_guard(guard, meth) + @conditions[guard] && guard(guard, meth) + end + + def guard(guard, meth) + [@conditions[guard]].flatten.any? do |pattern| + if pattern.is_a?(Regexp) + @request.send(meth) =~ pattern + else + @request.send(meth).send(:[], 0, pattern.length) == pattern + end + end + end + end +end diff --git a/spec/shrimp/middleware_spec.rb b/spec/shrimp/middleware_spec.rb index 48e720f..f080a70 100644 --- a/spec/shrimp/middleware_spec.rb +++ b/spec/shrimp/middleware_spec.rb @@ -105,12 +105,12 @@ def mock_app(options = { }, conditions = { }) context "except" do before { mock_app(options, :except => %w(/secret)) } - it "render pdf for set only option" do + it "render pdf for set except option" do get '/invoice/test.pdf' @middleware.send(:'render_as_pdf?').should be true end - it "render pdf for set only option" do + it "render pdf for set except option" do get '/public/test.pdf' @middleware.send(:'render_as_pdf?').should be true end @@ -120,4 +120,30 @@ def mock_app(options = { }, conditions = { }) @middleware.send(:'render_as_pdf?').should be false end end + + context "only_hosts" do + before { mock_app(options, :only_hosts => [%r[^test.example.org]]) } + it "render pdf for set only_hosts option" do + get '/test.pdf', {}, {'HTTP_HOST' => 'test.example.org' } + @middleware.send(:'render_as_pdf?').should be true + end + + it "not render pdf for any other hosts" do + get '/test.pdf' + @middleware.send(:'render_as_pdf?').should be false + end + end + + context "except_hosts" do + before { mock_app(options, :except_hosts => [%r[^test.example.org]]) } + it "render pdf for set except_hosts option" do + get '/invoice/test.pdf' + @middleware.send(:'render_as_pdf?').should be true + end + + it "not render pdf for any other hosts" do + get '/secret/test.pdf', {}, {'HTTP_HOST' => 'test.example.org' } + @middleware.send(:'render_as_pdf?').should be false + end + end end