# Copyright (C) 2013, Eric Wong and all contributors # License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt) require_relative 'server_helper' require 'zlib' require 'time' class TestExtrasTryGzipStatic < Testcase ENV["N"].to_i > 1 and parallelize_me! include ServerHelper GPL_TEXT = IO.binread("COPYING").freeze def setup @tmpdir = Dir.mktmpdir server_helper_setup end def teardown server_helper_teardown FileUtils.rm_rf @tmpdir end def test_gzip_static err, cfg, host, port = @err, Yahns::Config.new, @srv.addr[3], @srv.addr[1] tmpdir = @tmpdir pid = mkserver(cfg) do require './extras/try_gzip_static' cfg.instance_eval do app(:rack, TryGzipStatic.new(tmpdir)) do listen "#{host}:#{port}" end stderr_path err.path end end begin # setup gpl = "#{tmpdir}/COPYING" gplgz = "#{tmpdir}/COPYING.gz" FileUtils.cp("COPYING", gpl) _, status = Process.waitpid2(fork do File.open(gplgz, "w") do |fp| Zlib::GzipWriter.wrap(fp.dup) { |io| io.write(GPL_TEXT) } end exit!(0) end) assert status.success?, status.inspect st = File.stat(gpl) gz_st = File.stat(gplgz) assert_equal GPL_TEXT, `zcat #{gplgz}`, "Eric screwed up using zlib" File.utime(st.atime, st.mtime, gplgz) end check = lambda do |req, &blk| c = get_tcp_client(host, port) begin c.write "#{req}\r\n\r\n" buf = c.read(666000) head, body = buf.split(/\r\n\r\n/) blk.call(head) body ensure c.close end end Timeout.timeout(30) do # basic tests %w(GET HEAD).each do |m| body = check.call("#{m} /COPYING HTTP/1.0") do |head| refute_match %r{^Content-Encoding: gzip\b}, head assert_match %r{^Content-Type: text/plain\b}, head assert_match %r{^Content-Length: #{st.size}\b}, head end case m when "GET" then assert_equal GPL_TEXT, body when "HEAD" then assert_nil body end req = "#{m} /COPYING HTTP/1.0\r\nAccept-Encoding: gzip" body = check.call(req) do |head| assert_match %r{^Content-Encoding: gzip\b}, head assert_match %r{^Content-Type: text/plain\b}, head assert_match %r{^Content-Length: #{gz_st.size}\b}, head end case m when "GET" assert_equal GPL_TEXT, Zlib::GzipReader.new(StringIO.new(body)).read when "HEAD" then assert_nil body end end end Timeout.timeout(30) do # range tests %w(HEAD GET).each do |m| req = "#{m} /COPYING HTTP/1.0\r\n" \ "Range: bytes=5-46\r\nAccept-Encoding: gzip" body = check.call(req) do |head| assert_match %r{\AHTTP/1\.1 206 Partial Content\r\n}, head refute_match %r{^Content-Encoding: gzip\b}, head assert_match %r{^Content-Type: text/plain\b}, head assert_match %r{^Content-Length: 42\b}, head assert_match %r{^Content-Range: bytes 5-46/#{st.size}\r\n}, head end case m when "GET" then assert_equal GPL_TEXT[5..46], body when "HEAD" then assert_nil body end req = "#{m} /COPYING HTTP/1.0\r\n" \ "Range: bytes=66666666-\r\nAccept-Encoding: gzip" body = check.call(req) do |head| assert_match %r{^Content-Range: bytes \*/#{st.size}\r\n}, head assert_match %r{\AHTTP/1\.1 416 }, head end assert_nil body end end Timeout.timeout(30) do # gzip counterpart is nonexistent File.link(gpl, "#{gpl}.hardlink") %w(GET HEAD).each do |m| req = "#{m} /COPYING.hardlink HTTP/1.0\r\nAccept-Encoding: gzip" body = check.call(req) do |head| refute_match %r{^Content-Encoding: gzip\b}, head assert_match %r{^Content-Type: text/plain\b}, head assert_match %r{^Content-Length: #{st.size}\b}, head end case m when "GET" then assert_equal GPL_TEXT, body when "HEAD" then assert_nil body end end end Timeout.timeout(30) do # If-Modified-Since %w(GET HEAD).each do |m| req = "#{m} /COPYING HTTP/1.0\r\n" \ "If-Modified-Since: #{st.mtime.httpdate}" body = check.call(req) do |head| assert_match %r{\AHTTP/1\.1 304 Not Modified}, head end assert_nil body end end # skew the times of the gzip file, should now fail to use gzipped Timeout.timeout(30) do File.utime(Time.at(0), Time.at(0), gplgz) %w(GET HEAD).each do |m| req = "#{m} /COPYING HTTP/1.0\r\nAccept-Encoding: gzip" body = check.call(req) do |head| refute_match %r{^Content-Encoding: gzip\b}, head assert_match %r{^Content-Type: text/plain\b}, head assert_match %r{^Content-Length: #{st.size}\b}, head end case m when "GET" then assert_equal GPL_TEXT, body when "HEAD" then assert_nil body end end end Timeout.timeout(30) do # 404 %w(GET HEAD).each do |m| req = "#{m} /cp-ing HTTP/1.0\r\nAccept-Encoding: gzip" body = check.call(req) do |head| assert_match %r{HTTP/1\.1 404 }, head end assert_nil body end body = check.call("FOO /COPYING HTTP/1.0") do |head| assert_match %r{HTTP/1\.1 405 }, head end assert_nil body end ensure quit_wait(pid) end end