rack_gzfile 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d17f0629b61d4802b40da6dd088ab82277c09412
4
+ data.tar.gz: 3f0fb225709a01983227b70f014985505e324a13
5
+ SHA512:
6
+ metadata.gz: 1c2af2da13f9473883c6868aeac25763229da118e9f7d0eac8c7284cf6396a6a9d6512e8fb6261d8dd02a00f5a72ae60b6e585baf911edb8a37b50ea4d53daf5
7
+ data.tar.gz: 7c7bf53188977357a6a3bd7daaaf123886328d0653b2d3555a8072ec54dcdcf286484ed0200945d9b9ec6ecab93d7540f816c2fb516d515a1b66e0f6563b57a0
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rack_gzfile.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Brian Alexander
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # RackGzfile
2
+
3
+ By default, `rake assets:precompile` generates gzipped versions of certain types of files. Servers (like Nginx with the GzipStatic module) can then serve these gzipped assets so they can get the reduced bandwidth of gzip without needing to compress the file on every request. [This pull request](https://github.com/rack/rack/pull/479) will hopefully bring this functionality to Rack. In the meantime, this gem can be used.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'rack_gzfile'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ ## Usage
16
+
17
+ `Rack::GzFile` can be used as a drop-in replacement for [`Rack::File`](https://github.com/rack/rack/blob/master/lib/rack/file.rb).
18
+
19
+ ### Usage with `Rack::Static`
20
+
21
+ Unfortunately, `Rack::Static` is hardcoded to use `Rack::File`. [Hopefully this will be changed](https://github.com/rack/rack/pull/479#issuecomment-21907789), but in the meantime you can do an ugly monkey patch like this:
22
+
23
+ ```ruby
24
+ Rack::Static.class_eval do
25
+ def initialize_with_gzip_file_server(app, options={})
26
+ initialize_without_gzip_file_server(app, options)
27
+
28
+ root = options[:root] || Dir.pwd
29
+ @file_server = Rack::GzFile.new(root, @headers)
30
+ end
31
+ alias_method_chain :initialize, :gzip_file_server
32
+ end
33
+ ```
34
+
35
+ ## Contributing
36
+
37
+ 1. Fork it
38
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
39
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
40
+ 4. Push to the branch (`git push origin my-new-feature`)
41
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,5 @@
1
+ module Rack
2
+ class GzFile
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,45 @@
1
+ module Rack
2
+ # Rack::GzFile behaves exactly the same as Rack::File, except that it will
3
+ # also serve up a gzip encoding of a file, if one is available on the
4
+ # filesystem.
5
+ #
6
+ # For each request, Rack::GzFile first checks the filesystem for a file with a
7
+ # .gz extension. If one is found, the appropriate encoding headers are added
8
+ # to the response and the gzip file is served.
9
+ #
10
+ # If no .gz file is found, Rack::GzFile will behave exactly like Rack::File.
11
+ class GzFile
12
+ def initialize(root, headers={}, default_mime = 'text/plain')
13
+ @file_server = if Rack::File.instance_method(:initialize).arity.abs == 2
14
+ Rack::File.new(root, headers) # for Rack < 1.5.0
15
+ else
16
+ Rack::File.new(root, headers, default_mime)
17
+ end
18
+ @default_mime = default_mime
19
+ end
20
+
21
+ def call(env)
22
+ path_info = env['PATH_INFO']
23
+ status = nil
24
+
25
+ if env['HTTP_ACCEPT_ENCODING'] =~ /\bgzip\b/
26
+ status, headers, body = @file_server.call(
27
+ env.merge('PATH_INFO' => path_info + '.gz')
28
+ )
29
+ end
30
+
31
+ case status
32
+ when 200
33
+ headers['Content-Type'] = Mime.mime_type(::File.extname(path_info), @default_mime)
34
+ headers['Content-Encoding'] = 'gzip'
35
+ when 304
36
+ else
37
+ status, headers, body = @file_server.call(env)
38
+ end
39
+
40
+ headers['Vary'] = 'Accept-Encoding'
41
+
42
+ [status, headers, body]
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,2 @@
1
+ require "rack/gz_file"
2
+ require "rack/gz_file/version"
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rack/gz_file/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rack_gzfile"
8
+ spec.version = Rack::GzFile::VERSION
9
+ spec.authors = ["Brian Alexander"]
10
+ spec.email = ["balexand@gmail.com"]
11
+ spec.description = %q{Rack::File meets gzip_static}
12
+ spec.summary = %q{Rack::File meets gzip_static}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rack"
23
+ spec.add_development_dependency "rake"
24
+ spec.add_development_dependency "rspec"
25
+ end
@@ -0,0 +1 @@
1
+ I can't has gzip!
@@ -0,0 +1 @@
1
+ I can has gzip!
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+
3
+ describe Rack::GzFile do
4
+
5
+ let(:root) { File.expand_path("../../../fixtures", __FILE__) }
6
+ let(:request) { Rack::MockRequest.new(Rack::Lint.new(Rack::GzFile.new(root))) }
7
+
8
+ describe "#call" do
9
+
10
+ context "non-gzipped file requested" do
11
+
12
+ it "renders non-gzipped file" do
13
+ res = request.get('/i_can_has_gzip.html')
14
+ expect(res.status).to eq 200
15
+ expect(res.body).to eq "I can has gzip!\n"
16
+ expect(res.headers.key?('Content-Encoding')).to eq false
17
+ expect(res.headers['Vary']).to eq 'Accept-Encoding'
18
+ expect(res.headers['Content-Length']).to eq "I can has gzip!\n".size.to_s
19
+ end
20
+
21
+ end
22
+
23
+ context "gzipped file requested" do
24
+
25
+ it "renders gzipped file if it exists" do
26
+ res = request.get('/i_can_has_gzip.html', 'HTTP_ACCEPT_ENCODING' => 'gzip')
27
+ expect(res.status).to eq 200
28
+ expect(Zlib::GzipReader.new(StringIO.new(res.body)).read).to eq "I can has gzip!\n"
29
+ expect(res.headers['Content-Encoding']).to eq 'gzip'
30
+ expect(res.headers['Vary']).to eq 'Accept-Encoding'
31
+ expect(res.headers['Content-Length']).to eq File.size(File.join(root, "i_can_has_gzip.html.gz")).to_s
32
+ end
33
+
34
+ it "renders non-gzipped file if gzipped file not present" do
35
+ res = request.get('/foo.html', 'HTTP_ACCEPT_ENCODING' => 'gzip')
36
+ expect(res.status).to eq 200
37
+ expect(res.body).to eq "I can't has gzip!\n"
38
+ expect(res.headers.key?('Content-Encoding')).to eq false
39
+ expect(res.headers['Vary']).to eq 'Accept-Encoding'
40
+ expect(res.headers['Content-Length']).to eq "I can't has gzip!\n".size.to_s
41
+ end
42
+
43
+ it "renders passes 304 response for gzipped file without updating headers" do
44
+ date = Time.new(2012,12,25)
45
+ File.utime date, date, File.join(root, "i_can_has_gzip.html.gz")
46
+ res = request.get('/i_can_has_gzip.html', 'HTTP_ACCEPT_ENCODING' => 'gzip', 'HTTP_IF_MODIFIED_SINCE' => date.httpdate)
47
+
48
+ expect(res.status).to eq 304
49
+ expect(res.body).to eq ""
50
+ expect(res.headers.key?('Content-Encoding')).to eq false
51
+ expect(res.headers['Vary']).to eq 'Accept-Encoding'
52
+ expect(res.headers.key?('Content-Length')).to eq false
53
+ end
54
+
55
+ it "renders normal file if arbitrary status is returned for gzipped file" do
56
+ Rack::File.any_instance.stub(:call) do |env|
57
+ case env['PATH_INFO']
58
+ when "/i_can_has_gzip.html.gz"
59
+ [500, {}, ["Something went wrong"]]
60
+ else
61
+ [200, {"Content-Type" => "text/plain"}, ["Got the non-gzipped version"]]
62
+ end
63
+ end
64
+
65
+ res = request.get('/i_can_has_gzip.html', 'HTTP_ACCEPT_ENCODING' => 'gzip')
66
+ expect(res.status).to eq 200
67
+ expect(res.body).to eq "Got the non-gzipped version"
68
+ expect(res.headers.key?('Content-Encoding')).to eq false
69
+ expect(res.headers['Vary']).to eq 'Accept-Encoding'
70
+ expect(res.headers['Content-Length']).to eq "Got the non-gzipped version".size.to_s
71
+ end
72
+
73
+ end
74
+
75
+ end
76
+
77
+ end
@@ -0,0 +1,4 @@
1
+ require 'rack_gzfile'
2
+ require 'rack/lint'
3
+ require 'rack/mock'
4
+ require 'zlib'
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack_gzfile
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Brian Alexander
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-08-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rack
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Rack::File meets gzip_static
70
+ email:
71
+ - balexand@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - Gemfile
78
+ - LICENSE.txt
79
+ - README.md
80
+ - Rakefile
81
+ - lib/rack/gz_file.rb
82
+ - lib/rack/gz_file/version.rb
83
+ - lib/rack_gzfile.rb
84
+ - rack_gzfile.gemspec
85
+ - spec/fixtures/foo.html
86
+ - spec/fixtures/i_can_has_gzip.html
87
+ - spec/fixtures/i_can_has_gzip.html.gz
88
+ - spec/lib/rack/gz_file_spec.rb
89
+ - spec/spec_helper.rb
90
+ homepage: ''
91
+ licenses:
92
+ - MIT
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - '>='
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 2.0.2
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: Rack::File meets gzip_static
114
+ test_files:
115
+ - spec/fixtures/foo.html
116
+ - spec/fixtures/i_can_has_gzip.html
117
+ - spec/fixtures/i_can_has_gzip.html.gz
118
+ - spec/lib/rack/gz_file_spec.rb
119
+ - spec/spec_helper.rb