server: add gzip support
This commit is contained in:
parent
786700e6ea
commit
d89f3fd8b9
6 changed files with 103 additions and 14 deletions
40
packages/ruby/server/.rubocop.yml
Normal file
40
packages/ruby/server/.rubocop.yml
Normal file
|
@ -0,0 +1,40 @@
|
|||
##
|
||||
# Plugins
|
||||
require:
|
||||
- standard
|
||||
|
||||
##
|
||||
# Defaults: standard-rb
|
||||
inherit_gem:
|
||||
standard: config/base.yml
|
||||
|
||||
##
|
||||
# All cops
|
||||
AllCops:
|
||||
TargetRubyVersion: 3.2
|
||||
Include:
|
||||
- lib/*.rb
|
||||
- lib/**/*.rb
|
||||
- test/*_test.rb
|
||||
|
||||
##
|
||||
# Enabled
|
||||
Style/FrozenStringLiteralComment:
|
||||
Enabled: true
|
||||
|
||||
##
|
||||
# Disabled
|
||||
Layout/ArgumentAlignment:
|
||||
Enabled: false
|
||||
Layout/MultilineMethodCallIndentation:
|
||||
Enabled: false
|
||||
Layout/EmptyLineBetweenDefs:
|
||||
Enabled: false
|
||||
Style/TrivialAccessors:
|
||||
Enabled: false
|
||||
Lint/NestedMethodDefinition:
|
||||
Exclude:
|
||||
- test/server_dir_test.rb
|
||||
Style/SingleLineMethods:
|
||||
Exclude:
|
||||
- test/server_dir_test.rb
|
|
@ -3,6 +3,7 @@
|
|||
class Server
|
||||
require "rack"
|
||||
require_relative "server/puma"
|
||||
require_relative "server/gzip"
|
||||
require_relative "server/dir"
|
||||
|
||||
def self.app(path)
|
||||
|
|
|
@ -1,19 +1,17 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
##
|
||||
# A rack application that serves the contents
|
||||
# of a directory over HTTP.
|
||||
class Server::Dir
|
||||
MIME_TYPES = {
|
||||
".ttf" => "font/ttf"
|
||||
}.freeze
|
||||
prepend Server::Gzip
|
||||
|
||||
def initialize(root)
|
||||
@root = File.realpath(root)
|
||||
end
|
||||
|
||||
def call(env)
|
||||
req = Rack::Request.new(env)
|
||||
headers = Rack::Headers.new(env)
|
||||
h, body = read(local_path(req.path))
|
||||
[200, headers.merge!(h), body]
|
||||
finish Rack::Request.new(env)
|
||||
rescue Errno::EPERM, Errno::EACCES
|
||||
body = "Permission denied"
|
||||
[403, {"content-length" => body.bytesize, "content-type" => "text/plain"}, [body]]
|
||||
|
@ -29,18 +27,24 @@ class Server::Dir
|
|||
|
||||
attr_reader :root
|
||||
|
||||
def read(path)
|
||||
def finish(request)
|
||||
path = find_path(request)
|
||||
body = File.binread(path)
|
||||
extn = File.extname(path)
|
||||
[
|
||||
{"content-type" => MIME_TYPES[extn] || Rack::Mime.mime_type(extn),
|
||||
200,
|
||||
{"content-type" => mime_types[extn] || Rack::Mime.mime_type(extn),
|
||||
"content-length" => body.bytesize},
|
||||
body.each_line
|
||||
]
|
||||
end
|
||||
|
||||
def local_path(req_path)
|
||||
lpath = File.join root, File.expand_path(req_path)
|
||||
File.directory?(lpath) ? File.join(lpath, "index.html") : lpath
|
||||
def find_path(request)
|
||||
path = File.join root, File.expand_path(request.path)
|
||||
File.directory?(path) ? File.join(path, "index.html") : path
|
||||
end
|
||||
|
||||
def mime_types
|
||||
{".ttf" => "font/ttf"}.freeze
|
||||
end
|
||||
end
|
||||
|
|
33
packages/ruby/server/lib/server/gzip.rb
Normal file
33
packages/ruby/server/lib/server/gzip.rb
Normal file
|
@ -0,0 +1,33 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
##
|
||||
# A mixin module that serves a compressed version of
|
||||
# a file when the file is found to exist on disk,
|
||||
# and has a ".gz" file extension.
|
||||
module Server::Gzip
|
||||
def finish(request)
|
||||
path = gzip_path(request)
|
||||
if path
|
||||
body = File.binread(path)
|
||||
extn = File.extname(path[0..-4])
|
||||
[
|
||||
200,
|
||||
{"content-type" => mime_types[extn] || Rack::Mime.mime_type(extn),
|
||||
"content-encoding" => "gzip",
|
||||
"content-length" => body.bytesize},
|
||||
body.each_line
|
||||
]
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def gzip_path(request)
|
||||
return unless request.get_header("accept-encoding")
|
||||
&.include?("gzip")
|
||||
path = "#{find_path(request)}.gz"
|
||||
File.exist?(path) ? path : nil
|
||||
end
|
||||
end
|
|
@ -10,6 +10,15 @@ Gem::Specification.new do |gem|
|
|||
gem.require_paths = ["lib"]
|
||||
gem.summary = "A static file web server"
|
||||
gem.description = gem.summary
|
||||
|
||||
##
|
||||
# Default gems
|
||||
# Pinned to specific versions for OpenBSD support
|
||||
gem.add_runtime_dependency "json", "= 2.6.1"
|
||||
gem.add_runtime_dependency "racc", "= 1.6.0"
|
||||
gem.add_runtime_dependency "stringio", "= 3.0.1"
|
||||
gem.add_runtime_dependency "set", "= 1.0.2"
|
||||
|
||||
gem.add_runtime_dependency "puma", "~> 6.3"
|
||||
gem.add_runtime_dependency "rack", "~> 3.0"
|
||||
gem.add_development_dependency "standard", "~> 1.24"
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative "setup"
|
||||
require "rack/test"
|
||||
|
||||
|
@ -44,7 +46,7 @@ class ServerDirTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_internal_server_error
|
||||
def app.read(path) raise RuntimeError, "test" end
|
||||
def app.finish(request) raise "test" end
|
||||
get "/"
|
||||
assert_equal 500, last_response.status
|
||||
assert_equal "text/plain", last_response.content_type
|
||||
|
@ -62,7 +64,7 @@ class ServerDirTest < Test::Unit::TestCase
|
|||
assert_equal "Permission denied".bytesize, last_response.content_length
|
||||
assert_equal "Permission denied", last_response.body
|
||||
ensure
|
||||
File.chmod 0440, "./test/webroot/permission_denied.html"
|
||||
File.chmod 0o440, "./test/webroot/permission_denied.html"
|
||||
end
|
||||
|
||||
def test_page_not_found
|
||||
|
|
Loading…
Reference in a new issue