simple-httpd 0.3.0 → 0.3.1
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 +4 -4
- data/.rubocop.yml +7 -0
- data/Gemfile +3 -1
- data/VERSION +1 -1
- data/bin/simple-httpd +1 -3
- data/examples/ex1.services/ex1_service_module.rb +8 -0
- data/examples/ex1/root.rb +4 -0
- data/examples/ex1/spec.rb +7 -0
- data/examples/ex2/info.rb +5 -3
- data/examples/ex3/example_service.rb +3 -2
- data/lib/simple/httpd.rb +37 -28
- data/lib/simple/httpd/base_controller.rb +6 -0
- data/lib/simple/httpd/base_controller/build_url.rb +1 -1
- data/lib/simple/httpd/base_controller/debug.rb +2 -0
- data/lib/simple/httpd/base_controller/error_handling.rb +21 -38
- data/lib/simple/httpd/base_controller/json.rb +2 -31
- data/lib/simple/httpd/base_controller/request.rb +23 -0
- data/lib/simple/httpd/base_controller/result.rb +19 -0
- data/lib/simple/httpd/cli.rb +71 -30
- data/lib/simple/httpd/helpers.rb +35 -3
- data/lib/simple/httpd/mount.rb +66 -0
- data/lib/simple/httpd/rack/dynamic_mount.rb +52 -32
- data/lib/simple/httpd/rack/static_mount.rb +20 -14
- data/lib/simple/httpd/route.rb +79 -0
- data/lib/simple/httpd/server.rb +28 -16
- data/lib/simple/httpd/service_adapter.rb +108 -0
- data/simple-httpd.gemspec +2 -1
- data/spec/simple/httpd/base_controller/httpd_cors_spec.rb +8 -3
- data/spec/simple/httpd/base_controller/httpd_url_building_spec.rb +17 -0
- data/spec/simple/httpd/helpers_spec.rb +25 -8
- data/spec/simple/httpd/loading_helpers_spec.rb +15 -0
- data/spec/simple/httpd/rspec_httpd_spec.rb +25 -9
- data/spec/simple/httpd/services/service_explicit_spec.rb +0 -5
- data/spec/simple/httpd/services/sideloading_spec.rb +9 -0
- data/spec/spec_helper.rb +2 -3
- metadata +31 -12
- data/examples/services/example_service.rb +0 -25
- data/lib/simple/httpd/mount_spec.rb +0 -106
- data/lib/simple/httpd/service.rb +0 -70
- data/lib/simple/service.rb +0 -69
- data/lib/simple/service/action.rb +0 -78
- data/lib/simple/service/context.rb +0 -46
- data/spec/simple/httpd/services/service_spec.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4a7ef636de1fafcba61a0e8d7ed71a235d9c4700633f8ef8a899028415ffa1c7
|
4
|
+
data.tar.gz: 2018dc0e1bd99ec1bdc40524bfe2701be509e252cb6655b21e629e996da22614
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dd3fc097a2342e19b79c087fec69c92db23085c2352d323c3b284e60eaa764543048f731063e0d3c31ad3e136dc1bb2518456c00519f9231c0f3cde57a96f0d2
|
7
|
+
data.tar.gz: aff819af94b2b12d8e02c1c966dc9eeb9eb6d3b4a805778d609600d2dc9ff33dccb435983ecf4e1221e5346b899ccd7b358d625756fe26b912bf662b94770226
|
data/.rubocop.yml
CHANGED
@@ -8,6 +8,7 @@ AllCops:
|
|
8
8
|
- '*.gemspec'
|
9
9
|
- 'Gemfile'
|
10
10
|
- 'Rakefile'
|
11
|
+
- 'scripts/*.rb'
|
11
12
|
|
12
13
|
Metrics/LineLength:
|
13
14
|
Max: 140
|
@@ -87,3 +88,9 @@ Metrics/ParameterLists:
|
|
87
88
|
|
88
89
|
Style/StringLiteralsInInterpolation:
|
89
90
|
Enabled: false
|
91
|
+
|
92
|
+
Style/DoubleNegation:
|
93
|
+
Enabled: false
|
94
|
+
|
95
|
+
Style/ParallelAssignment:
|
96
|
+
Enabled: false
|
data/Gemfile
CHANGED
@@ -6,12 +6,14 @@ gemspec
|
|
6
6
|
# --- Local overrides for runtime dependencies ------------------------------
|
7
7
|
|
8
8
|
# gem "simple-cli", path: "../simple-cli"
|
9
|
+
# gem "simple-service", path: "../simple-service"
|
9
10
|
|
10
11
|
# --- Development and test dependencies ------------------------------
|
11
12
|
|
12
13
|
group :development, :test do
|
13
|
-
gem "rspec-httpd", "~> 0.3.
|
14
|
+
gem "rspec-httpd", "~> 0.3.2"
|
14
15
|
# gem "rspec-httpd", path: "../rspec-httpd"
|
16
|
+
# # gem "simple-http", path: "../simple-http"
|
15
17
|
|
16
18
|
gem 'rake', '~> 11'
|
17
19
|
gem 'rspec', '~> 3.7'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.1
|
data/bin/simple-httpd
CHANGED
data/examples/ex1/root.rb
CHANGED
data/examples/ex2/info.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
get
|
2
|
-
|
3
|
-
|
1
|
+
[:get, :post, :put, :delete, :head].each do |verb|
|
2
|
+
send verb, "/inspect" do
|
3
|
+
content_type :text
|
4
|
+
request.env.map { |key, value| "#{key}=#{value}\n" }.grep(/^[A-Z]/).sort.join
|
5
|
+
end
|
4
6
|
end
|
@@ -7,7 +7,8 @@ mount_service ExplicitService do |service|
|
|
7
7
|
post "/echo/:a" => :explicit_echo
|
8
8
|
|
9
9
|
put "/echo_context" do
|
10
|
-
|
11
|
-
|
10
|
+
::Simple::Service.with_context(context) do
|
11
|
+
::Simple::Service.invoke(service, :echo_context)
|
12
|
+
end
|
12
13
|
end
|
13
14
|
end
|
data/lib/simple/httpd.rb
CHANGED
@@ -11,20 +11,29 @@ require "simple/service"
|
|
11
11
|
require "simple/httpd/helpers"
|
12
12
|
require "simple/httpd/base_controller"
|
13
13
|
require "simple/httpd/version"
|
14
|
-
require "simple/httpd/
|
14
|
+
require "simple/httpd/mount"
|
15
15
|
require "simple/httpd/server"
|
16
16
|
|
17
|
-
require "simple/httpd/
|
17
|
+
require "simple/httpd/service_adapter"
|
18
18
|
|
19
19
|
class Simple::Httpd
|
20
20
|
SELF = self
|
21
21
|
|
22
|
-
|
23
|
-
|
22
|
+
# returns a logger for Simple::Httpd.
|
23
|
+
#
|
24
|
+
# Initially we default to <tt>::Simple::CLI.logger</tt>. This gives colored
|
25
|
+
# logging during loading and mounting. Note that Simple::Httpd::Server builds
|
26
|
+
# its own logger instance to to pass that along to the web server.
|
27
|
+
def self.logger
|
28
|
+
@logger ||= ::Simple::CLI.logger
|
24
29
|
end
|
25
30
|
|
26
|
-
def self.
|
27
|
-
@logger
|
31
|
+
def self.custom_logger?
|
32
|
+
@logger && @logger != ::Simple::CLI.logger
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.logger=(logger)
|
36
|
+
@logger = logger
|
28
37
|
end
|
29
38
|
|
30
39
|
# Converts the passed in args into a Simple::Httpd application.
|
@@ -34,43 +43,49 @@ class Simple::Httpd
|
|
34
43
|
# respond to call/3) it redirects to <tt>Server.listen!</tt> right
|
35
44
|
# away - this way this method can be used as a helper method
|
36
45
|
# to easily start a Rack server.
|
37
|
-
def self.listen!(*
|
46
|
+
def self.listen!(*mounts, environment: "development", host: nil, port:, &block)
|
38
47
|
# If there is no argument but a block use the block as a rack server
|
39
48
|
if block
|
40
|
-
raise ArgumentError, "Can't deal w/block *and*
|
49
|
+
raise ArgumentError, "Can't deal w/block *and* mounts" unless mounts.empty?
|
41
50
|
|
42
51
|
app = block
|
43
|
-
elsif
|
52
|
+
elsif mounts.length == 1 && mounts.first.respond_to?(:call)
|
44
53
|
# there is one argument, and that looks like a Rack app: return that.
|
45
|
-
app =
|
54
|
+
app = mounts.first
|
46
55
|
else
|
47
56
|
# Build a Httpd app, and listen
|
48
|
-
app = build(*
|
57
|
+
app = build(*mounts)
|
49
58
|
app.rack
|
50
59
|
end
|
51
60
|
|
52
|
-
Server.listen!(app, environment: environment, host: host, port: port
|
61
|
+
Server.listen!(app, environment: environment, host: host, port: port)
|
53
62
|
end
|
54
63
|
|
55
64
|
# Converts the passed in arguments into a Simple::Httpd application.
|
56
65
|
#
|
57
66
|
# For a description of mounts see <tt>#add</tt>
|
58
|
-
def self.build(*
|
59
|
-
new(*
|
67
|
+
def self.build(*mounts)
|
68
|
+
new(*mounts)
|
60
69
|
end
|
61
70
|
|
62
71
|
private
|
63
72
|
|
64
73
|
# Builds a Simple::Httpd application.
|
65
|
-
def initialize(*
|
66
|
-
@
|
67
|
-
|
68
|
-
mount(
|
74
|
+
def initialize(*mounts)
|
75
|
+
@mounts = []
|
76
|
+
mounts.map do |mount|
|
77
|
+
mount(mount, at: nil)
|
69
78
|
end
|
70
79
|
end
|
71
80
|
|
72
81
|
public
|
73
82
|
|
83
|
+
def route_descriptions
|
84
|
+
@mounts.inject([]) do |ary, mount|
|
85
|
+
ary.concat mount.route_descriptions
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
74
89
|
# Adds one or more mount_points
|
75
90
|
#
|
76
91
|
# Each entry in mounts can be either:
|
@@ -79,10 +94,10 @@ class Simple::Httpd
|
|
79
94
|
# - a string denoting a mount_point, e.g. "path/to/root:/")
|
80
95
|
# - a string denoting a "/" mount_point (e.g. "path", which is shorthand for "path:/")
|
81
96
|
#
|
82
|
-
def mount(
|
97
|
+
def mount(mount, at: nil)
|
83
98
|
raise ArgumentError, "Cannot mount onto an already built app" if built?
|
84
99
|
|
85
|
-
@
|
100
|
+
@mounts << Mount.build(mount, at: at)
|
86
101
|
end
|
87
102
|
|
88
103
|
extend Forwardable
|
@@ -97,8 +112,8 @@ class Simple::Httpd
|
|
97
112
|
def build_rack
|
98
113
|
uri_map = {}
|
99
114
|
|
100
|
-
@
|
101
|
-
apps =
|
115
|
+
@mounts.group_by(&:mount_point).map do |mount_point, mounts|
|
116
|
+
apps = mounts.map(&:build_rack_apps).flatten
|
102
117
|
uri_map[mount_point] = Rack.merge(apps)
|
103
118
|
end
|
104
119
|
|
@@ -108,10 +123,4 @@ class Simple::Httpd
|
|
108
123
|
def built?
|
109
124
|
@rack != nil
|
110
125
|
end
|
111
|
-
|
112
|
-
public
|
113
|
-
|
114
|
-
def listen!(environment:, port:, logger:)
|
115
|
-
SELF.listen!(rack, environment: environment, port: port, logger: logger)
|
116
|
-
end
|
117
126
|
end
|
@@ -17,6 +17,12 @@ class Simple::Httpd::BaseController < Sinatra::Base
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
require_relative "./route"
|
21
|
+
|
22
|
+
class Simple::Httpd::BaseController
|
23
|
+
extend ::Simple::Httpd::RouteDescriptions
|
24
|
+
end
|
25
|
+
|
20
26
|
Dir.chdir __dir__ do
|
21
27
|
Dir.glob("base_controller/*.rb").sort.each do |file|
|
22
28
|
require_relative file
|
@@ -28,7 +28,7 @@ class Simple::Httpd::BaseController
|
|
28
28
|
private
|
29
29
|
|
30
30
|
def build_url_query(params)
|
31
|
-
params = params.reject { |_k, v| v.nil? || v.empty? }
|
31
|
+
params = params.reject { |_k, v| v.nil? || v.to_s.empty? }
|
32
32
|
return nil if params.empty?
|
33
33
|
|
34
34
|
params.map { |k, value| "#{k}=#{escape(value.to_s)}" }.join("&")
|
@@ -1,7 +1,5 @@
|
|
1
1
|
require_relative "./json"
|
2
2
|
|
3
|
-
# rubocop:disable Metrics/ClassLength
|
4
|
-
|
5
3
|
class Simple::Httpd::BaseController
|
6
4
|
H = ::Simple::Httpd::Helpers
|
7
5
|
|
@@ -9,8 +7,6 @@ class Simple::Httpd::BaseController
|
|
9
7
|
set :dump_errors, false
|
10
8
|
set :raise_errors, false
|
11
9
|
|
12
|
-
set :raise_errors, true if ENV["RACK_ENV"] == "test"
|
13
|
-
|
14
10
|
private
|
15
11
|
|
16
12
|
def stringify_hash(hsh)
|
@@ -127,19 +123,27 @@ class Simple::Httpd::BaseController
|
|
127
123
|
|
128
124
|
# -- print unspecified errors.
|
129
125
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
126
|
+
if ENV["RACK_ENV"] == "production"
|
127
|
+
error do |exc|
|
128
|
+
content_type :text
|
129
|
+
status 500
|
130
|
+
exc.class.name
|
131
|
+
end
|
132
|
+
else
|
133
|
+
error do |exc|
|
134
|
+
content_type :text
|
135
|
+
message = <<~MSG
|
136
|
+
=== #{exc.class.name} =====================
|
137
|
+
#{exc.message.chomp}
|
138
|
+
|
139
|
+
#{H.filtered_stacktrace(exc.backtrace).join("\n")}
|
140
|
+
==================================================================
|
141
|
+
MSG
|
142
|
+
|
143
|
+
STDERR.puts message
|
144
|
+
status 500
|
145
|
+
"\n#{message}\n"
|
146
|
+
end
|
143
147
|
end
|
144
148
|
|
145
149
|
private
|
@@ -152,25 +156,4 @@ class Simple::Httpd::BaseController
|
|
152
156
|
exc.message
|
153
157
|
# "#{exc.message}, from #{exc.backtrace.join("\n\t")}"
|
154
158
|
end
|
155
|
-
|
156
|
-
def remove_wd(str)
|
157
|
-
@wd ||= Dir.getwd
|
158
|
-
|
159
|
-
if str.start_with?(@wd)
|
160
|
-
str[(@wd.length + 1)..-1]
|
161
|
-
else
|
162
|
-
str
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
def filtered_backtrace(exc, count: 20)
|
167
|
-
lines = exc.backtrace.map do |line|
|
168
|
-
next "...\n" if line =~ /\.rvm\b/
|
169
|
-
|
170
|
-
"#{remove_wd(line)}\n"
|
171
|
-
end
|
172
|
-
|
173
|
-
s = lines[0, count].join("")
|
174
|
-
s.gsub(/(\.\.\.\n)+/, " ... (lines removed) ...\n")
|
175
|
-
end
|
176
159
|
end
|
@@ -12,42 +12,13 @@ class Simple::Httpd::BaseController
|
|
12
12
|
|
13
13
|
configure :development, :test do
|
14
14
|
begin
|
15
|
-
@@neatjson = true
|
16
15
|
require "neatjson"
|
17
16
|
rescue LoadError
|
18
|
-
|
17
|
+
:nop
|
19
18
|
end
|
20
19
|
|
21
20
|
def generate_json(result)
|
22
|
-
|
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_body
|
33
|
-
return @parsed_body if defined? @parsed_body
|
34
|
-
|
35
|
-
@parsed_body = parse_body
|
36
|
-
rescue RuntimeError => e
|
37
|
-
raise ArgumentError, e.to_s
|
38
|
-
end
|
39
|
-
|
40
|
-
private
|
41
|
-
|
42
|
-
def parse_body
|
43
|
-
case request.media_type
|
44
|
-
when "application/json"
|
45
|
-
request.body.rewind
|
46
|
-
body = request.body.read
|
47
|
-
body == "" ? {} : JSON.parse(body)
|
48
|
-
else
|
49
|
-
# parses form data
|
50
|
-
request.POST
|
21
|
+
JSON.respond_to?(:neat_generate) ? JSON.neat_generate(result) : JSON.pretty_generate(result)
|
51
22
|
end
|
52
23
|
end
|
53
24
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Simple::Httpd::BaseController
|
2
|
+
def parsed_body
|
3
|
+
return @parsed_body if defined? @parsed_body
|
4
|
+
|
5
|
+
@parsed_body = parse_body
|
6
|
+
rescue RuntimeError => e
|
7
|
+
raise ArgumentError, e.to_s
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def parse_body
|
13
|
+
case request.media_type
|
14
|
+
when "application/json"
|
15
|
+
request.body.rewind
|
16
|
+
body = request.body.read
|
17
|
+
body == "" ? {} : JSON.parse(body)
|
18
|
+
else
|
19
|
+
# parses form data
|
20
|
+
request.POST
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class ::Simple::Httpd::BaseController
|
2
|
+
private
|
3
|
+
|
4
|
+
# encodes the result, according to its payload.
|
5
|
+
#
|
6
|
+
# This function is used by the service integration code, but
|
7
|
+
# is potentially useful outside.
|
8
|
+
def encode_result(result)
|
9
|
+
case result
|
10
|
+
when Array, Hash
|
11
|
+
json(result)
|
12
|
+
when String
|
13
|
+
content_type :text
|
14
|
+
result
|
15
|
+
else
|
16
|
+
result
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|