server.rb 0.2.2 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d86d66d6dd85fd989a0c7cea5e0a89003da4f93c5bbb90e8e59cb24aa92a4273
4
- data.tar.gz: 22d12221ead684c5897cd9138502370852d4869f47a965d0b4678648924baa64
3
+ metadata.gz: d6f5a23f88fe1b283e2b5004394f493a588060e653a28f72840ff5a194108d41
4
+ data.tar.gz: 479b0da5bf427fd73ef5ade931b713f342dc5be8d0e5409d12041b323e3c3c43
5
5
  SHA512:
6
- metadata.gz: ba7756e35e925bb88b6dbd82d75ad098a349b0f27fb823a766650d5683df8bc4893cc6017da46458140d059ab6e0e683b34486ff4880da2546c9e41f4f77e8c6
7
- data.tar.gz: 5fee378893a5c0f1c8984f396e2cda243f4fa24d866f2a6b0fe58dfb1db34b160320140cdc08a73196e52b6319317fae0e201290940c1294e9913e1547b50fd9
6
+ metadata.gz: 213694f2d265096664eaee7e7eab3f75f95fa361155e7c2671118dd02768f41bd9d1dab1d77eb320deb9c584c904207ee57025b7446bf8657bbde68f596c1620
7
+ data.tar.gz: c2182a37c1af04a2cac3e9826e3d70a145810dd9f2fb8d76a6a52a5b1ecdfcae2c9f4d87ee72bf39aa3284a3fb9c9d09ed47cf9f8b60b377b2daf7fa39b426de
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # {Server::IndexResolver Server::IndexResolver} is a
5
+ # middleware that serves the contents of index.html
6
+ # from a given directory
7
+ class Server::IndexResolver
8
+ def initialize(app, options = {})
9
+ @app = app
10
+ @root = options.fetch(:root)
11
+ end
12
+
13
+ def call(env)
14
+ index = File.join(root, File.expand_path(env["PATH_INFO"]), "index.html")
15
+ if File.exist?(index)
16
+ Rack::Response[
17
+ 200,
18
+ {"content-type" => "text/html"},
19
+ File.read(index).each_line
20
+ ].finish
21
+ else
22
+ @app.call(env)
23
+ end
24
+ end
25
+
26
+ private
27
+ attr_reader :root
28
+ end
@@ -1,3 +1,3 @@
1
1
  class Server
2
- VERSION = "0.2.2"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/server.rb CHANGED
@@ -3,34 +3,39 @@
3
3
  class Server
4
4
  require "rack"
5
5
  require_relative "server/puma"
6
- require_relative "server/gzip"
7
- require_relative "server/etag"
8
- require_relative "server/dir"
6
+ require_relative "server/index_resolver"
9
7
 
10
8
  ##
11
- # @param [String] path
12
- # The path to a directory.
13
- #
9
+ # @param [String] root
10
+ # The path to a directory
14
11
  # @return [Rack::Builder]
15
- # Returns a Rack app.
16
- def self.app(path)
12
+ # Returns a Rack app
13
+ def self.app(root)
17
14
  Rack::Builder.app do
18
- use Server::ETag
19
- run Server::Dir.new(path)
15
+ use IndexResolver, {root:}
16
+ use Rack::Deflater
17
+ run Rack::Files.new(root)
20
18
  end
21
19
  end
22
- private_class_method :app
23
20
 
24
21
  ##
25
22
  # @param [String] path
26
23
  # The path to a directory
27
- #
28
24
  # @param [Hash] options
29
25
  # Hash of options
30
- #
31
26
  # @return [Server]
32
27
  # Returns an instance of {Server Server}
33
28
  def self.for(path, options = {})
29
+ new app(path), prepare(options)
30
+ end
31
+
32
+ ##
33
+ # Prepares options for {Server#initialize Server#initialize}
34
+ # @param [#to_h] options
35
+ # @return [Hash]
36
+ # Returns a Hash object
37
+ def self.prepare(options)
38
+ options = options.to_h.dup
34
39
  host = options.delete(:host) ||
35
40
  options.delete("host") ||
36
41
  options.delete(:bind) ||
@@ -42,10 +47,12 @@ class Server
42
47
  unix = options.delete(:unix) ||
43
48
  options.delete("unix") ||
44
49
  nil
45
- new app(path), options.merge!(
50
+ options.merge!(
46
51
  binds: [unix ? "unix://#{unix}" : "tcp://#{host}:#{port}"]
47
52
  )
53
+ options
48
54
  end
55
+
49
56
  class << self
50
57
  alias_method :dir, :for
51
58
  end
@@ -53,10 +60,8 @@ class Server
53
60
  ##
54
61
  # @param [Rack::Builder] app
55
62
  # Rack application
56
- #
57
63
  # @param [Hash] options
58
64
  # Hash of options
59
- #
60
65
  # @return [Server]
61
66
  # Returns an instance of {Server Server}
62
67
  def initialize(app, options = {})
@@ -68,10 +73,8 @@ class Server
68
73
 
69
74
  ##
70
75
  # Starts the web server
71
- #
72
76
  # @param [Boolean] block
73
77
  # When given as true, this method will block
74
- #
75
78
  # @return [Thread]
76
79
  # Returns a thread
77
80
  def start(block: false)
@@ -82,7 +85,6 @@ class Server
82
85
 
83
86
  ##
84
87
  # Stops the web server
85
- #
86
88
  # @return [void]
87
89
  def stop
88
90
  @server.stop
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: server.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - '0x1eef'
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-04 00:00:00.000000000 Z
11
+ date: 2024-08-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: puma
@@ -88,9 +88,7 @@ extensions: []
88
88
  extra_rdoc_files: []
89
89
  files:
90
90
  - lib/server.rb
91
- - lib/server/dir.rb
92
- - lib/server/etag.rb
93
- - lib/server/gzip.rb
91
+ - lib/server/index_resolver.rb
94
92
  - lib/server/puma.rb
95
93
  - lib/server/version.rb
96
94
  homepage: https://github.com/0x1eef/server.rb#readme
@@ -112,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
112
110
  - !ruby/object:Gem::Version
113
111
  version: '0'
114
112
  requirements: []
115
- rubygems_version: 3.5.9
113
+ rubygems_version: 3.5.13
116
114
  signing_key:
117
115
  specification_version: 4
118
116
  summary: A static file web server
data/lib/server/dir.rb DELETED
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- ##
4
- # A rack application that serves the contents
5
- # of a directory over HTTP.
6
- class Server::Dir
7
- prepend Server::Gzip
8
-
9
- def initialize(root)
10
- @root = File.realpath(root)
11
- @mime_types = {".ttf" => "font/ttf"}.freeze
12
- end
13
-
14
- def call(env)
15
- catch(:redirect) { finish Rack::Request.new(env) }
16
- rescue Errno::EPERM, Errno::EACCES
17
- body = "Permission denied"
18
- [403, {"content-length" => body.bytesize, "content-type" => "text/plain"}, [body]]
19
- rescue Errno::ENOENT
20
- body = "The requested URL was not found"
21
- [404, {"content-length" => body.bytesize, "content-type" => "text/plain"}, [body]]
22
- rescue => ex
23
- body = "Internal server error (#{ex.class})"
24
- [500, {"content-length" => body.bytesize, "content-type" => "text/plain"}, [body]]
25
- end
26
-
27
- def finish(req)
28
- path = resolve_path(req)
29
- body = File.binread(path)
30
- extn = File.extname(path)
31
- [
32
- 200,
33
- {"content-type" => mime_types[extn] || Rack::Mime.mime_type(extn),
34
- "content-length" => body.bytesize},
35
- body.each_line.to_a
36
- ]
37
- end
38
-
39
- private
40
-
41
- attr_reader :root, :mime_types
42
-
43
- def resolve_path(req)
44
- path = File.join root, File.expand_path(req.path)
45
- return path unless File.directory?(path)
46
- if req.path.end_with?("/")
47
- File.join(path, "index.html")
48
- else
49
- throw(:redirect, [301, {"Location" => "#{req.path}/"}, [""]])
50
- end
51
- end
52
- end
data/lib/server/etag.rb DELETED
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- ##
4
- # A middleware that adds ETag support.
5
- class Server::ETag < Rack::ETag
6
- ETAGS = {}
7
-
8
- ##
9
- # @param [#call] app
10
- # A rack app.
11
- #
12
- # @return [Server::ETag]
13
- # Reurns an instance of {Server::ETag Server::ETag}.
14
- def initialize(app)
15
- @app = app
16
- end
17
-
18
- ##
19
- # @param [Hash] env
20
- # An environment hash.
21
- #
22
- # @return [Array<Number, Hash, #each>]
23
- def call(env)
24
- status, headers, body = super(env)
25
- if headers["etag"] && headers["etag"] == env["HTTP_IF_NONE_MATCH"]
26
- [304, headers, [""]]
27
- else
28
- [status, headers, body]
29
- end
30
- end
31
- end
data/lib/server/gzip.rb DELETED
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- ##
4
- # A mixin that serves a compressed copy of a file.
5
- # Similar to the nginx module
6
- # [gzip_static](http://nginx.org/en/docs/http/ngx_http_gzip_static_module.html).
7
- module Server::Gzip
8
- def finish(request)
9
- path = gzip_path(request)
10
- if path
11
- body = File.binread(path)
12
- extn = File.extname(path[0..-4])
13
- [
14
- 200,
15
- {"content-type" => mime_types[extn] || Rack::Mime.mime_type(extn),
16
- "content-encoding" => "gzip",
17
- "content-length" => body.bytesize},
18
- body.each_line
19
- ]
20
- else
21
- super
22
- end
23
- end
24
-
25
- private
26
-
27
- def gzip_path(request)
28
- return unless request.get_header("accept-encoding")
29
- &.include?("gzip")
30
- path = "#{find_path(request)}.gz"
31
- File.exist?(path) ? path : nil
32
- end
33
- end