simple-httpd 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rubocop.yml +80 -0
- data/Gemfile +5 -0
- data/README.md +3 -0
- data/Rakefile +1 -0
- data/VERSION +1 -0
- data/bin/bundle +105 -0
- data/bin/console +15 -0
- data/bin/rake +29 -0
- data/bin/rspec +29 -0
- data/bin/rubocop +29 -0
- data/lib/simple-httpd.rb +3 -0
- data/lib/simple.rb +2 -0
- data/lib/simple/httpd.rb +43 -0
- data/lib/simple/httpd/app.rb +84 -0
- data/lib/simple/httpd/app/file_server.rb +19 -0
- data/lib/simple/httpd/base_controller.rb +24 -0
- data/lib/simple/httpd/base_controller/build_url.rb +37 -0
- data/lib/simple/httpd/base_controller/cors.rb +21 -0
- data/lib/simple/httpd/base_controller/debug.rb +8 -0
- data/lib/simple/httpd/base_controller/erb.rb +20 -0
- data/lib/simple/httpd/base_controller/error_handling.rb +147 -0
- data/lib/simple/httpd/base_controller/json.rb +46 -0
- data/lib/simple/httpd/base_controller/x_processing.rb +11 -0
- data/lib/simple/httpd/version.rb +24 -0
- data/log/.gitkeep +0 -0
- data/scripts/stats +4 -0
- data/scripts/watch +2 -0
- data/simple-httpd.gemspec +41 -0
- data/spec/simple/httpd/version_spec.rb +10 -0
- data/spec/spec_helper.rb +30 -0
- data/spec/support/004_simplecov.rb +22 -0
- data/tasks/release.rake +104 -0
- metadata +204 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e3943911c33876d60f023ec58fab2d875eb9e2b0b23c3649f0d7601e8b1f304c
|
4
|
+
data.tar.gz: 7ff0ef4341bb717ed1b6fafc7339335aa738a660638df64d1b5eba5ec6174a2c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ca193f4c704a1d94f2cc193f953c259c97164dcc28eae9a75347b72e18b31447cf1222df51c36109c129827e09e65e9ad0d3c098fb63a41597052c86cbf08277
|
7
|
+
data.tar.gz: 27045e31517c41301ad6ce9e43c8bad59b90e4e099b64c115a9061ba6eed6b28d238e1a117a65efe85fa3fd0d1d3131a369ffd98cf1beff4b98ceabf94854aa6
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.3
|
3
|
+
Exclude:
|
4
|
+
- 'spec/**/*'
|
5
|
+
- 'test/**/*'
|
6
|
+
- 'bin/**/*'
|
7
|
+
- 'tasks/release.rake'
|
8
|
+
- '*.gemspec'
|
9
|
+
- 'Gemfile'
|
10
|
+
- 'Rakefile'
|
11
|
+
|
12
|
+
Metrics/LineLength:
|
13
|
+
Max: 140
|
14
|
+
|
15
|
+
Metrics/MethodLength:
|
16
|
+
Max: 20
|
17
|
+
|
18
|
+
Style/SpecialGlobalVars:
|
19
|
+
Enabled: false
|
20
|
+
|
21
|
+
Style/StringLiterals:
|
22
|
+
EnforcedStyle: double_quotes
|
23
|
+
ConsistentQuotesInMultiline: false
|
24
|
+
|
25
|
+
Style/ClassAndModuleChildren:
|
26
|
+
Enabled: false
|
27
|
+
|
28
|
+
Style/ModuleFunction:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
Style/FrozenStringLiteralComment:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
Style/Documentation:
|
35
|
+
Enabled: false
|
36
|
+
|
37
|
+
Style/MutableConstant:
|
38
|
+
Enabled: false
|
39
|
+
|
40
|
+
Style/FormatStringToken:
|
41
|
+
Enabled: false
|
42
|
+
|
43
|
+
Style/Lambda:
|
44
|
+
Enabled: false
|
45
|
+
|
46
|
+
Style/SymbolArray:
|
47
|
+
Enabled: false
|
48
|
+
|
49
|
+
Style/FormatString:
|
50
|
+
Enabled: false
|
51
|
+
|
52
|
+
Style/PercentLiteralDelimiters:
|
53
|
+
Enabled: false
|
54
|
+
|
55
|
+
Lint/MissingCopEnableDirective:
|
56
|
+
Enabled: false
|
57
|
+
|
58
|
+
Style/NumericPredicate:
|
59
|
+
Enabled: false
|
60
|
+
|
61
|
+
Style/RegexpLiteral:
|
62
|
+
Enabled: false
|
63
|
+
|
64
|
+
Style/ClassVars:
|
65
|
+
Enabled: false
|
66
|
+
|
67
|
+
Style/ConditionalAssignment:
|
68
|
+
Enabled: false
|
69
|
+
|
70
|
+
Style/IfUnlessModifier:
|
71
|
+
Enabled: false
|
72
|
+
|
73
|
+
Style/PerlBackrefs:
|
74
|
+
Enabled: false
|
75
|
+
|
76
|
+
Style/TrailingUnderscoreVariable:
|
77
|
+
Enabled: false
|
78
|
+
|
79
|
+
Style/StderrPuts:
|
80
|
+
Enabled: false
|
data/Gemfile
ADDED
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Dir.glob("tasks/*.rake").each { |r| import r }
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.2
|
data/bin/bundle
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'bundle' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "rubygems"
|
12
|
+
|
13
|
+
m = Module.new do
|
14
|
+
module_function
|
15
|
+
|
16
|
+
def invoked_as_script?
|
17
|
+
File.expand_path($0) == File.expand_path(__FILE__)
|
18
|
+
end
|
19
|
+
|
20
|
+
def env_var_version
|
21
|
+
ENV["BUNDLER_VERSION"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def cli_arg_version
|
25
|
+
return unless invoked_as_script? # don't want to hijack other binstubs
|
26
|
+
return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
|
27
|
+
bundler_version = nil
|
28
|
+
update_index = nil
|
29
|
+
ARGV.each_with_index do |a, i|
|
30
|
+
if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
|
31
|
+
bundler_version = a
|
32
|
+
end
|
33
|
+
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
|
34
|
+
bundler_version = $1 || ">= 0.a"
|
35
|
+
update_index = i
|
36
|
+
end
|
37
|
+
bundler_version
|
38
|
+
end
|
39
|
+
|
40
|
+
def gemfile
|
41
|
+
gemfile = ENV["BUNDLE_GEMFILE"]
|
42
|
+
return gemfile if gemfile && !gemfile.empty?
|
43
|
+
|
44
|
+
File.expand_path("../../Gemfile", __FILE__)
|
45
|
+
end
|
46
|
+
|
47
|
+
def lockfile
|
48
|
+
lockfile =
|
49
|
+
case File.basename(gemfile)
|
50
|
+
when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
|
51
|
+
else "#{gemfile}.lock"
|
52
|
+
end
|
53
|
+
File.expand_path(lockfile)
|
54
|
+
end
|
55
|
+
|
56
|
+
def lockfile_version
|
57
|
+
return unless File.file?(lockfile)
|
58
|
+
lockfile_contents = File.read(lockfile)
|
59
|
+
return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
|
60
|
+
Regexp.last_match(1)
|
61
|
+
end
|
62
|
+
|
63
|
+
def bundler_version
|
64
|
+
@bundler_version ||= begin
|
65
|
+
env_var_version || cli_arg_version ||
|
66
|
+
lockfile_version || "#{Gem::Requirement.default}.a"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def load_bundler!
|
71
|
+
ENV["BUNDLE_GEMFILE"] ||= gemfile
|
72
|
+
|
73
|
+
# must dup string for RG < 1.8 compatibility
|
74
|
+
activate_bundler(bundler_version.dup)
|
75
|
+
end
|
76
|
+
|
77
|
+
def activate_bundler(bundler_version)
|
78
|
+
if Gem::Version.correct?(bundler_version) && Gem::Version.new(bundler_version).release < Gem::Version.new("2.0")
|
79
|
+
bundler_version = "< 2"
|
80
|
+
end
|
81
|
+
gem_error = activation_error_handling do
|
82
|
+
gem "bundler", bundler_version
|
83
|
+
end
|
84
|
+
return if gem_error.nil?
|
85
|
+
require_error = activation_error_handling do
|
86
|
+
require "bundler/version"
|
87
|
+
end
|
88
|
+
return if require_error.nil? && Gem::Requirement.new(bundler_version).satisfied_by?(Gem::Version.new(Bundler::VERSION))
|
89
|
+
warn "Activating bundler (#{bundler_version}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_version}'`"
|
90
|
+
exit 42
|
91
|
+
end
|
92
|
+
|
93
|
+
def activation_error_handling
|
94
|
+
yield
|
95
|
+
nil
|
96
|
+
rescue StandardError, LoadError => e
|
97
|
+
e
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
m.load_bundler!
|
102
|
+
|
103
|
+
if m.invoked_as_script?
|
104
|
+
load Gem.bin_path("bundler", "bundle")
|
105
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
Bundler.require
|
5
|
+
require "simple-httpd"
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require "irb"
|
15
|
+
IRB.start
|
data/bin/rake
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rake' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rake", "rake")
|
data/bin/rspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rspec' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rspec-core", "rspec")
|
data/bin/rubocop
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rubocop' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
|
13
|
+
Pathname.new(__FILE__).realpath)
|
14
|
+
|
15
|
+
bundle_binstub = File.expand_path("../bundle", __FILE__)
|
16
|
+
|
17
|
+
if File.file?(bundle_binstub)
|
18
|
+
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
19
|
+
load(bundle_binstub)
|
20
|
+
else
|
21
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
22
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require "rubygems"
|
27
|
+
require "bundler/setup"
|
28
|
+
|
29
|
+
load Gem.bin_path("rubocop", "rubocop")
|
data/lib/simple-httpd.rb
ADDED
data/lib/simple.rb
ADDED
data/lib/simple/httpd.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
module Simple
|
2
|
+
end
|
3
|
+
|
4
|
+
module Simple::Httpd
|
5
|
+
end
|
6
|
+
|
7
|
+
require "simple/httpd/version"
|
8
|
+
require "simple/httpd/app"
|
9
|
+
require "simple/httpd/base_controller"
|
10
|
+
|
11
|
+
module Simple::Httpd
|
12
|
+
extend self
|
13
|
+
|
14
|
+
def build_rack(base_controller, logger:)
|
15
|
+
App.new(base_controller, logger: logger)
|
16
|
+
end
|
17
|
+
|
18
|
+
def listen!(app, environment:, port:)
|
19
|
+
expect! port => 80..60_000
|
20
|
+
|
21
|
+
logger = app.logger
|
22
|
+
logger.info "Starting httpd server on http://0.0.0.0:#{port}/"
|
23
|
+
|
24
|
+
app = Rack::Lint.new(app) if environment != "production"
|
25
|
+
|
26
|
+
# re/AccessLog: the AccessLog setting points WEBrick's access logging to the
|
27
|
+
# NullLogger object.
|
28
|
+
#
|
29
|
+
# Instead we'll use a combination of Rack::CommonLogger (see Simple::Httpd.app),
|
30
|
+
# and sinatra's logger (see Simple::Httpd::BaseController).
|
31
|
+
Rack::Server.start app: app,
|
32
|
+
Port: port,
|
33
|
+
environment: environment,
|
34
|
+
Logger: logger,
|
35
|
+
AccessLog: [[NullLogger, ""]]
|
36
|
+
end
|
37
|
+
|
38
|
+
module NullLogger # :nodoc:
|
39
|
+
extend self
|
40
|
+
|
41
|
+
def <<(msg); end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
class Simple::Httpd::App
|
2
|
+
end
|
3
|
+
|
4
|
+
require_relative "app/file_server"
|
5
|
+
|
6
|
+
# The Simple::Httpd::App implements a Rack compatible app, which serves
|
7
|
+
# HTTP requests via a set of controllers inherited from a base controller
|
8
|
+
# class.
|
9
|
+
#
|
10
|
+
# The individual routes are determined from the controller class names:
|
11
|
+
# assuming we have a controller class Foo::Bar::BazController inheriting
|
12
|
+
# from Foo::BaseController will serve the /bar/baz routes.
|
13
|
+
#
|
14
|
+
# Additional static routes can be configured by calling "mount_directory!!"
|
15
|
+
# on the app object.
|
16
|
+
class Simple::Httpd::App
|
17
|
+
extend Forwardable
|
18
|
+
delegate call: :@app
|
19
|
+
|
20
|
+
attr_reader :logger
|
21
|
+
|
22
|
+
#
|
23
|
+
# Builds a App object
|
24
|
+
def initialize(base_controller, logger:)
|
25
|
+
raise unless logger
|
26
|
+
|
27
|
+
@base_controller = base_controller
|
28
|
+
@logger = logger
|
29
|
+
@file_mounts = []
|
30
|
+
|
31
|
+
@app = Rack::URLMap.new(controllers_url_map)
|
32
|
+
end
|
33
|
+
|
34
|
+
def mount_directory!(url:, path:)
|
35
|
+
@logger.debug "#{path}: mount directory #{path}"
|
36
|
+
@app = FileServer.new(@app, url_prefix: url, root: path)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
# Find all controllers inheriting off base_controller and return
|
42
|
+
# a URL map, based on the names of the controllers.
|
43
|
+
def controllers_url_map
|
44
|
+
controller_by_mountpoint = ObjectSpace
|
45
|
+
.each_object(Class)
|
46
|
+
.select { |klass| klass < @base_controller }
|
47
|
+
.map { |controller| [mountpoint(controller), controller] }
|
48
|
+
.reject { |mountpoint, _controller| mountpoint.nil? }
|
49
|
+
|
50
|
+
controller_by_mountpoint
|
51
|
+
.sort_by { |path, _controller| path }
|
52
|
+
.each { |path, controller| logger.debug "#{path}: mount #{controller}" }
|
53
|
+
|
54
|
+
Hash[controller_by_mountpoint]
|
55
|
+
end
|
56
|
+
|
57
|
+
def mountpoint(controller)
|
58
|
+
return unless controller.name.end_with?("Controller")
|
59
|
+
|
60
|
+
relative_controller_name = relative_controller_name(controller)
|
61
|
+
return "/" if relative_controller_name == "RootController"
|
62
|
+
|
63
|
+
"/" + relative_controller_name.underscore.gsub(/_controller$/, "")
|
64
|
+
end
|
65
|
+
|
66
|
+
# With a controller of Postjob::FooBarController returns FooBarController
|
67
|
+
# (depending on the base_controller)
|
68
|
+
def relative_controller_name(controller)
|
69
|
+
controller_name = controller.name
|
70
|
+
if controller_name.start_with?(base_controller_namespace)
|
71
|
+
controller_name[base_controller_namespace.length..-1]
|
72
|
+
else
|
73
|
+
controller_name
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# With a base_controller of Postjob::BaseController this returns "Postjob"
|
78
|
+
def base_controller_namespace
|
79
|
+
@base_controller_namespace ||= begin
|
80
|
+
base_controller_name = @base_controller.name
|
81
|
+
base_controller_name.gsub(/::BaseController$/, "::")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class Simple::Httpd::App::FileServer
|
2
|
+
# A simple file server middleware
|
3
|
+
def initialize(app, url_prefix:, root:)
|
4
|
+
@app = app
|
5
|
+
@url_prefix = File.join("/", url_prefix, "/")
|
6
|
+
@file_server = Rack::File.new(root)
|
7
|
+
end
|
8
|
+
|
9
|
+
def call(env)
|
10
|
+
request_path = env["PATH_INFO"]
|
11
|
+
if request_path.start_with?(@url_prefix)
|
12
|
+
file_path = request_path[@url_prefix.length..-1]
|
13
|
+
env["PATH_INFO"] = file_path
|
14
|
+
@file_server.call(env)
|
15
|
+
else
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Note that all components in base_controller/*.rb are loaded automatically, from
|
2
|
+
# config/routes.rb, **after** this file is loaded. See the end of this file.
|
3
|
+
|
4
|
+
require "sinatra/base"
|
5
|
+
|
6
|
+
class Simple::Httpd::BaseController < Sinatra::Base
|
7
|
+
set :logging, true
|
8
|
+
|
9
|
+
# --- Sinatra::Reloader -----------------------------------------------------
|
10
|
+
|
11
|
+
# Note that Sinatra::Reloader is less thorough than, say, shotgun or the
|
12
|
+
# Rails development mode, but on the other hand it is much faster, and
|
13
|
+
# probably useful 90% of the time.
|
14
|
+
configure :development do
|
15
|
+
require "sinatra/reloader"
|
16
|
+
register Sinatra::Reloader
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
Dir.chdir __dir__ do
|
21
|
+
Dir.glob("base_controller/*.rb").sort.each do |file|
|
22
|
+
require_relative file
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "cgi"
|
2
|
+
|
3
|
+
class Simple::Httpd::BaseController
|
4
|
+
helpers do
|
5
|
+
def base_url
|
6
|
+
@base_url ||= request.base_url
|
7
|
+
end
|
8
|
+
|
9
|
+
def full_url(path, opts = {})
|
10
|
+
build_url(base_url, path, opts)
|
11
|
+
end
|
12
|
+
|
13
|
+
def url(path, opts = {})
|
14
|
+
build_url(path, opts)
|
15
|
+
end
|
16
|
+
|
17
|
+
def build_url(base, *args)
|
18
|
+
option_args, string_args = args.partition { |arg| arg.is_a?(Hash) }
|
19
|
+
options = option_args.inject({}) { |hsh, option| hsh.update option }
|
20
|
+
|
21
|
+
url = File.join([base] + string_args)
|
22
|
+
|
23
|
+
query = build_url_query(options)
|
24
|
+
url += url.index("?") ? "&#{query}" : "?#{query}" if query
|
25
|
+
url
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def build_url_query(params)
|
31
|
+
params = params.reject { |_k, v| v.nil? || v.empty? }
|
32
|
+
return nil if params.empty?
|
33
|
+
|
34
|
+
params.map { |k, value| "#{k}=#{escape(value.to_s)}" }.join("&")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
class Simple::Httpd::BaseController
|
2
|
+
CORS_HEADERS = {
|
3
|
+
"access-control-allow-credentials" => "true",
|
4
|
+
"access-control-allow-headers" => "Origin,X-Requested-With,Content-Type,Accept,Session-Id",
|
5
|
+
"access-control-allow-methods" => "*",
|
6
|
+
"access-control-allow-origin" => "*",
|
7
|
+
# "access-control-expose-headers" => "X-Total-Entries,X-Total-Pages,X-Page,X-Per-Page",
|
8
|
+
# "access-control-max-age" => "-1",
|
9
|
+
"access-control-max-age" => "600",
|
10
|
+
"access-control-request-headers" => "Content-Type",
|
11
|
+
"access-control-request-method" => "GET,POST,PATCH,PUT,DELETE,OPTIONS"
|
12
|
+
}
|
13
|
+
|
14
|
+
options "*" do
|
15
|
+
200
|
16
|
+
end
|
17
|
+
|
18
|
+
after do
|
19
|
+
headers CORS_HEADERS
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require "erb"
|
2
|
+
|
3
|
+
class Simple::Httpd::BaseController
|
4
|
+
# A simple ERB renderer
|
5
|
+
helpers do
|
6
|
+
module ERB::Helpers
|
7
|
+
def self.json(data)
|
8
|
+
JSON.pretty_generate(data)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def erb(template, data)
|
13
|
+
content_type "text/html"
|
14
|
+
|
15
|
+
erb = template.is_a?(ERB) ? template : ERB.new(template)
|
16
|
+
data[:helpers] = ERB::Helpers
|
17
|
+
erb.result_with_hash(data)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require_relative "./json"
|
2
|
+
|
3
|
+
class Simple::Httpd::BaseController
|
4
|
+
set :show_exceptions, false
|
5
|
+
set :dump_errors, false
|
6
|
+
set :raise_errors, false
|
7
|
+
|
8
|
+
set :raise_errors, true if ENV["RACK_ENV"] == "test"
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def stringify_hash(hsh)
|
13
|
+
return unless hsh
|
14
|
+
|
15
|
+
hsh.inject({}) do |r, (k, v)|
|
16
|
+
k = k.to_s if k.is_a?(Symbol)
|
17
|
+
r.update k => v
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
public
|
22
|
+
|
23
|
+
def render_error(exc, options)
|
24
|
+
expect! options => {
|
25
|
+
status: Integer,
|
26
|
+
title: String,
|
27
|
+
description: [String, nil]
|
28
|
+
}
|
29
|
+
|
30
|
+
status options[:status]
|
31
|
+
|
32
|
+
options = stringify_hash(options)
|
33
|
+
options["description"] ||= options["title"]
|
34
|
+
options["@type"] = error_type(exc)
|
35
|
+
options["@now"] = Time.now.to_f
|
36
|
+
|
37
|
+
json options
|
38
|
+
end
|
39
|
+
|
40
|
+
if defined?(Expectation)
|
41
|
+
|
42
|
+
error(Expectation::Matcher::Mismatch) do |exc|
|
43
|
+
render_error exc, status: 400,
|
44
|
+
title: "Invalid input",
|
45
|
+
description: error_description(exc)
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
# class InvalidRequest < RuntimeError
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# error(InvalidRequest) do |e|
|
54
|
+
# render_error e, status: 400,
|
55
|
+
# title: "Invalid input",
|
56
|
+
# description: error_description(e)
|
57
|
+
# end
|
58
|
+
|
59
|
+
error(ArgumentError) do |exc|
|
60
|
+
STDERR.puts "Caught ArgumentError: #{exc}, from\n\t#{exc.backtrace[0, 5].join("\n\t")}"
|
61
|
+
|
62
|
+
render_error exc, status: 422,
|
63
|
+
title: "Invalid input #{exc.inspect}",
|
64
|
+
description: error_description(exc)
|
65
|
+
end
|
66
|
+
|
67
|
+
# class NotAuthorizedError < RuntimeError
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# error(NotAuthorizedError) do
|
71
|
+
# render_error e, status: 403,
|
72
|
+
# title: "Not authorized",
|
73
|
+
# description: "You don't have necessary powers to access this page."
|
74
|
+
# end
|
75
|
+
|
76
|
+
# class LoginRequiredError < RuntimeError
|
77
|
+
# end
|
78
|
+
#
|
79
|
+
# error(LoginRequiredError) do
|
80
|
+
# render_error e, status: 404,
|
81
|
+
# title: "Not found",
|
82
|
+
# description: "The server failed to recognize affiliation. Please provide a valid Session-Id."
|
83
|
+
# end
|
84
|
+
|
85
|
+
class NotFoundError < RuntimeError
|
86
|
+
end
|
87
|
+
|
88
|
+
error(NotFoundError) do |exc|
|
89
|
+
render_error exc, status: 404,
|
90
|
+
title: "Not found",
|
91
|
+
description: error_description(exc)
|
92
|
+
end
|
93
|
+
|
94
|
+
error(Errno::ENOENT) do |exc|
|
95
|
+
render_error exc, status: 404,
|
96
|
+
title: "Not found",
|
97
|
+
description: "The requested record was not found."
|
98
|
+
end
|
99
|
+
|
100
|
+
# -- print unspecified errors.
|
101
|
+
|
102
|
+
error do |exc|
|
103
|
+
message = <<~MSG
|
104
|
+
=== #{exc.class.name} =====================
|
105
|
+
#{exc.message.chomp}
|
106
|
+
|
107
|
+
#{filtered_backtrace(exc)}
|
108
|
+
==================================================================
|
109
|
+
MSG
|
110
|
+
|
111
|
+
STDERR.puts message
|
112
|
+
status 500
|
113
|
+
"\n#{message}\n"
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def error_type(exc)
|
119
|
+
"error/#{exc.class.name.underscore}".gsub(/\/error$/, "")
|
120
|
+
end
|
121
|
+
|
122
|
+
def error_description(exc)
|
123
|
+
exc.message
|
124
|
+
# "#{exc.message}, from #{exc.backtrace.join("\n\t")}"
|
125
|
+
end
|
126
|
+
|
127
|
+
def remove_wd(str)
|
128
|
+
@wd ||= Dir.getwd
|
129
|
+
|
130
|
+
if str.start_with?(@wd)
|
131
|
+
str[(@wd.length + 1)..-1]
|
132
|
+
else
|
133
|
+
str
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def filtered_backtrace(exc, count: 20)
|
138
|
+
lines = exc.backtrace.map do |line|
|
139
|
+
next "...\n" if line =~ /\.rvm\b/
|
140
|
+
|
141
|
+
"#{remove_wd(line)}\n"
|
142
|
+
end
|
143
|
+
|
144
|
+
s = lines[0, count].join("")
|
145
|
+
s.gsub(/(\.\.\.\n)+/, " ... (lines removed) ...\n")
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class Simple::Httpd::BaseController
|
2
|
+
def json(result)
|
3
|
+
content_type :json
|
4
|
+
generate_json(result)
|
5
|
+
end
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def generate_json(result)
|
10
|
+
JSON.generate(result)
|
11
|
+
end
|
12
|
+
|
13
|
+
configure :development, :test do
|
14
|
+
begin
|
15
|
+
@@neatjson = true
|
16
|
+
require "neatjson"
|
17
|
+
rescue LoadError
|
18
|
+
@@neatjson = false
|
19
|
+
end
|
20
|
+
|
21
|
+
def generate_json(result)
|
22
|
+
if @@neatjson
|
23
|
+
JSON.neat_generate(result)
|
24
|
+
else
|
25
|
+
JSON.pretty_generate(result)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
public
|
31
|
+
|
32
|
+
def parsed_json_body
|
33
|
+
@parsed_json_body ||= parse_json_body
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def parse_json_body
|
39
|
+
unless request.content_type =~ /application\/json/
|
40
|
+
raise "Cannot parse non-JSON request body w/content_type #{request.content_type.inspect}"
|
41
|
+
end
|
42
|
+
|
43
|
+
request.body.rewind
|
44
|
+
JSON.parse(request.body.read)
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Simple::Httpd
|
2
|
+
module GemHelper
|
3
|
+
extend self
|
4
|
+
|
5
|
+
def version(name)
|
6
|
+
spec = Gem.loaded_specs[name]
|
7
|
+
version = spec ? spec.version.to_s : "0.0.0"
|
8
|
+
version += "+unreleased" if !spec || unreleased?(spec)
|
9
|
+
version
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def unreleased?(spec)
|
15
|
+
return false unless defined?(Bundler::Source::Gemspec)
|
16
|
+
return true if spec.source.is_a?(::Bundler::Source::Gemspec)
|
17
|
+
return true if spec.source.is_a?(::Bundler::Source::Path)
|
18
|
+
|
19
|
+
false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
VERSION = GemHelper.version "postjob"
|
24
|
+
end
|
data/log/.gitkeep
ADDED
File without changes
|
data/scripts/stats
ADDED
data/scripts/watch
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# This file is part of the sinatra-sse ruby gem.
|
2
|
+
#
|
3
|
+
# Copyright (c) 2016, 2017 @radiospiel, mediapeers Gem
|
4
|
+
# Distributed under the terms of the modified BSD license, see LICENSE.BSD
|
5
|
+
|
6
|
+
lib = File.expand_path('../lib', __FILE__)
|
7
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
8
|
+
|
9
|
+
Gem::Specification.new do |gem|
|
10
|
+
gem.name = "simple-httpd"
|
11
|
+
gem.version = File.read("VERSION")
|
12
|
+
|
13
|
+
gem.authors = [ "radiospiel" ]
|
14
|
+
gem.email = "eno@radiospiel.org"
|
15
|
+
gem.homepage = "http://github.com/radiospiel/simple-httpd"
|
16
|
+
gem.summary = "Super-simple HTTPD server"
|
17
|
+
|
18
|
+
gem.description = "Super-simple HTTPD server - sinatra w/gimmiks"
|
19
|
+
|
20
|
+
gem.files = `git ls-files`.split($/)
|
21
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
22
|
+
gem.require_paths = %w(lib)
|
23
|
+
|
24
|
+
# executables are used for development purposes only
|
25
|
+
gem.executables = []
|
26
|
+
|
27
|
+
gem.required_ruby_version = '~> 2.5'
|
28
|
+
|
29
|
+
# -- dependencies for postjob httpd
|
30
|
+
gem.add_runtime_dependency "neatjson", "~> 0.8.4"
|
31
|
+
gem.add_runtime_dependency "sinatra", "~> 2"
|
32
|
+
gem.add_runtime_dependency "sinatra-reloader", "~> 1"
|
33
|
+
|
34
|
+
# development gems
|
35
|
+
gem.add_development_dependency "rspec-httpd", "~> 0.0.14"
|
36
|
+
gem.add_development_dependency 'rake', '~> 11'
|
37
|
+
gem.add_development_dependency 'rspec', '~> 3.7'
|
38
|
+
gem.add_development_dependency 'rubocop', '~> 0.61.1'
|
39
|
+
gem.add_development_dependency 'simplecov', '~> 0'
|
40
|
+
gem.add_development_dependency 'awesome_print', '~> 0'
|
41
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
%w(auth authentication authorization).each do |library_name|
|
2
|
+
path = File.expand_path("../../#{library_name}/lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
|
4
|
+
end
|
5
|
+
|
6
|
+
ENV["RACK_ENV"] = "test"
|
7
|
+
ENV["RAILS_ENV"] = "test"
|
8
|
+
|
9
|
+
require "byebug"
|
10
|
+
require "rspec"
|
11
|
+
require "awesome_print"
|
12
|
+
Dir.glob("./spec/support/**/*.rb").sort.each { |path| load path }
|
13
|
+
|
14
|
+
require "simple/httpd"
|
15
|
+
|
16
|
+
RSpec.configure do |config|
|
17
|
+
config.run_all_when_everything_filtered = true
|
18
|
+
config.filter_run focus: (ENV["CI"] != "true")
|
19
|
+
config.expect_with(:rspec) { |c| c.syntax = :expect }
|
20
|
+
config.order = "random"
|
21
|
+
config.example_status_persistence_file_path = ".rspec.data"
|
22
|
+
|
23
|
+
config.backtrace_exclusion_patterns << /spec\/support/
|
24
|
+
config.backtrace_exclusion_patterns << /spec_helper/
|
25
|
+
config.backtrace_exclusion_patterns << /database_cleaner/
|
26
|
+
|
27
|
+
# config.around(:each) do |example|
|
28
|
+
# example.run
|
29
|
+
# end
|
30
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "simplecov"
|
2
|
+
|
3
|
+
# make sure multiple runs result in multiple result set. SimpleCov will take
|
4
|
+
# care of merging these results automatically.
|
5
|
+
SimpleCov.command_name "test:#{ENV['USE_ACTIVE_RECORD']}"
|
6
|
+
|
7
|
+
USE_ACTIVE_RECORD = ENV["USE_ACTIVE_RECORD"] == "1"
|
8
|
+
|
9
|
+
SimpleCov.start do
|
10
|
+
# return true to remove src from coverage
|
11
|
+
add_filter do |src|
|
12
|
+
next true if src.filename =~ /\/spec\//
|
13
|
+
next true if src.filename =~ /\/immutable\.rb/
|
14
|
+
|
15
|
+
next true if USE_ACTIVE_RECORD && src.filename =~ /\/sql\/connection\/raw_connection\.rb/
|
16
|
+
next true if !USE_ACTIVE_RECORD && src.filename =~ /\/sql\/connection\/active_record_connection\.rb/
|
17
|
+
|
18
|
+
false
|
19
|
+
end
|
20
|
+
|
21
|
+
minimum_coverage 90
|
22
|
+
end
|
data/tasks/release.rake
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler.setup
|
3
|
+
|
4
|
+
GEM_ROOT = File.expand_path('../../', __FILE__)
|
5
|
+
GEM_SPEC, more = Dir.glob("*.gemspec")
|
6
|
+
raise "Cannot determine gemspec" if more || !GEM_SPEC
|
7
|
+
|
8
|
+
VERSION_FILE_PATH = 'VERSION'
|
9
|
+
|
10
|
+
class VersionNumberTracker
|
11
|
+
class << self
|
12
|
+
def update_version_file(new_version_number)
|
13
|
+
File.open(VERSION_FILE_PATH, 'w') { |file| file.puts new_version_number }
|
14
|
+
new_version_number
|
15
|
+
end
|
16
|
+
|
17
|
+
def auto_version_bump
|
18
|
+
old_version_number = File.read("VERSION")
|
19
|
+
old = old_version_number.split('.')
|
20
|
+
current = old[0..-2] << old[-1].next
|
21
|
+
new_version_number = current.join('.')
|
22
|
+
|
23
|
+
update_version_file(new_version_number)
|
24
|
+
end
|
25
|
+
|
26
|
+
def manual_version_bump
|
27
|
+
update_version_file(ENV['VERSION'])
|
28
|
+
end
|
29
|
+
|
30
|
+
def update_version_number
|
31
|
+
@version = ENV['VERSION'] ? manual_version_bump : auto_version_bump
|
32
|
+
end
|
33
|
+
|
34
|
+
attr_reader :version
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
namespace :release do
|
39
|
+
task :version do
|
40
|
+
VersionNumberTracker.update_version_number
|
41
|
+
end
|
42
|
+
|
43
|
+
task :build do
|
44
|
+
Dir.chdir(GEM_ROOT) do
|
45
|
+
sh("gem build #{GEM_SPEC}")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
desc "Commit changes"
|
50
|
+
task :commit do
|
51
|
+
Dir.chdir(GEM_ROOT) do
|
52
|
+
version = VersionNumberTracker.version
|
53
|
+
sh("git add #{VERSION_FILE_PATH}")
|
54
|
+
sh("git commit -m \"bump to v#{version}\"")
|
55
|
+
sh("git tag -a v#{version} -m \"Tag\"")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
desc "Push code and tags"
|
60
|
+
task :push do
|
61
|
+
sh("git push origin #{$TARGET_BRANCH}")
|
62
|
+
sh('git push --tags')
|
63
|
+
end
|
64
|
+
|
65
|
+
desc "Cleanup"
|
66
|
+
task :clean do
|
67
|
+
Dir.glob(File.join(GEM_ROOT, '*.gem')).each { |f| FileUtils.rm_rf(f) }
|
68
|
+
end
|
69
|
+
|
70
|
+
desc "Push Gem to gemfury"
|
71
|
+
task :publish do
|
72
|
+
Dir.chdir(GEM_ROOT) { sh("gem push #{Dir.glob('*.gem').first}") }
|
73
|
+
end
|
74
|
+
|
75
|
+
task :target_master do
|
76
|
+
$TARGET_BRANCH = 'master'
|
77
|
+
end
|
78
|
+
|
79
|
+
task :target_stable do
|
80
|
+
$TARGET_BRANCH = 'stable'
|
81
|
+
end
|
82
|
+
|
83
|
+
task :checkout do
|
84
|
+
sh "git status --untracked-files=no --porcelain > /dev/null || (echo '*** working dir not clean' && false)"
|
85
|
+
sh "git checkout #{$TARGET_BRANCH}"
|
86
|
+
sh "git pull"
|
87
|
+
end
|
88
|
+
|
89
|
+
task default: [
|
90
|
+
'checkout',
|
91
|
+
'version',
|
92
|
+
'clean',
|
93
|
+
'build',
|
94
|
+
'commit',
|
95
|
+
'push',
|
96
|
+
'publish'
|
97
|
+
]
|
98
|
+
|
99
|
+
task master: %w(target_master default)
|
100
|
+
task stable: %w(target_stable default)
|
101
|
+
end
|
102
|
+
|
103
|
+
desc "Clean, build, commit and push"
|
104
|
+
task release: 'release:master'
|
metadata
ADDED
@@ -0,0 +1,204 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simple-httpd
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- radiospiel
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2019-06-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: neatjson
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.8.4
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.8.4
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sinatra
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sinatra-reloader
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec-httpd
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.0.14
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.0.14
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '11'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '11'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.7'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.7'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.61.1
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.61.1
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: simplecov
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: awesome_print
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
description: Super-simple HTTPD server - sinatra w/gimmiks
|
140
|
+
email: eno@radiospiel.org
|
141
|
+
executables: []
|
142
|
+
extensions: []
|
143
|
+
extra_rdoc_files: []
|
144
|
+
files:
|
145
|
+
- ".gitignore"
|
146
|
+
- ".rubocop.yml"
|
147
|
+
- Gemfile
|
148
|
+
- README.md
|
149
|
+
- Rakefile
|
150
|
+
- VERSION
|
151
|
+
- bin/bundle
|
152
|
+
- bin/console
|
153
|
+
- bin/rake
|
154
|
+
- bin/rspec
|
155
|
+
- bin/rubocop
|
156
|
+
- lib/simple-httpd.rb
|
157
|
+
- lib/simple.rb
|
158
|
+
- lib/simple/httpd.rb
|
159
|
+
- lib/simple/httpd/app.rb
|
160
|
+
- lib/simple/httpd/app/file_server.rb
|
161
|
+
- lib/simple/httpd/base_controller.rb
|
162
|
+
- lib/simple/httpd/base_controller/build_url.rb
|
163
|
+
- lib/simple/httpd/base_controller/cors.rb
|
164
|
+
- lib/simple/httpd/base_controller/debug.rb
|
165
|
+
- lib/simple/httpd/base_controller/erb.rb
|
166
|
+
- lib/simple/httpd/base_controller/error_handling.rb
|
167
|
+
- lib/simple/httpd/base_controller/json.rb
|
168
|
+
- lib/simple/httpd/base_controller/x_processing.rb
|
169
|
+
- lib/simple/httpd/version.rb
|
170
|
+
- log/.gitkeep
|
171
|
+
- scripts/stats
|
172
|
+
- scripts/watch
|
173
|
+
- simple-httpd.gemspec
|
174
|
+
- spec/simple/httpd/version_spec.rb
|
175
|
+
- spec/spec_helper.rb
|
176
|
+
- spec/support/004_simplecov.rb
|
177
|
+
- tasks/release.rake
|
178
|
+
homepage: http://github.com/radiospiel/simple-httpd
|
179
|
+
licenses: []
|
180
|
+
metadata: {}
|
181
|
+
post_install_message:
|
182
|
+
rdoc_options: []
|
183
|
+
require_paths:
|
184
|
+
- lib
|
185
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
186
|
+
requirements:
|
187
|
+
- - "~>"
|
188
|
+
- !ruby/object:Gem::Version
|
189
|
+
version: '2.5'
|
190
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
191
|
+
requirements:
|
192
|
+
- - ">="
|
193
|
+
- !ruby/object:Gem::Version
|
194
|
+
version: '0'
|
195
|
+
requirements: []
|
196
|
+
rubyforge_project:
|
197
|
+
rubygems_version: 2.7.6
|
198
|
+
signing_key:
|
199
|
+
specification_version: 4
|
200
|
+
summary: Super-simple HTTPD server
|
201
|
+
test_files:
|
202
|
+
- spec/simple/httpd/version_spec.rb
|
203
|
+
- spec/spec_helper.rb
|
204
|
+
- spec/support/004_simplecov.rb
|