diff --git a/font_assets.gemspec b/font_assets.gemspec index 3715245..5d59db9 100644 --- a/font_assets.gemspec +++ b/font_assets.gemspec @@ -20,4 +20,5 @@ Gem::Specification.new do |s| s.add_dependency "rack" s.add_development_dependency "rspec", "~>2.0" + s.add_development_dependency "rspec-its", "~> 1.0" end diff --git a/lib/font_assets/middleware.rb b/lib/font_assets/middleware.rb index 32dc028..9d225ff 100644 --- a/lib/font_assets/middleware.rb +++ b/lib/font_assets/middleware.rb @@ -3,6 +3,7 @@ module FontAssets class Middleware + attr_reader :origin, :options, :mime_types def initialize(app, origin, options={}) @app = app @@ -11,73 +12,90 @@ def initialize(app, origin, options={}) @mime_types = FontAssets::MimeTypes.new(Rack::Mime::MIME_TYPES) end - def access_control_headers - { - "Access-Control-Allow-Origin" => origin, - "Access-Control-Allow-Methods" => "GET", - "Access-Control-Allow-Headers" => "x-requested-with", - "Access-Control-Max-Age" => "3628800" - } - end - def call(env) - @ssl_request = Rack::Request.new(env).scheme == "https" - # intercept the "preflight" request - if env["REQUEST_METHOD"] == "OPTIONS" - return [200, access_control_headers, []] - else - code, headers, body = @app.call(env) - set_headers! headers, body, env["PATH_INFO"] - [code, headers, body] + FontAssetsRequest.new(self, env).do_request do + @app.call(env) end end + class FontAssetsRequest + def initialize(middleware, env) + @middleware = middleware + @request = Rack::Request.new(env) + end + + def do_request + if font_asset? + if @request.options? + return [200, access_control_headers, []] + else + code, headers, body = yield - private + headers.merge!(access_control_headers) + headers.merge!('Content-Type' => mime_type) if headers['Content-Type'] - def origin - if !wildcard_origin? and allow_ssl? and ssl_request? - uri = URI(@origin) - uri.scheme = "https" - uri.to_s - else - @origin + [code, headers, body] + end + else + yield + end end - end - def wildcard_origin? - @origin == '*' - end + private + def access_control_headers + { + "Access-Control-Allow-Origin" => origin, + "Access-Control-Allow-Methods" => "GET", + "Access-Control-Allow-Headers" => "x-requested-with", + "Access-Control-Max-Age" => "3628800" + } + end - def ssl_request? - @ssl_request - end + def origin + if !wildcard_origin? and allow_ssl? and ssl_request? + uri = URI(@middleware.origin) + uri.scheme = "https" + uri.to_s + else + @middleware.origin + end + end - def allow_ssl? - @options[:allow_ssl] - end + def wildcard_origin? + @middleware.origin == '*' + end - def extension(path) - if path.nil? || path.length == 0 - nil - else - "." + path.split("?").first.split(".").last + def ssl_request? + @request.scheme == "https" end - end - def font_asset?(path) - @mime_types.font? extension(path) - end + def allow_ssl? + @middleware.options[:allow_ssl] + end - def set_headers!(headers, body, path) - if ext = extension(path) and font_asset?(ext) - headers.merge!(access_control_headers) - headers.merge!('Content-Type' => mime_type(ext)) if headers['Content-Type'] + def path + @request.path_info + end + + def font_asset? + mime_types.font? extension end - end - def mime_type(extension) - @mime_types[extension] + def mime_type + mime_types[extension] + end + + def mime_types + @middleware.mime_types + end + + def extension + if path.nil? || path.length == 0 + nil + else + "." + path.split("?").first.split(".").last + end + end end end end diff --git a/lib/font_assets/mime_types.rb b/lib/font_assets/mime_types.rb index 7d4429d..240d6c8 100644 --- a/lib/font_assets/mime_types.rb +++ b/lib/font_assets/mime_types.rb @@ -4,9 +4,9 @@ class MimeTypes MIME_TYPES = { '.eot' => 'application/vnd.ms-fontobject', '.svg' => 'image/svg+xml', - '.ttf' => 'application/x-font-ttf', - '.otf' => 'application/x-font-otf', - '.woff' => 'application/x-font-woff' + '.ttf' => 'application/octet-stream', + '.otf' => 'application/font-sfnt', + '.woff' => 'application/font-woff' } def initialize(types, default = DEFAULT_TYPE.dup) diff --git a/spec/middleware_spec.rb b/spec/middleware_spec.rb index 8f40b7d..550218e 100644 --- a/spec/middleware_spec.rb +++ b/spec/middleware_spec.rb @@ -22,7 +22,7 @@ its(["Access-Control-Max-Age"]) { should == "3628800" } its(['Access-Control-Allow-Methods']) { should == 'GET' } its(['Access-Control-Allow-Origin']) { should == 'https://test.origin' } - its(['Content-Type']) { should == 'application/x-font-ttf' } + its(['Content-Type']) { should == 'application/octet-stream' } end end @@ -36,7 +36,7 @@ its(["Access-Control-Max-Age"]) { should == "3628800" } its(['Access-Control-Allow-Methods']) { should == 'GET' } its(['Access-Control-Allow-Origin']) { should == 'http://test.origin' } - its(['Content-Type']) { should == 'application/x-font-ttf' } + its(['Content-Type']) { should == 'application/octet-stream' } end end @@ -55,7 +55,7 @@ its(["Access-Control-Max-Age"]) { should == "3628800" } its(['Access-Control-Allow-Methods']) { should == 'GET' } its(['Access-Control-Allow-Origin']) { should == '*' } - its(['Content-Type']) { should == 'application/x-font-ttf' } + its(['Content-Type']) { should == 'application/octet-stream' } end end @@ -69,7 +69,7 @@ its(["Access-Control-Max-Age"]) { should == "3628800" } its(['Access-Control-Allow-Methods']) { should == 'GET' } its(['Access-Control-Allow-Origin']) { should == '*' } - its(['Content-Type']) { should == 'application/x-font-ttf' } + its(['Content-Type']) { should == 'application/octet-stream' } end end end @@ -85,7 +85,7 @@ its(["Access-Control-Max-Age"]) { should == "3628800" } its(['Access-Control-Allow-Methods']) { should == 'GET' } its(['Access-Control-Allow-Origin']) { should == 'http://test.origin' } - its(['Content-Type']) { should == 'application/x-font-ttf' } + its(['Content-Type']) { should == 'application/octet-stream' } end end end @@ -138,24 +138,41 @@ context 'for OPTIONS requests' do let(:app) { load_app 'http://test.options' } - let(:response) { request app, '/test.ttf', :method => 'OPTIONS' } - context 'the response headers' do - subject { response[1] } + context 'to font assets' do + let(:response) { request app, '/test.ttf', :method => 'OPTIONS' } - its(["Access-Control-Allow-Headers"]) { should == "x-requested-with" } - its(["Access-Control-Max-Age"]) { should == "3628800" } - its(['Access-Control-Allow-Methods']) { should == 'GET' } - its(['Access-Control-Allow-Origin']) { should == 'http://test.options' } + context 'the response headers' do + subject { response[1] } - it 'should not contain a Content-Type' do - subject['Content-Type'].should be_nil + its(["Access-Control-Allow-Headers"]) { should == "x-requested-with" } + its(["Access-Control-Max-Age"]) { should == "3628800" } + its(['Access-Control-Allow-Methods']) { should == 'GET' } + its(['Access-Control-Allow-Origin']) { should == 'http://test.options' } + + it 'should not contain a Content-Type' do + subject['Content-Type'].should be_nil + end + end + + context 'the response body' do + subject { response[2] } + it { should be_empty } end end - context 'the response body' do - subject { response[2] } - it { should be_empty } + context 'to non-font assets' do + let(:response) { request app, '/test', method: 'OPTIONS' } + + context 'the response headers' do + subject { response[1] } + + its(["Access-Control-Allow-Headers"]) { should be_nil } + its(["Access-Control-Max-Age"]) { should be_nil } + its(['Access-Control-Allow-Methods']) { should be_nil } + its(['Access-Control-Allow-Origin']) { should be_nil } + its(['Content-Type']) { should == 'text/plain' } + end end end diff --git a/spec/mime_types_spec.rb b/spec/mime_types_spec.rb index a835b0e..a2748a4 100644 --- a/spec/mime_types_spec.rb +++ b/spec/mime_types_spec.rb @@ -31,7 +31,7 @@ let(:types) { described_class.new({}) } it 'returns the mime type of the passed extension' do - types['.woff'].should == 'application/x-font-woff' + types['.woff'].should == 'application/font-woff' end it 'returns the default mime type for unknown extensions' do @@ -44,12 +44,12 @@ it 'is true for known font extensions' do FontAssets::MimeTypes::MIME_TYPES.keys.each do |key| - types.font?(key).should be_true + types.font?(key).should be_truthy end end it 'is false for unrecognized font extensions' do - types.font?('.bad').should be_false + types.font?('.bad').should be_falsey end end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b8190e7..4e456be 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,3 +1,5 @@ +require 'rspec/its' + RSpec.configure do |config| config.treat_symbols_as_metadata_keys_with_true_values = true config.run_all_when_everything_filtered = true