font_assets 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +2 -0
- data/CHANGELOG.md +29 -0
- data/README.md +78 -9
- data/font_assets.gemspec +2 -3
- data/lib/font_assets.rb +0 -2
- data/lib/font_assets/middleware.rb +19 -4
- data/lib/font_assets/mime_types.rb +38 -0
- data/lib/font_assets/railtie.rb +0 -7
- data/lib/font_assets/version.rb +1 -1
- data/spec/middleware_spec.rb +80 -0
- data/spec/mime_types_spec.rb +55 -0
- data/spec/spec_helper.rb +5 -0
- metadata +35 -4
data/.rspec
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
### master
|
2
|
+
|
3
|
+
### 0.1.0 / 2012-01-18
|
4
|
+
|
5
|
+
[full changelog](https://github.com/rubymaverick/font_assets/compare/v0.0.2...v0.1.0)
|
6
|
+
|
7
|
+
Enhancements
|
8
|
+
|
9
|
+
* Refactor MIME type settings into a local object.
|
10
|
+
* Add RSpec specs on the middleware and mime type handler.
|
11
|
+
* Update the README with more detail and examples.
|
12
|
+
* Fixed a typo in "ttf" in the middleware.
|
13
|
+
* Removed duplicate Railtie definition.
|
14
|
+
|
15
|
+
Bug Fixes
|
16
|
+
|
17
|
+
* Fix MIME types not being properly set in recent versions of Rack (starting in [Rack 1.3.0](https://github.com/rack/rack/commit/469518f7d971ba99fc335cf546d605d2364c81aa))
|
18
|
+
|
19
|
+
### 0.0.2 / 2011-12-15
|
20
|
+
|
21
|
+
[full changelog](https://github.com/rubymaverick/font_assets/compare/v0.0.1...v0.0.2)
|
22
|
+
|
23
|
+
Enhancements
|
24
|
+
|
25
|
+
* Make MIME setting more future-compatible by optionally setting it.
|
26
|
+
|
27
|
+
### 0.0.1 / 2011-12-15
|
28
|
+
|
29
|
+
Initial release.
|
data/README.md
CHANGED
@@ -1,32 +1,101 @@
|
|
1
1
|
Font Assets
|
2
2
|
=============
|
3
3
|
|
4
|
-
This little gem helps serve font-face assets in Rails 3.1. It really does these
|
4
|
+
This little gem helps serve font-face assets in Rails 3.1. It really does these
|
5
|
+
two things:
|
5
6
|
|
6
|
-
|
7
|
-
|
7
|
+
* Responds with "proper" mime types for woff, eot, tff, and svg font files, and
|
8
|
+
* Sets Access-Control-Allow-Origin response headers for font assets, which Firefox requires for cross domain fonts.
|
9
|
+
|
10
|
+
In addition, it will also respond to the pre-flight OPTIONS requests made by
|
11
|
+
supporting browsers (Firefox).
|
8
12
|
|
9
13
|
Install
|
10
14
|
-------
|
11
15
|
|
12
16
|
Add `font_assets` to your Gemfile:
|
13
17
|
|
14
|
-
|
18
|
+
```ruby
|
19
|
+
gem 'font_assets'
|
20
|
+
```
|
15
21
|
|
16
22
|
|
17
23
|
Usage
|
18
24
|
-----
|
19
25
|
|
20
|
-
|
26
|
+
By default, in a Rails application, this gem should Just Work™. However, the
|
27
|
+
default settings allow any requesting site to use the linked fonts, due to the
|
28
|
+
Allowed Origin being '*', by default. This is only useful for browsers which
|
29
|
+
support this feature (Firefox), but restricting it to certain domains may be
|
30
|
+
beneficial.
|
31
|
+
|
32
|
+
Set the origin domain that will get set in the `Access-Control-Allow-Origin`
|
33
|
+
header:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
# in config/environments/production.rb
|
37
|
+
config.font_assets.origin = 'http://codeschool.com'
|
38
|
+
```
|
39
|
+
|
40
|
+
The origin domain must match the domain of the site serving the page that is
|
41
|
+
requesting the font, not the host of the font. For example, if you are using a
|
42
|
+
CDN to serve your assets (like CloudFront), and the full path to the font asset
|
43
|
+
is `http://d3rd6rvl24noqd.cloudfront.net/assets/fonts/Pacifico-webfont-734f1436e605566ae2f1c132905e28b2.woff`,
|
44
|
+
but the URI the user is visiting is `http://coffeescript.codeschool.com/level/1`,
|
45
|
+
you'd want to set the origin header to this:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
config.font_assets.origin = 'http://coffeescript.codeschool.com'
|
49
|
+
```
|
50
|
+
|
51
|
+
An Example Response
|
52
|
+
-------------------
|
21
53
|
|
22
|
-
|
54
|
+
Below is an example response for a .woff font asset on a Rails 3.1 application
|
55
|
+
running behind several proxies and caches (including CloudFront):
|
23
56
|
|
24
|
-
|
57
|
+
```
|
58
|
+
$ curl -i http://d1tijy5l7mg5kk.cloudfront.net/assets/ubuntu/Ubuntu-Bold-webfont-4bcb5239bfd34be67bc07901959fc6e1.woff
|
59
|
+
HTTP/1.0 200 OK
|
60
|
+
Server: nginx
|
61
|
+
Date: Sat, 14 Jan 2012 19:45:19 GMT
|
62
|
+
Content-Type: application/x-font-woff
|
63
|
+
Last-Modified: Sat, 14 Jan 2012 16:58:14 GMT
|
64
|
+
Cache-Control: public, max-age=31557600
|
65
|
+
Access-Control-Allow-Origin: http://www.codeschool.com
|
66
|
+
Access-Control-Allow-Methods: GET
|
67
|
+
Access-Control-Allow-Headers: x-requested-with
|
68
|
+
Access-Control-Max-Age: 3628800
|
69
|
+
X-Content-Digest: 66049433125f563329c4178848643536f76459e5
|
70
|
+
X-Rack-Cache: fresh
|
71
|
+
Content-Length: 17440
|
72
|
+
X-Varnish: 311344447
|
73
|
+
Age: 289983
|
74
|
+
X-Cache: Hit from cloudfront
|
75
|
+
X-Amz-Cf-Id: 9yzifs_hIQF_MxPLwSR8zck3eZVXJ8LFKpMUpXnu2SmMuEmyrUbHdQ==,Lbh9kfjr0YRm77seSmOSQ6oFkUEMabvtFStJLhTOy9BfGrIXVneoKQ==
|
76
|
+
Via: 1.1 varnish, 1.0 2815dd16e8c2a0074b81a6148bd8aa3a.cloudfront.net:11180 (CloudFront), 1.0 f9e7403ca14431787835521769ace98a.cloudfront.net:11180 (CloudFront)
|
77
|
+
Connection: close
|
78
|
+
```
|
25
79
|
|
26
|
-
|
80
|
+
In it, you can see where this middleware has injected the `Content-Type` and
|
81
|
+
`Access-Control-*` headers into the response.
|
27
82
|
|
28
|
-
|
83
|
+
And below is an example OPTIONS request response:
|
29
84
|
|
85
|
+
```
|
86
|
+
$ curl -i -X OPTIONS http://www.codeschool.com/
|
87
|
+
HTTP/1.1 200 OK
|
88
|
+
Server: nginx
|
89
|
+
Date: Wed, 18 Jan 2012 04:13:25 GMT
|
90
|
+
Connection: keep-alive
|
91
|
+
Access-Control-Allow-Origin: http://www.codeschool.com
|
92
|
+
Access-Control-Allow-Methods: GET
|
93
|
+
Access-Control-Allow-Headers: x-requested-with
|
94
|
+
Access-Control-Max-Age: 3628800
|
95
|
+
Vary: Accept-Encoding
|
96
|
+
X-Rack-Cache: invalidate, pass
|
97
|
+
Content-Length: 0
|
98
|
+
```
|
30
99
|
|
31
100
|
License
|
32
101
|
-------
|
data/font_assets.gemspec
CHANGED
@@ -18,7 +18,6 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
# s.add_runtime_dependency "rest-client"
|
21
|
+
s.add_dependency "rack"
|
22
|
+
s.add_development_dependency "rspec"
|
24
23
|
end
|
data/lib/font_assets.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
+
require 'rack'
|
2
|
+
require 'font_assets/mime_types'
|
3
|
+
|
1
4
|
module FontAssets
|
2
5
|
class Middleware
|
3
6
|
|
4
7
|
def initialize(app, origin)
|
5
8
|
@app = app
|
6
9
|
@origin = origin
|
10
|
+
@mime_types = FontAssets::MimeTypes.new(Rack::Mime::MIME_TYPES)
|
7
11
|
end
|
8
12
|
|
9
13
|
def access_control_headers
|
@@ -21,21 +25,32 @@ module FontAssets
|
|
21
25
|
return [200, access_control_headers, []]
|
22
26
|
else
|
23
27
|
code, headers, body = @app.call(env)
|
24
|
-
|
28
|
+
set_headers! headers, body, env["PATH_INFO"]
|
25
29
|
[code, headers, body]
|
26
30
|
end
|
27
31
|
end
|
28
32
|
|
33
|
+
|
29
34
|
private
|
30
35
|
|
36
|
+
|
31
37
|
def extension(path)
|
32
|
-
path.split("?").first.split(".").last
|
38
|
+
"." + path.split("?").first.split(".").last
|
33
39
|
end
|
34
40
|
|
35
41
|
def font_asset?(path)
|
36
|
-
|
42
|
+
@mime_types.font? extension(path)
|
37
43
|
end
|
38
44
|
|
45
|
+
def set_headers!(headers, body, path)
|
46
|
+
if ext = extension(path) and font_asset?(ext)
|
47
|
+
headers.merge!(access_control_headers)
|
48
|
+
headers.merge!('Content-Type' => mime_type(ext)) unless body.empty?
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def mime_type(extension)
|
53
|
+
@mime_types[extension]
|
54
|
+
end
|
39
55
|
end
|
40
|
-
|
41
56
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module FontAssets
|
2
|
+
class MimeTypes
|
3
|
+
DEFAULT_TYPE = 'application/octet-stream'
|
4
|
+
MIME_TYPES = {
|
5
|
+
'.eot' => 'application/vnd.ms-fontobject',
|
6
|
+
'.svg' => 'image/svg+xml',
|
7
|
+
'.ttf' => 'application/x-font-ttf',
|
8
|
+
'.woff' => 'application/x-font-woff'
|
9
|
+
}
|
10
|
+
|
11
|
+
def initialize(types, default = DEFAULT_TYPE.dup)
|
12
|
+
@types = types.dup
|
13
|
+
@default = default
|
14
|
+
|
15
|
+
MIME_TYPES.each_pair do |extension, type|
|
16
|
+
set extension, type
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def [](extension)
|
21
|
+
@types.fetch(extension, DEFAULT_TYPE.dup).dup
|
22
|
+
end
|
23
|
+
|
24
|
+
def font?(extension)
|
25
|
+
MIME_TYPES.keys.include? extension
|
26
|
+
end
|
27
|
+
|
28
|
+
def set(extension, mime_type)
|
29
|
+
if @types[extension].nil? || @types[extension] == @default
|
30
|
+
set!(extension, mime_type)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def set!(extension, mime_type)
|
35
|
+
@types[extension] = mime_type
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/font_assets/railtie.rb
CHANGED
@@ -9,12 +9,5 @@ module FontAssets
|
|
9
9
|
|
10
10
|
app.middleware.insert_before 'ActionDispatch::Static', FontAssets::Middleware, config.font_assets.origin
|
11
11
|
end
|
12
|
-
|
13
|
-
config.after_initialize do
|
14
|
-
Rack::Mime::MIME_TYPES['.woff'] ||= 'application/x-font-woff'
|
15
|
-
Rack::Mime::MIME_TYPES['.ttf'] ||= 'application/x-font-ttf'
|
16
|
-
Rack::Mime::MIME_TYPES['.eot'] ||= 'application/vnd.ms-fontobject'
|
17
|
-
Rack::Mime::MIME_TYPES['.svg'] ||= 'image/svg+xml'
|
18
|
-
end
|
19
12
|
end
|
20
13
|
end
|
data/lib/font_assets/version.rb
CHANGED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'font_assets/middleware'
|
3
|
+
|
4
|
+
describe FontAssets::Middleware do
|
5
|
+
it 'passes all Rack::Lint checks' do
|
6
|
+
app = Rack::Lint.new(FontAssets::Middleware.new(inner_app, 'http://test.local'))
|
7
|
+
request app, '/'
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'for GET requests' do
|
11
|
+
context 'to font assets' do
|
12
|
+
let(:app) { load_app 'http://test.origin' }
|
13
|
+
let(:call) { request app, '/test.ttf' }
|
14
|
+
|
15
|
+
context 'the response headers' do
|
16
|
+
subject { call[1] }
|
17
|
+
|
18
|
+
its(["Access-Control-Allow-Headers"]) { should == "x-requested-with" }
|
19
|
+
its(["Access-Control-Max-Age"]) { should == "3628800" }
|
20
|
+
its(['Access-Control-Allow-Methods']) { should == 'GET' }
|
21
|
+
its(['Access-Control-Allow-Origin']) { should == 'http://test.origin' }
|
22
|
+
its(['Content-Type']) { should == 'application/x-font-ttf' }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'to non-font assets' do
|
27
|
+
let(:app) { load_app }
|
28
|
+
let(:call) { request app, '/' }
|
29
|
+
|
30
|
+
context 'the response headers' do
|
31
|
+
subject { call[1] }
|
32
|
+
|
33
|
+
its(["Access-Control-Allow-Headers"]) { should be_nil }
|
34
|
+
its(["Access-Control-Max-Age"]) { should be_nil }
|
35
|
+
its(['Access-Control-Allow-Methods']) { should be_nil }
|
36
|
+
its(['Access-Control-Allow-Origin']) { should be_nil }
|
37
|
+
its(['Content-Type']) { should == 'text/plain' }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'for OPTIONS requests' do
|
43
|
+
let(:app) { load_app 'http://test.options' }
|
44
|
+
let(:call) { request app, '/test.ttf', :method => 'OPTIONS' }
|
45
|
+
|
46
|
+
context 'the response headers' do
|
47
|
+
subject { call[1] }
|
48
|
+
|
49
|
+
its(["Access-Control-Allow-Headers"]) { should == "x-requested-with" }
|
50
|
+
its(["Access-Control-Max-Age"]) { should == "3628800" }
|
51
|
+
its(['Access-Control-Allow-Methods']) { should == 'GET' }
|
52
|
+
its(['Access-Control-Allow-Origin']) { should == 'http://test.options' }
|
53
|
+
|
54
|
+
it 'should not contain a Content-Type' do
|
55
|
+
subject['Content-Type'].should be_nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'the response body' do
|
60
|
+
subject { call[2] }
|
61
|
+
it { should be_empty }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
|
69
|
+
def load_app(origin = 'http://test.local')
|
70
|
+
FontAssets::Middleware.new(inner_app, origin)
|
71
|
+
end
|
72
|
+
|
73
|
+
def inner_app
|
74
|
+
lambda { |env| [200, {'Content-Type' => 'text/plain'}, 'Success'] }
|
75
|
+
end
|
76
|
+
|
77
|
+
def request(app, path, options = {})
|
78
|
+
app.call Rack::MockRequest.env_for(path, options)
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'font_assets/mime_types'
|
3
|
+
|
4
|
+
describe FontAssets::MimeTypes do
|
5
|
+
context 'given an empty hash' do
|
6
|
+
let(:hash) { Hash.new }
|
7
|
+
subject { described_class.new(hash) }
|
8
|
+
|
9
|
+
it 'adds the known mime types' do
|
10
|
+
FontAssets::MimeTypes::MIME_TYPES.each_pair do |ext, type|
|
11
|
+
subject[ext].should == type
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'given a populated hash' do
|
17
|
+
let(:default_type) { 'default/type' }
|
18
|
+
let(:hash) { { '.ttf' => default_type, '.svg' => 'test/type' } }
|
19
|
+
subject { described_class.new(hash, default_type) }
|
20
|
+
|
21
|
+
it 'retains the non-default-matching mime types' do
|
22
|
+
subject['.svg'].should == hash['.svg']
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'overrides the default-matching mime types' do
|
26
|
+
subject['.ttf'].should_not == hash['.ttf']
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context '#[]' do
|
31
|
+
let(:types) { described_class.new({}) }
|
32
|
+
|
33
|
+
it 'returns the mime type of the passed extension' do
|
34
|
+
types['.woff'].should == 'application/x-font-woff'
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'returns the default mime type for unknown extensions' do
|
38
|
+
types['.bad'].should == 'application/octet-stream'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context '#font?' do
|
43
|
+
let(:types) { described_class.new({}) }
|
44
|
+
|
45
|
+
it 'is true for known font extensions' do
|
46
|
+
FontAssets::MimeTypes::MIME_TYPES.keys.each do |key|
|
47
|
+
types.font?(key).should be_true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'is false for unrecognized font extensions' do
|
52
|
+
types.font?('.bad').should be_false
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: font_assets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,30 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
13
|
-
dependencies:
|
12
|
+
date: 2012-01-18 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rack
|
16
|
+
requirement: &70274473944840 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70274473944840
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
requirement: &70274473944080 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70274473944080
|
14
36
|
description: Improve font serving in Rails 3.1
|
15
37
|
email:
|
16
38
|
- rubymaverick@gmail.com
|
@@ -19,14 +41,20 @@ extensions: []
|
|
19
41
|
extra_rdoc_files: []
|
20
42
|
files:
|
21
43
|
- .gitignore
|
44
|
+
- .rspec
|
45
|
+
- CHANGELOG.md
|
22
46
|
- Gemfile
|
23
47
|
- README.md
|
24
48
|
- Rakefile
|
25
49
|
- font_assets.gemspec
|
26
50
|
- lib/font_assets.rb
|
27
51
|
- lib/font_assets/middleware.rb
|
52
|
+
- lib/font_assets/mime_types.rb
|
28
53
|
- lib/font_assets/railtie.rb
|
29
54
|
- lib/font_assets/version.rb
|
55
|
+
- spec/middleware_spec.rb
|
56
|
+
- spec/mime_types_spec.rb
|
57
|
+
- spec/spec_helper.rb
|
30
58
|
homepage: https://github.com/rubymaverick/font_assets
|
31
59
|
licenses: []
|
32
60
|
post_install_message:
|
@@ -51,4 +79,7 @@ rubygems_version: 1.8.10
|
|
51
79
|
signing_key:
|
52
80
|
specification_version: 3
|
53
81
|
summary: Improve font serving in Rails 3.1
|
54
|
-
test_files:
|
82
|
+
test_files:
|
83
|
+
- spec/middleware_spec.rb
|
84
|
+
- spec/mime_types_spec.rb
|
85
|
+
- spec/spec_helper.rb
|