simple-httpd 0.3.4 → 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e552a1dc3cc22d3fa1e614a440e86820ec7f95157711f77cfb5b2492966a4414
4
- data.tar.gz: d014f9712b6493403d09a35b650467070dd46079a6bf401f22aa2da9edcb79a3
3
+ metadata.gz: 00457b4ed11c8a501e43a4c4826ef6d78722b072ffff0bab1b0c609c797e14f7
4
+ data.tar.gz: ed35d788fba032b31b971f29e07b23cf490ffc1d96a3aff9369bc812bda22dde
5
5
  SHA512:
6
- metadata.gz: 6c258058969660cf9c45a6a1fb5193b1f5fdba24cda123bd77257531251da295082c5c71af48af16aa01fae9f28539c66409b8900d005ba525ad4ab52aa70ad8
7
- data.tar.gz: 5bf9584a2c7be956483792568aa19e8996ec116ae8c49998da39e104c5943414ed3b6fb8ef6d3664958c851037292ef769f6b4248b7cca894a21d43c03d1aa11
6
+ metadata.gz: 0d57c201cad87a16655eb6e05a4b527176603ab063d08878b44711741babd3fb62140224b5e7cfd0c6ff3e2937c5d177c6ffcb4d88143903f99d36bd5d937f02
7
+ data.tar.gz: a55d03f273b5a634262a55916c15690bf845641f69af2217a82d4a778b84af089cdb3722df89c25d4d1d847a2654f4c858c141900115e895c8fa3d8ef55dbc4b
data/.envrc ADDED
@@ -0,0 +1,7 @@
1
+ # A direnv config file: https://github.com/direnv/direnv
2
+
3
+ if [ "$(type -t direnv_load)" = 'function' ]; then
4
+ # Whatever you want only direnv to execute
5
+ PATH_add bin
6
+ fi
7
+
data/.rubocop.yml CHANGED
@@ -16,6 +16,9 @@ Metrics/LineLength:
16
16
  Metrics/MethodLength:
17
17
  Max: 20
18
18
 
19
+ Metrics/AbcSize:
20
+ Max: 20
21
+
19
22
  Style/SpecialGlobalVars:
20
23
  Enabled: false
21
24
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.4
1
+ 0.3.5
data/examples/ex1/root.rb CHANGED
@@ -1,3 +1,11 @@
1
+ # This would be an example of sleeping for 1 sec with thin/eventmachine.
2
+ #
3
+ # aget "/" do
4
+ # EM.add_timer(1) {
5
+ # body { "hello sync" }
6
+ # }
7
+ # end
8
+
1
9
  get "/" do
2
10
  "root"
3
11
  end
@@ -7,8 +7,6 @@ mount_service ExplicitService do |service|
7
7
  post "/echo/:a" => :explicit_echo
8
8
 
9
9
  put "/echo_context" do
10
- ::Simple::Service.with_context(context) do
11
- ::Simple::Service.invoke(service, :echo_context)
12
- end
10
+ service.invoke :echo_context
13
11
  end
14
12
  end
data/lib/simple/httpd.rb CHANGED
@@ -3,17 +3,6 @@
3
3
  module Simple
4
4
  end
5
5
 
6
- class Simple::Httpd
7
- end
8
-
9
- require "simple/service"
10
- require "simple/httpd/helpers"
11
- require "simple/httpd/base_controller"
12
- require "simple/httpd/version"
13
- require "simple/httpd/mount"
14
- require "simple/httpd/server"
15
- require "simple/httpd/service_adapter"
16
-
17
6
  class Simple::Httpd
18
7
  SELF = self
19
8
 
@@ -39,7 +28,18 @@ class Simple::Httpd
39
28
  def self.logger=(logger)
40
29
  @logger = logger
41
30
  end
31
+ end
42
32
 
33
+ require "simple/service"
34
+ require "simple/httpd/helpers"
35
+ require "simple/httpd/reloader"
36
+ require "simple/httpd/base_controller"
37
+ require "simple/httpd/version"
38
+ require "simple/httpd/mount"
39
+ require "simple/httpd/server"
40
+ require "simple/httpd/service_integration"
41
+
42
+ class Simple::Httpd
43
43
  # Converts the passed in args into a Simple::Httpd application.
44
44
  #
45
45
  # The passed in arguments are used to create a Simple::Httpd object.
@@ -2,18 +2,17 @@
2
2
  # config/routes.rb, **after** this file is loaded. See the end of this file.
3
3
 
4
4
  require "sinatra/base"
5
+ ::Sinatra::Request.include(::Simple::Httpd::Helpers::RequestHeader)
5
6
 
6
7
  class Simple::Httpd::BaseController < Sinatra::Base
7
8
  set :logging, true
8
9
 
9
- # --- Sinatra::Reloader -----------------------------------------------------
10
+ extend Simple::Httpd::Reloader
10
11
 
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
12
+ def dispatch!
13
+ self.class.reload! if ::Simple::Httpd.env == "development"
14
+
15
+ super
17
16
  end
18
17
  end
19
18
 
@@ -1,21 +1,22 @@
1
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
- }
2
+ # see https://fetch.spec.whatwg.org/#http-responses
3
+ # see https://stackoverflow.com/questions/24264574/cors-headers-present-only-on-preflight-or-every-request
13
4
 
14
5
  options "*" do
6
+ # The Access-Control max age setting is cached for up to 1 day. This value
7
+ # is capped at different values depending on the browser.
8
+ headers "Access-Control-Max-Age" => "86400"
9
+ headers "Access-Control-Allow-Methods" => "*"
10
+ headers "Access-Control-Allow-Headers" => "Origin,X-Requested-With,Content-Type,Accept,Session-Id"
11
+ headers "Access-Control-Expose-Headers" => "X-Total-Entries,X-Total-Pages,X-Page,X-Per-Page"
12
+
15
13
  200
16
14
  end
17
15
 
18
16
  after do
19
- headers CORS_HEADERS
17
+ # This set of CORS headers must be set on each request.
18
+ headers "Access-Control-Allow-Credentials" => "true",
19
+ "Access-Control-Allow-Origin" => origin,
20
+ "Vary" => "Accept-Encoding, Origin"
20
21
  end
21
22
  end
@@ -1,5 +1,20 @@
1
+ # rubocop:disable Metrics/ClassLength, Lint/Void
2
+ # rubocop:disable Metrics/AbcSize
3
+
1
4
  require_relative "./json"
2
5
 
6
+ # reimplement Sinatra's NotFound handler.
7
+ #
8
+ # The original renders HTML; this is not really useful for us.
9
+ Sinatra::Base
10
+ class Sinatra::Base
11
+ error ::Sinatra::NotFound do
12
+ content_type "text/plain"
13
+
14
+ "Don't know how to handle: #{request.request_method} '#{request.path_info}'"
15
+ end
16
+ end
17
+
3
18
  class Simple::Httpd::BaseController
4
19
  H = ::Simple::Httpd::Helpers
5
20
 
@@ -33,10 +48,25 @@ class Simple::Httpd::BaseController
33
48
  options["description"] ||= options["title"]
34
49
  options["@type"] = error_type(exc)
35
50
  options["@now"] = Time.now.to_f
51
+ options["@request"] = "#{request.request_method} #{request.path}"
52
+
53
+ if Simple::Httpd.env == "development" || Simple::Httpd.env == "test"
54
+ options["@headers"] = request_headers_for_debugging
55
+ options["@backtrace"] = exc.backtrace[0, 10]
56
+ end
36
57
 
37
58
  json options
38
59
  end
39
60
 
61
+ def request_headers_for_debugging
62
+ request.headers.each_with_object({}) do |(key, value), hsh|
63
+ next if /^(Host|Version|Connection|User-Agent|Accept-Encoding)$/ =~ key
64
+ next if key == "Accept" && value == "*/*"
65
+
66
+ hsh[key] = value
67
+ end
68
+ end
69
+
40
70
  if defined?(Expectation)
41
71
 
42
72
  error(Expectation::Matcher::Mismatch) do |exc|
@@ -57,8 +87,6 @@ class Simple::Httpd::BaseController
57
87
  # end
58
88
 
59
89
  error(ArgumentError) do |exc|
60
- STDERR.puts "Caught ArgumentError: #{exc}, from\n\t#{exc.backtrace[0, 5].join("\n\t")}"
61
-
62
90
  render_error exc, status: 422,
63
91
  title: "Invalid input #{exc.inspect}",
64
92
  description: error_description(exc)
@@ -75,16 +103,16 @@ class Simple::Httpd::BaseController
75
103
  class NotAuthorizedError < RuntimeError
76
104
  end
77
105
 
106
+ def not_authorized!(msg)
107
+ raise NotAuthorizedError, msg
108
+ end
109
+
78
110
  error(NotAuthorizedError) do
79
111
  render_error e, status: 403,
80
112
  title: "Not authorized",
81
113
  description: "You don't have necessary powers to access this page."
82
114
  end
83
115
 
84
- def not_authorized!(msg)
85
- raise NotAuthorizedError, msg
86
- end
87
-
88
116
  # -- login required.---------------------------------------------------------
89
117
 
90
118
  class LoginRequiredError < RuntimeError
@@ -123,7 +151,7 @@ class Simple::Httpd::BaseController
123
151
 
124
152
  # -- print unspecified errors.
125
153
 
126
- if ENV["RACK_ENV"] == "production"
154
+ if ::Simple::Httpd.env == "development"
127
155
  error do |exc|
128
156
  content_type :text
129
157
  status 500
@@ -0,0 +1,8 @@
1
+ class Simple::Httpd::BaseController
2
+ helpers do
3
+ def origin
4
+ request["Origin"] ||
5
+ "#{request.scheme}://#{request.host_with_port}"
6
+ end
7
+ end
8
+ end
@@ -1,19 +1,19 @@
1
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
2
+ helpers do
3
+ # encodes the result, according to its payload.
4
+ #
5
+ # This function is used by the service integration code, but
6
+ # is potentially useful outside.
7
+ def encode_result(result)
8
+ case result
9
+ when Array, Hash
10
+ json(result)
11
+ when String
12
+ content_type :text
13
+ result
14
+ else
15
+ result
16
+ end
17
17
  end
18
18
  end
19
19
  end
@@ -55,6 +55,7 @@ module Simple::Httpd::CLI
55
55
  port: port)
56
56
  end
57
57
 
58
+ # rubocop:disable Metrics/AbcSize
58
59
  def routes(*mounts, environment: "development", services: nil)
59
60
  prepare_environment!(environment: environment)
60
61
  app = build_app!(mounts: mounts, services: services)
@@ -65,11 +66,11 @@ module Simple::Httpd::CLI
65
66
  max_verb_len = routes.map(&:verb).map(&:length).max
66
67
  max_path_len = routes.map(&:path).map(&:length).max
67
68
 
68
- routes.
69
- sort_by { |route| [route.path, route.verb] }.
70
- each { |route|
69
+ routes
70
+ .sort_by { |route| [route.path, route.verb] }
71
+ .each do |route|
71
72
  puts format("%#{max_verb_len}s %-#{max_path_len}s %s", route.verb, route.path, route.source_location_str)
72
- }
73
+ end
73
74
  end
74
75
 
75
76
  private
@@ -113,12 +114,6 @@ module Simple::Httpd::CLI
113
114
  end
114
115
  end
115
116
 
116
- def stderr_logger
117
- logger = ::Logger.new STDERR
118
- logger.level = ::Logger::INFO
119
- logger
120
- end
121
-
122
117
  def start_simplecov
123
118
  require "simplecov"
124
119
 
@@ -1,4 +1,15 @@
1
1
  module Simple::Httpd::Helpers
2
+ module RequestHeader
3
+ def headers
4
+ env.each_with_object({}) do |(key, value), hsh|
5
+ next unless key =~ /\AHTTP_(.*)/
6
+
7
+ key = $1.split("_").collect(&:capitalize).join("-")
8
+ hsh[key] = value
9
+ end
10
+ end
11
+ end
12
+
2
13
  extend self
3
14
 
4
15
  private
@@ -16,6 +27,10 @@ module Simple::Httpd::Helpers
16
27
  def shorten_path(path)
17
28
  path = File.absolute_path(path)
18
29
 
30
+ shorten_absolute_path(path)
31
+ end
32
+
33
+ def shorten_absolute_path(path)
19
34
  if path.start_with?(pwd)
20
35
  path = path[pwd.length..-1]
21
36
  path = File.join("./", path) if path =~ /\//
@@ -52,8 +67,11 @@ module Simple::Httpd::Helpers
52
67
  raise "Missing description" unless description
53
68
 
54
69
  subclass = Class.new(klass)
70
+ subclass.define_singleton_method(:description) { description }
55
71
  subclass.define_method(:inspect) { description } if description
56
- instance_eval_paths subclass, paths: paths if paths
72
+
73
+ ::Simple::Httpd::Reloader.attach(subclass, paths: Array(paths))
74
+
57
75
  subclass
58
76
  end
59
77
 
@@ -9,13 +9,17 @@ class Simple::Httpd::Rack::DynamicMount
9
9
 
10
10
  extend Forwardable
11
11
 
12
- delegate :call => :@rack_app # rubocop:disable Style/HashSyntax
13
-
14
12
  def self.build(mount_point, path)
15
13
  expect! path => String
16
14
  new(mount_point, path)
17
15
  end
18
16
 
17
+ def call(env)
18
+ reload! if ::Simple::Httpd.env == "development"
19
+
20
+ @rack_app.call(env)
21
+ end
22
+
19
23
  attr_reader :path
20
24
  attr_reader :mount_point
21
25
 
@@ -24,7 +28,8 @@ class Simple::Httpd::Rack::DynamicMount
24
28
  @path = path.gsub(/\/\z/, "") # remove trailing "/"
25
29
 
26
30
  setup_paths!
27
- load_service_files!
31
+ ::Simple::Httpd::Reloader.attach self, paths: service_files, reloading_instance: nil
32
+
28
33
  @root_controller = build_root_controller # also loads helpers
29
34
  @url_map = build_url_map
30
35
 
@@ -47,25 +52,26 @@ class Simple::Httpd::Rack::DynamicMount
47
52
  logger.info "#{path}: found #{@source_paths.count} sources, #{@helper_paths.count} helpers"
48
53
  end
49
54
 
50
- def load_service_files!
51
- return if path == "." # i.e. mounting current directory
55
+ def service_files
56
+ @service_files ||= _service_files
57
+ end
58
+
59
+ def _service_files
60
+ return [] if path == "." # i.e. mounting current directory
52
61
 
53
62
  service_path = "#{path}.services"
54
- service_files = Dir.glob("#{service_path}/**/*.rb")
55
- return if service_files.empty?
63
+ return [] unless Dir.exist?(service_path)
56
64
 
65
+ service_files = Dir.glob("#{service_path}/**/*.rb").sort
57
66
  logger.info "#{service_path}: loading #{service_files.count} service file(s)"
58
- service_files.sort.each do |path|
59
- logger.debug "Loading service file #{path.inspect}"
60
- load path
61
- end
67
+ service_files
62
68
  end
63
69
 
64
70
  # wraps all helpers into a Simple::Httpd::BaseController subclass
65
71
  def build_root_controller
66
72
  H.subclass ::Simple::Httpd::BaseController,
67
73
  paths: @helper_paths.sort,
68
- description: "root controller at #{path} w/#{@helper_paths.count} helpers"
74
+ description: "<root controller: #{H.shorten_path path}>"
69
75
  end
70
76
 
71
77
  def build_url_map
@@ -73,7 +79,9 @@ class Simple::Httpd::Rack::DynamicMount
73
79
  relative_path = absolute_path[(path.length)..-1]
74
80
 
75
81
  relative_mount_point = relative_path == "/root.rb" ? "/" : relative_path.gsub(/\.rb$/, "")
76
- controller_class = H.subclass @root_controller, description: "controller at #{absolute_path}", paths: absolute_path
82
+ controller_class = H.subclass @root_controller,
83
+ paths: absolute_path,
84
+ description: "<controller:#{H.shorten_absolute_path(absolute_path)}>"
77
85
 
78
86
  controller_class.route_descriptions.each do |route|
79
87
  route = route.prefix(@mount_point, relative_mount_point)
@@ -0,0 +1,61 @@
1
+ module Simple::Httpd::Reloader
2
+ def self.attach(target, paths:, reloading_instance: target)
3
+ target.extend self
4
+ target.load!(paths: paths, reloading_instance: reloading_instance)
5
+ target
6
+ end
7
+
8
+ H = ::Simple::Httpd::Helpers
9
+
10
+ attr_accessor :reloading_paths
11
+
12
+ def load!(paths:, reloading_instance:)
13
+ paths = Array(paths)
14
+ paths = nil if paths.empty?
15
+
16
+ @__reload_paths__ = paths
17
+ @__reloading_instance__ = reloading_instance
18
+
19
+ reload_all_changed_files
20
+ end
21
+
22
+ def reload!
23
+ # if this is a class, and its superclass is also reloadable,
24
+ # reload the superclass first.
25
+ if respond_to?(:superclass) && superclass&.respond_to?(:reload!)
26
+ superclass.reload!
27
+ end
28
+
29
+ reload_all_changed_files
30
+ end
31
+
32
+ private
33
+
34
+ def reload_all_changed_files
35
+ return unless @__reload_paths__
36
+
37
+ @__reload_paths__.each do |path|
38
+ reload_file_if_necessary(path)
39
+ end
40
+ end
41
+
42
+ def reload_file_if_necessary(path)
43
+ @__source_mtimes_by_path__ ||= {}
44
+
45
+ mtime = File.mtime(path)
46
+ return if @__source_mtimes_by_path__[path] == mtime
47
+
48
+ Simple::Httpd.logger.debug do
49
+ verb = @__source_mtimes_by_path__.key?(path) ? "reloading" : "loading"
50
+ "#{verb} #{H.shorten_path path}"
51
+ end
52
+
53
+ if @__reloading_instance__
54
+ @__reloading_instance__.instance_eval File.read(path), path, 1
55
+ else
56
+ load path
57
+ end
58
+
59
+ @__source_mtimes_by_path__[path] = mtime
60
+ end
61
+ end
@@ -18,19 +18,29 @@ class Simple::Httpd
18
18
 
19
19
  ::Simple::Httpd.logger.info "Starting httpd server on http://#{host}:#{port}/"
20
20
 
21
+ app = ::Rack::CommonLogger.new(app)
21
22
  app = ::Rack::Lint.new(app) if environment != "production"
22
23
 
23
24
  # re/AccessLog: the AccessLog setting points WEBrick's access logging to the
24
25
  # NullLogger object.
25
26
  #
26
- # Instead we'll use a combination of Rack::CommonLogger (see Simple::Httpd.app),
27
- # and sinatra's logger (see Simple::Httpd::BaseController).
28
- ::Rack::Server.start app: app,
29
- Host: host,
30
- Port: port,
31
- environment: environment,
32
- Logger: build_logger,
33
- AccessLog: [[NullLogger, ""]]
27
+ # We do not set the environment. Rack is using this to load different
28
+ # default middlewares (ShowException, Lint, CommonLogger) depending on
29
+ # the environment setting (which should be either "development" or
30
+ # "deployment").
31
+ server_opts = {
32
+ app: app,
33
+ Host: host,
34
+ Port: port,
35
+ Logger: build_logger,
36
+ AccessLog: [[NullLogger, ""]]
37
+ }
38
+
39
+ unless ::Simple::Httpd.env == "development"
40
+ server_opts.update workers: 4, min_threads: 4
41
+ end
42
+
43
+ ::Rack::Server.start server_opts
34
44
  end
35
45
 
36
46
  private
@@ -1,19 +1,29 @@
1
1
  require "simple-service"
2
2
 
3
- module Simple::Httpd::ServiceAdapter
4
- def mount_service(service)
5
- @service = service
6
-
7
- instance_eval do
8
- def dispatch!
9
- ::Simple::Service.with_context(context)
10
- super
11
- ensure
12
- ::Simple::Service.context = nil
13
- end
3
+ module Simple::Httpd::ServiceIntegration
4
+ class Adapter
5
+ extend Forwardable
14
6
 
15
- yield(service)
7
+ def initialize(simple_service)
8
+ @simple_service = simple_service
16
9
  end
10
+
11
+ def action(action_name)
12
+ ::Simple::Service.action(@simple_service, action_name)
13
+ end
14
+
15
+ def invoke(name, args: {}, flags: {})
16
+ ::Simple::Service.invoke @simple_service, name, args: args, flags: flags
17
+ end
18
+
19
+ def invoke3(name, *args, **flags)
20
+ ::Simple::Service.invoke3 @simple_service, name, *args, **flags
21
+ end
22
+ end
23
+
24
+ def mount_service(service)
25
+ @service = Adapter.new(service)
26
+ yield(@service)
17
27
  ensure
18
28
  @service = nil
19
29
  end
@@ -52,16 +62,18 @@ module Simple::Httpd::ServiceAdapter
52
62
  def install_route(verb, path, opts, &block)
53
63
  if service_route?(verb, path, opts, &block)
54
64
  path, action_name = *path.first
55
- handle_service_route(verb, path, action_name)
65
+ install_service_shortcut(verb, path, action_name)
66
+ elsif @service
67
+ install_service_route(verb, path, opts, &block)
56
68
  else
57
- handle_non_service_route(verb, path, opts, &block)
69
+ install_non_service_route(verb, path, opts, &block)
58
70
  end
59
71
  end
60
72
 
61
- def handle_service_route(verb, path, action_name)
73
+ def install_service_shortcut(verb, path, action_name)
62
74
  # Fetch action's source_location. This also verifies that the action
63
75
  # is defined in the first place.
64
- action = ::Simple::Service.action(@service, action_name)
76
+ action = @service.action(action_name)
65
77
 
66
78
  describe_route!(verb: verb, path: path, source_location: action.source_location)
67
79
 
@@ -72,27 +84,43 @@ module Simple::Httpd::ServiceAdapter
72
84
  # define sinatra route.
73
85
  route(verb, path) do
74
86
  ::Simple::Service.with_context(context) do
75
- result = ::Simple::Service.invoke(service, action_name, args: self.parsed_body, flags: stringified_params)
87
+ result = service.invoke(action_name, args: parsed_body, flags: stringified_params)
76
88
  encode_result(result)
89
+ rescue Exception => e
90
+ Simple::Httpd.logger.warn "#{e}, from\n #{e.backtrace[0,10].join("\n ")}"
91
+ raise
77
92
  end
78
93
  end
79
94
  end
80
95
 
81
- def handle_non_service_route(verb, path, opts, &block)
96
+ def install_service_route(verb, path, opts, &block)
82
97
  describe_route!(verb: verb, path: path, source_location: block.source_location) if block
83
98
 
84
99
  route(verb, path, opts) do
85
- result = instance_eval(&block)
86
- unless headers["Content-Type"]
87
- result = encode_result(result)
100
+ ::Simple::Service.with_context(context) do
101
+ result = instance_eval(&block)
102
+ unless headers["Content-Type"]
103
+ result = encode_result(result)
104
+ end
105
+ result
106
+ rescue Exception => e
107
+ Simple::Httpd.logger.warn "#{e}, from\n #{e.backtrace[0,10].join("\n ")}"
108
+ raise
88
109
  end
89
- result
110
+ end
111
+ end
112
+
113
+ def install_non_service_route(verb, path, opts, &block)
114
+ describe_route!(verb: verb, path: path, source_location: block.source_location) if block
115
+
116
+ route(verb, path, opts) do
117
+ instance_eval(&block)
90
118
  end
91
119
  end
92
120
 
93
121
  module Helpers
94
122
  def stringified_params
95
- params.each_with_object({}) do |(k,v), hsh|
123
+ params.each_with_object({}) do |(k, v), hsh|
96
124
  hsh[k.to_s] = v
97
125
  end
98
126
  end
@@ -105,5 +133,5 @@ module Simple::Httpd::ServiceAdapter
105
133
  end
106
134
  end
107
135
 
108
- ::Simple::Httpd::BaseController.extend(::Simple::Httpd::ServiceAdapter)
109
- ::Simple::Httpd::BaseController.helpers(::Simple::Httpd::ServiceAdapter::Helpers)
136
+ ::Simple::Httpd::BaseController.extend(::Simple::Httpd::ServiceIntegration)
137
+ ::Simple::Httpd::BaseController.helpers(::Simple::Httpd::ServiceIntegration::Helpers)
data/simple-httpd.gemspec CHANGED
@@ -22,6 +22,7 @@ Gem::Specification.new do |gem|
22
22
  # dependencies
23
23
  gem.add_dependency "neatjson", "~> 0.8.4"
24
24
  gem.add_dependency "sinatra", "~> 2"
25
+ # gem.add_dependency "async_sinatra" #, "~> 2"
25
26
  # gem.add_dependency "sinatra-reloader", "~> 1"
26
27
  gem.add_dependency "expectation", "~> 1"
27
28
  gem.add_dependency "simple-cli", "~> 0.3.5"
data/spec/spec_helper.rb CHANGED
@@ -33,7 +33,9 @@ end
33
33
  Dir.glob("./spec/support/**/*.rb").sort.each { |path| load path }
34
34
 
35
35
  require "simple/httpd"
36
-
36
+ #Simple::Httpd.env = "test"
37
+ if ::Simple::Httpd.env == "development"
38
+ end
37
39
  RSpec.configure do |config|
38
40
  config.run_all_when_everything_filtered = true
39
41
  config.filter_run focus: (ENV["CI"] != "true")
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple-httpd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.3.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - radiospiel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-04 00:00:00.000000000 Z
11
+ date: 2019-12-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: neatjson
@@ -87,6 +87,7 @@ executables:
87
87
  extensions: []
88
88
  extra_rdoc_files: []
89
89
  files:
90
+ - ".envrc"
90
91
  - ".gitignore"
91
92
  - ".rubocop.yml"
92
93
  - ".tm_properties"
@@ -99,7 +100,6 @@ files:
99
100
  - bin/console
100
101
  - bin/rake
101
102
  - bin/rspec
102
- - bin/rubocop
103
103
  - bin/simple-httpd
104
104
  - examples/README.md
105
105
  - examples/ex1.services/ex1_service_module.rb
@@ -127,6 +127,7 @@ files:
127
127
  - lib/simple/httpd/base_controller/debug.rb
128
128
  - lib/simple/httpd/base_controller/error_handling.rb
129
129
  - lib/simple/httpd/base_controller/json.rb
130
+ - lib/simple/httpd/base_controller/origin.rb
130
131
  - lib/simple/httpd/base_controller/request.rb
131
132
  - lib/simple/httpd/base_controller/result.rb
132
133
  - lib/simple/httpd/base_controller/x_processing.rb
@@ -137,9 +138,10 @@ files:
137
138
  - lib/simple/httpd/rack/dynamic_mount.rb
138
139
  - lib/simple/httpd/rack/merger.rb
139
140
  - lib/simple/httpd/rack/static_mount.rb
141
+ - lib/simple/httpd/reloader.rb
140
142
  - lib/simple/httpd/route.rb
141
143
  - lib/simple/httpd/server.rb
142
- - lib/simple/httpd/service_adapter.rb
144
+ - lib/simple/httpd/service_integration.rb
143
145
  - lib/simple/httpd/version.rb
144
146
  - log/.gitkeep
145
147
  - scripts/release
@@ -179,7 +181,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
179
181
  - !ruby/object:Gem::Version
180
182
  version: '0'
181
183
  requirements: []
182
- rubygems_version: 3.0.4
184
+ rubygems_version: 3.0.6
183
185
  signing_key:
184
186
  specification_version: 4
185
187
  summary: Super-simple HTTPD server
data/bin/rubocop DELETED
@@ -1,29 +0,0 @@
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")