Add packages/ruby/server.rb as a git submodule

This commit is contained in:
0x1eef 2024-03-23 14:44:22 -03:00
parent d71267970f
commit 337a2460e3
22 changed files with 81 additions and 386 deletions

3
.gitmodules vendored
View file

@ -1,3 +1,6 @@
[submodule "submodules/surah-name-glyphs"] [submodule "submodules/surah-name-glyphs"]
path = submodules/surah-name-glyphs path = submodules/surah-name-glyphs
url = https://github.com/ReflectsLight/surah-name-glyphs url = https://github.com/ReflectsLight/surah-name-glyphs
[submodule "packages/ruby/server.rb"]
path = packages/ruby/server.rb
url = https://github.com/0x1eef/server.rb

@ -0,0 +1 @@
Subproject commit bf94e6f20c1f48ec002611912a53e0bf746f076f

View file

@ -1,8 +0,0 @@
build/
tmp/
node_modules/
.bundle/
*.log
*.sh
*.core
Gemfile.lock

View file

@ -1,40 +0,0 @@
##
# 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

View file

@ -1,4 +0,0 @@
# frozen_string_literal: true
source "https://rubygems.org"
gemspec

View file

@ -0,0 +1,77 @@
PATH
remote: .
specs:
server.rb (0.1.0)
json (= 2.6.1)
puma (~> 6.3)
racc (= 1.6.0)
rack (~> 3.0)
set (= 1.0.2)
stringio (= 3.0.1)
GEM
remote: https://rubygems.org/
specs:
ast (2.4.2)
json (2.6.1)
language_server-protocol (3.17.0.3)
lint_roller (1.0.0)
nio4r (2.5.9)
parallel (1.23.0)
parser (3.2.2.3)
ast (~> 2.4.1)
racc
power_assert (2.0.3)
puma (6.3.0)
nio4r (~> 2.0)
racc (1.6.0)
rack (3.0.8)
rack-test (2.1.0)
rack (>= 1.3)
rainbow (3.1.1)
regexp_parser (2.8.1)
rexml (3.2.5)
rubocop (1.52.1)
json (~> 2.3)
parallel (~> 1.10)
parser (>= 3.2.2.3)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.28.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.29.0)
parser (>= 3.2.1.0)
rubocop-performance (1.18.0)
rubocop (>= 1.7.0, < 2.0)
rubocop-ast (>= 0.4.0)
ruby-progressbar (1.13.0)
set (1.0.2)
standard (1.29.0)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.0)
rubocop (~> 1.52.0)
standard-custom (~> 1.0.0)
standard-performance (~> 1.1.0)
standard-custom (1.0.1)
lint_roller (~> 1.0)
standard-performance (1.1.0)
lint_roller (~> 1.0)
rubocop-performance (~> 1.18.0)
stringio (3.0.1)
test-unit (3.6.1)
power_assert
unicode-display_width (2.4.2)
PLATFORMS
x86_64-openbsd
DEPENDENCIES
rack-test (~> 2.1)
server.rb!
standard (~> 1.24)
test-unit (~> 3.5)
BUNDLED WITH
2.3.26

View file

@ -1,15 +0,0 @@
Copyright (C) 2023 by 0x1eef <0x1eef@protonmail.com>
Permission to use, copy, modify, and/or distribute this
software for any purpose with or without fee is hereby
granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS
ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
OF THIS SOFTWARE.

View file

@ -1,40 +0,0 @@
## About
server.rb implements a static file web server
by using the fast performing Ruby web server
[Puma](https://github.com/puma/puma)
and a small
[Rack](https://github.com/rack/rack)
application.
## Examples
### Server.for_dir
The `Server.for_dir` method returns a Server instance
that serves the contents of a directory. `Server#start` spawns
a new thread to listen for requests, and afterwards returns
the thread. `Thread#join` can block execution at that point,
or execution can continue as normal by not calling `Thread#join`:
```ruby
require "server"
##
# Create a Server instance for the contents of a directory
server = Server.for_dir("./build/website/")
##
# Start listening for connections
thr = server.start
##
# Prevent the main thread from exiting
thr.join
```
## License
[BSD Zero Clause](https://choosealicense.com/licenses/0bsd/).
<br>
See [LICENSE](./LICENSE).

View file

@ -1,52 +0,0 @@
# frozen_string_literal: true
class Server
require "rack"
require_relative "server/puma"
require_relative "server/gzip"
require_relative "server/etag"
require_relative "server/dir"
def self.app(path)
Rack::Builder.app do
use Server::ETag
run Server::Dir.new(path)
end
end
def self.for_dir(path, options = {})
host = options.delete(:host) || "127.0.0.1"
port = options.delete(:port) || 7777
unix = options.delete(:unix) || false
new app(path), options.merge!(
binds: [unix ? "unix://#{unix}" : "tcp://#{host}:#{port}"]
)
end
def initialize(app, options = {})
@app = app
@options = default_options.merge!(options)
@events = Puma::Events.new
@server = Puma::Server.new(@app, @events, @options)
end
def start(block: false)
@server.binder.parse(@options[:binds])
thr = @server.run
block ? thr.join : thr
end
def stop
@server.stop
end
private
def default_options
{
min_threads: 1,
max_threads: 5,
workers: 1
}
end
end

View file

@ -1,47 +0,0 @@
# frozen_string_literal: true
##
# A rack application that serves the contents
# of a directory over HTTP.
class Server::Dir
prepend Server::Gzip
def initialize(root)
@root = File.realpath(root)
@mime_types = {".ttf" => "font/ttf"}.freeze
end
def call(env)
finish Rack::Request.new(env)
rescue Errno::EPERM, Errno::EACCES
body = "Permission denied"
[403, {"content-length" => body.bytesize, "content-type" => "text/plain"}, [body]]
rescue Errno::ENOENT
body = "The requested URL was not found"
[404, {"content-length" => body.bytesize, "content-type" => "text/plain"}, [body]]
rescue => ex
body = "Internal server error (#{ex.class})"
[500, {"content-length" => body.bytesize, "content-type" => "text/plain"}, [body]]
end
def finish(request)
path = find_path(request)
body = File.binread(path)
extn = File.extname(path)
[
200,
{"content-type" => mime_types[extn] || Rack::Mime.mime_type(extn),
"content-length" => body.bytesize},
body.each_line.to_a
]
end
private
attr_reader :root, :mime_types
def find_path(request)
path = File.join root, File.expand_path(request.path)
File.directory?(path) ? File.join(path, "index.html") : path
end
end

View file

@ -1,18 +0,0 @@
# frozen_string_literal: true
class Server::ETag < Rack::ETag
ETAGS = {}
def initialize(app)
@app = app
end
def call(env)
status, headers, body = super(env)
if headers["etag"] && headers["etag"] == env["HTTP_IF_NONE_MATCH"]
[304, headers, [""]]
else
[status, headers, body]
end
end
end

View file

@ -1,33 +0,0 @@
# 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

View file

@ -1,8 +0,0 @@
# frozen_string_literal: true
require "puma"
require "puma/events"
class Puma::Server
public :binder
end

View file

@ -1,19 +0,0 @@
# frozen_string_literal: true
Gem::Specification.new do |gem|
gem.name = "server.rb"
gem.authors = ["0x1eef"]
gem.email = ["0x1eef@protonmail.com"]
gem.homepage = "https://github.com/0x1eef/server.rb#readme"
gem.version = "0.1.0"
gem.licenses = ["0BSD"]
gem.files = Dir["lib/*", "lib/**/*.rb"]
gem.require_paths = ["lib"]
gem.summary = "A static file web server"
gem.description = gem.summary
gem.add_runtime_dependency "puma", "~> 6.3"
gem.add_runtime_dependency "rack", "~> 3.0"
gem.add_development_dependency "standard", "~> 1.24"
gem.add_development_dependency "rack-test", "~> 2.1"
gem.add_development_dependency "test-unit", "~> 3.5"
end

View file

@ -1,87 +0,0 @@
# frozen_string_literal: true
require_relative "setup"
require "rack/test"
class ServerDirTest < Test::Unit::TestCase
include Rack::Test::Methods
def test_index
get "/"
assert_equal 200, last_response.status
assert_equal "text/html", last_response.content_type
assert_equal bytesize("./test/webroot/index.html"), last_response.content_length
end
def test_ttf_font
get "/fonts/roboto-mono-regular.ttf"
assert_equal 200, last_response.status
assert_equal "font/ttf", last_response.content_type
assert_equal bytesize("./test/webroot/fonts/roboto-mono-regular.ttf"),
last_response.content_length
end
def test_js_file
get "/js/index.js"
assert_equal 200, last_response.status
assert_equal "application/javascript", last_response.content_type
assert_equal bytesize("./test/webroot/js/index.js"),
last_response.content_length
end
def test_png_file
get "/images/0x1eef.png"
assert_equal 200, last_response.status
assert_equal "image/png", last_response.content_type
assert_equal bytesize("./test/webroot/images/0x1eef.png"),
last_response.content_length
end
def test_json_file
get "/json/1.json"
assert_equal 200, last_response.status
assert_equal "application/json", last_response.content_type
assert_equal bytesize("./test/webroot/json/1.json"),
last_response.content_length
end
def test_internal_server_error
def app.finish(request) raise "test" end
get "/"
assert_equal 500, last_response.status
assert_equal "text/plain", last_response.content_type
assert_equal "Internal server error (RuntimeError)".bytesize,
last_response.content_length
assert_equal "Internal server error (RuntimeError)",
last_response.body
end
def test_permission_denied
File.chmod 0, "./test/webroot/permission_denied.html"
get "/permission_denied.html"
assert_equal 403, last_response.status
assert_equal "text/plain", last_response.content_type
assert_equal "Permission denied".bytesize, last_response.content_length
assert_equal "Permission denied", last_response.body
ensure
File.chmod 0o440, "./test/webroot/permission_denied.html"
end
def test_page_not_found
get "/foobarbaz"
assert_equal 404, last_response.status
assert_equal "text/plain", last_response.content_type
assert_equal "The requested URL was not found".bytesize, last_response.content_length
assert_equal "The requested URL was not found", last_response.body
end
private
def app
@app ||= Server.app("./test/webroot/")
end
def bytesize(path)
File.binread(path).bytesize
end
end

View file

@ -1,3 +0,0 @@
require "bundler/setup"
require "test/unit"
require "server"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

View file

@ -1,8 +0,0 @@
<!DOCTYPE html>
<head>
<title>/index.html</title>
</head>
<body>
<b>/index.html</b>
</body>
</html>

View file

@ -1,3 +0,0 @@
(function() {
console.log("Hello world");
})();

View file

@ -1 +0,0 @@
[{"id":"1","place_of_revelation":"makkah","transliterated_name":"Al-Fatihah","translated_name":"The Opener","verse_count":7,"slug":"al-fatihah","codepoints":[1575,1604,1601,1575,1578,1581,1577]},[1,"بِسْمِ اللَّهِ الرَّحْمَـٰنِ الرَّحِيمِ"],[2,"الْحَمْدُ لِلَّهِ رَبِّ الْعَالَمِينَ"],[3,"الرَّحْمَـٰنِ الرَّحِيمِ"],[4,"مَالِكِ يَوْمِ الدِّينِ"],[5,"إِيَّاكَ نَعْبُدُ وَإِيَّاكَ نَسْتَعِينُ"],[6,"اهْدِنَا الصِّرَاطَ الْمُسْتَقِيمَ"],[7,"صِرَاطَ الَّذِينَ أَنْعَمْتَ عَلَيْهِمْ غَيْرِ الْمَغْضُوبِ عَلَيْهِمْ وَلَا الضَّالِّينَ"]]