diff options
author | Aaron Patterson <aaron.patterson@gmail.com> | 2015-05-26 14:35:11 -0700 |
---|---|---|
committer | Aaron Patterson <aaron.patterson@gmail.com> | 2015-05-26 14:35:11 -0700 |
commit | e73ca98cf8684d5f8313eb8d48f2c7f57588bb68 (patch) | |
tree | af6eb59c3389e150f0d0f6bcfa3242bba119a8b6 | |
parent | d7c6b75a66f793f27398abb6932b4a540bf996ec (diff) | |
parent | 421932740bb8395f908759124c2727eab9cd6b54 (diff) | |
download | rack-e73ca98cf8684d5f8313eb8d48f2c7f57588bb68.tar.gz |
Merge pull request #863 from jeremyevans/static_gzip
Add support for serving gzipped static files
-rw-r--r-- | lib/rack/static.rb | 22 | ||||
-rw-r--r-- | test/cgi/test.gz | bin | 0 -> 165 bytes | |||
-rw-r--r-- | test/spec_static.rb | 28 |
3 files changed, 48 insertions, 2 deletions
diff --git a/lib/rack/static.rb b/lib/rack/static.rb index ec9ec91f..f401abeb 100644 --- a/lib/rack/static.rb +++ b/lib/rack/static.rb @@ -84,6 +84,7 @@ module Rack @app = app @urls = options[:urls] || ["/favicon.ico"] @index = options[:index] + @gzip = options[:gzip] root = options[:root] || Dir.pwd # HTTP Headers @@ -110,9 +111,26 @@ module Rack path = env[PATH_INFO] if can_serve(path) - env[PATH_INFO] = (path =~ /\/$/ ? path + @index : @urls[path]) if overwrite_file_path(path) + if overwrite_file_path(path) + env[PATH_INFO] = (path =~ /\/$/ ? path + @index : @urls[path]) + elsif @gzip && env['HTTP_ACCEPT_ENCODING'] =~ /\bgzip\b/ + path = env[PATH_INFO] + env[PATH_INFO] += '.gz' + response = @file_server.call(env) + env[PATH_INFO] = path + + if response[0] == 404 + response = nil + else + if mime_type = Mime.mime_type(::File.extname(path), 'text/plain') + response[1][CONTENT_TYPE] = mime_type + end + response[1]['Content-Encoding'] = 'gzip' + end + end + path = env[PATH_INFO] - response = @file_server.call(env) + response ||= @file_server.call(env) headers = response[1] applicable_rules(path).each do |rule, new_headers| diff --git a/test/cgi/test.gz b/test/cgi/test.gz Binary files differnew file mode 100644 index 00000000..312c60e2 --- /dev/null +++ b/test/cgi/test.gz diff --git a/test/spec_static.rb b/test/spec_static.rb index fed1df25..2fac80b2 100644 --- a/test/spec_static.rb +++ b/test/spec_static.rb @@ -1,6 +1,8 @@ require 'rack/static' require 'rack/lint' require 'rack/mock' +require 'zlib' +require 'stringio' class DummyApp def call(env) @@ -18,10 +20,12 @@ describe Rack::Static do OPTIONS = {:urls => ["/cgi"], :root => root} STATIC_OPTIONS = {:urls => [""], :root => "#{root}/static", :index => 'index.html'} HASH_OPTIONS = {:urls => {"/cgi/sekret" => 'cgi/test'}, :root => root} + GZIP_OPTIONS = {:urls => ["/cgi"], :root => root, :gzip=>true} @request = Rack::MockRequest.new(static(DummyApp.new, OPTIONS)) @static_request = Rack::MockRequest.new(static(DummyApp.new, STATIC_OPTIONS)) @hash_request = Rack::MockRequest.new(static(DummyApp.new, HASH_OPTIONS)) + @gzip_request = Rack::MockRequest.new(static(DummyApp.new, GZIP_OPTIONS)) it "serves files" do res = @request.get("/cgi/test") @@ -70,6 +74,30 @@ describe Rack::Static do res.body.should == "Hello World" end + it "serves gzipped files if client accepts gzip encoding and gzip files are present" do + res = @gzip_request.get("/cgi/test", 'HTTP_ACCEPT_ENCODING'=>'deflate, gzip') + res.should.be.ok + res.headers['Content-Encoding'].should.equal 'gzip' + res.headers['Content-Type'].should.equal 'text/plain' + Zlib::GzipReader.wrap(StringIO.new(res.body), &:read).should =~ /ruby/ + end + + it "serves regular files if client accepts gzip encoding and gzip files are not present" do + res = @gzip_request.get("/cgi/rackup_stub.rb", 'HTTP_ACCEPT_ENCODING'=>'deflate, gzip') + res.should.be.ok + res.headers['Content-Encoding'].should.equal nil + res.headers['Content-Type'].should.equal 'text/x-script.ruby' + res.body.should =~ /ruby/ + end + + it "serves regular files if client does not accept gzip encoding" do + res = @gzip_request.get("/cgi/test") + res.should.be.ok + res.headers['Content-Encoding'].should.equal nil + res.headers['Content-Type'].should.equal 'text/plain' + res.body.should =~ /ruby/ + end + it "supports serving fixed cache-control (legacy option)" do opts = OPTIONS.merge(:cache_control => 'public') request = Rack::MockRequest.new(static(DummyApp.new, opts)) |