Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions font_assets.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -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
120 changes: 69 additions & 51 deletions lib/font_assets/middleware.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

module FontAssets
class Middleware
attr_reader :origin, :options, :mime_types

def initialize(app, origin, options={})
@app = app
Expand All @@ -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
6 changes: 3 additions & 3 deletions lib/font_assets/mime_types.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
51 changes: 34 additions & 17 deletions spec/middleware_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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

Expand All @@ -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

Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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

Expand Down
6 changes: 3 additions & 3 deletions spec/mime_types_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
2 changes: 2 additions & 0 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -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
Expand Down