deas 0.42.0 → 0.43.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.
@@ -9,7 +9,7 @@ module Deas
9
9
 
10
10
  attr_reader :error_procs, :template_source, :logger, :router
11
11
 
12
- def initialize(args = nil)
12
+ def initialize(args)
13
13
  args ||= {}
14
14
  @error_procs = args[:error_procs] || []
15
15
  @template_source = args[:template_source]
@@ -17,6 +17,17 @@ module Deas
17
17
  @router = args[:router]
18
18
  end
19
19
 
20
+ def ==(other_server_data)
21
+ if other_server_data.kind_of?(ServerData)
22
+ self.error_procs == other_server_data.error_procs &&
23
+ self.template_source == other_server_data.template_source &&
24
+ self.logger == other_server_data.logger &&
25
+ self.router == other_server_data.router
26
+ else
27
+ super
28
+ end
29
+ end
30
+
20
31
  end
21
32
 
22
33
  end
@@ -1,12 +1,27 @@
1
1
  require 'sinatra/base'
2
2
  require 'deas/error_handler'
3
3
  require 'deas/exceptions'
4
+ require 'deas/request_data'
4
5
  require 'deas/server_data'
5
6
 
6
7
  module Deas
7
8
 
8
9
  module SinatraApp
9
10
 
11
+ DEFAULT_ERROR_RESPONSE_STATUS = 500.freeze
12
+
13
+ # these are standard error classes that we rescue, handle and don't reraise
14
+ # in the rack app, this keeps the app from shutting down unexpectedly;
15
+ # `LoadError`, `NotImplementedError` and `Timeout::Error` are common non
16
+ # `StandardError` exceptions that should be treated like a `StandardError`
17
+ # so we don't want one of these to shutdown the app
18
+ STANDARD_ERROR_CLASSES = [
19
+ StandardError,
20
+ LoadError,
21
+ NotImplementedError,
22
+ Timeout::Error
23
+ ].freeze
24
+
10
25
  def self.new(server_config)
11
26
  # This is generic server initialization stuff. Eventually do this in the
12
27
  # server's initialization logic more like Sanford does.
@@ -19,17 +34,11 @@ module Deas
19
34
  })
20
35
 
21
36
  Sinatra.new do
22
- # built-in settings
23
- set :environment, server_config.env
24
- set :root, server_config.root
25
- set :views, server_config.views_root
26
- set :public_folder, server_config.public_root
27
- set :default_encoding, server_config.default_encoding
28
- set :dump_errors, server_config.dump_errors
29
- set :method_override, server_config.method_override
30
- set :reload_templates, server_config.reload_templates
31
- set :sessions, server_config.sessions
32
- set :static, server_config.static_files
37
+ # unifying settings - these are used by Deas so extensions can have a
38
+ # common way to identify these low-level settings. Deas does not use
39
+ # them directly
40
+ set :environment, server_config.env
41
+ set :root, server_config.root
33
42
 
34
43
  # TODO: sucks to have to do this but b/c of Rack there is no better way
35
44
  # to make the server data available to middleware. We should remove this
@@ -38,32 +47,61 @@ module Deas
38
47
  # Not sure right now, just jotting down notes.
39
48
  set :deas_server_data, server_data
40
49
 
50
+ # static settings - Deas doesn't care about these anymore so just
51
+ # use some intelligent defaults
52
+ set :views, server_config.root
53
+ set :public_folder, server_config.root
54
+ set :default_encoding, 'utf-8'
55
+ set :method_override, false
56
+ set :reload_templates, false
57
+ set :static, false
58
+ set :sessions, false
59
+
60
+ # Turn this off b/c Deas won't auto provide it. We may add an extension
61
+ # gem or something??
62
+ disable :protection
63
+
41
64
  # raise_errors and show_exceptions prevent Deas error handlers from being
42
65
  # called and Deas' logging doesn't finish. They should always be false.
43
66
  set :raise_errors, false
44
67
  set :show_exceptions, false
45
68
 
46
- # turn off logging b/c Deas handles its own logging logic
69
+ # turn off logging, dump_errors b/c Deas handles its own logging logic
70
+ set :dump_errors, false
47
71
  set :logging, false
48
72
 
49
- # TODO: rework with `server_config.default_encoding` once we move off of using Sinatra
50
- # TODO: could maybe move into a deas-json mixin once off of Sinatra
51
- # Add charset to json content type responses - by default only added to these:
52
- # ["application/javascript", "application/xml", "application/xhtml+xml", /^text\//]
53
- settings.add_charset << "application/json"
54
-
55
- server_config.settings.each{ |set_args| set *set_args }
56
73
  server_config.middlewares.each{ |use_args| use *use_args }
57
74
 
58
75
  # routes
59
76
  server_config.routes.each do |route|
60
- # TODO: `self` is the sinatra_call; eventually stop sending it
61
- # (part of phasing out Sinatra)
62
- send(route.method, route.path){ route.run(server_data, self) }
77
+ send(route.method, route.path) do
78
+ begin
79
+ route.run(
80
+ server_data,
81
+ RequestData.new({
82
+ :request => request,
83
+ :response => response,
84
+ :params => params,
85
+ :route_path => route.path
86
+ })
87
+ )
88
+ rescue *STANDARD_ERROR_CLASSES => err
89
+ request.env['deas.error'] = err
90
+ response.status = DEFAULT_ERROR_RESPONSE_STATUS
91
+ ErrorHandler.run(request.env['deas.error'], {
92
+ :server_data => server_data,
93
+ :request => request,
94
+ :response => response,
95
+ :handler_class => request.env['deas.handler_class'],
96
+ :handler => request.env['deas.handler'],
97
+ :params => request.env['deas.params'],
98
+ :splat => request.env['deas.splat'],
99
+ :route_path => request.env['deas.route_path']
100
+ })
101
+ end
102
+ end
63
103
  end
64
104
 
65
- # error handling
66
-
67
105
  not_found do
68
106
  # `self` is the sinatra call in this context
69
107
  if env['sinatra.error']
@@ -76,25 +114,13 @@ module Deas
76
114
  end
77
115
  ErrorHandler.run(env['deas.error'], {
78
116
  :server_data => server_data,
79
- :request => self.request,
80
- :response => self.response,
81
- :handler_class => self.request.env['deas.handler_class'],
82
- :handler => self.request.env['deas.handler'],
83
- :params => self.request.env['deas.params'],
84
- })
85
- end
86
- end
87
- error do
88
- # `self` is the sinatra call in this context
89
- if env['sinatra.error']
90
- env['deas.error'] = env['sinatra.error']
91
- ErrorHandler.run(env['deas.error'], {
92
- :server_data => server_data,
93
- :request => self.request,
94
- :response => self.response,
95
- :handler_class => self.request.env['deas.handler_class'],
96
- :handler => self.request.env['deas.handler'],
97
- :params => self.request.env['deas.params'],
117
+ :request => request,
118
+ :response => response,
119
+ :handler_class => request.env['deas.handler_class'],
120
+ :handler => request.env['deas.handler'],
121
+ :params => request.env['deas.params'],
122
+ :splat => request.env['deas.splat'],
123
+ :route_path => request.env['deas.route_path']
98
124
  })
99
125
  end
100
126
  end
@@ -27,15 +27,16 @@ module Deas
27
27
  :router => a.delete(:router),
28
28
  :template_source => a.delete(:template_source),
29
29
  :request => a.delete(:request),
30
- :session => a.delete(:session),
31
30
  :params => NormalizedParams.new(a.delete(:params) || {}).value,
32
- :splat => a.delete(:splat)
31
+ :route_path => a.delete(:route_path)
33
32
  })
33
+ @splat = a.delete(:splat)
34
34
  a.each{|key, value| self.handler.send("#{key}=", value) }
35
35
 
36
36
  catch(:halt){ self.handler.deas_init }
37
37
  end
38
38
 
39
+ def splat; @splat; end
39
40
  def halted?; @halted; end
40
41
 
41
42
  def run
data/lib/deas/url.rb CHANGED
@@ -38,16 +38,20 @@ module Deas
38
38
  end
39
39
 
40
40
  def set_named(path, params)
41
- params.inject(path) do |path_string, (name, value)|
42
- if path_string.include?(":#{name}")
43
- if (v = value.to_s).empty?
44
- raise EmptyNamedValueError , "an empty value (`#{value.inspect}`) " \
45
- "was given for the `#{name}` url param"
41
+ # Process longer param names first. This ensures that shorter names that
42
+ # compose longer names won't be set as a part of the longer name.
43
+ params.keys.sort{ |a, b| b.to_s.size <=> a.to_s.size }.inject(path) do |p, name|
44
+ if p.include?(":#{name}")
45
+ if (v = params[name].to_s).empty?
46
+ raise EmptyNamedValueError , "an empty value, " \
47
+ "`#{params[name].inspect}`, " \
48
+ "was given for the " \
49
+ "`#{name.inspect}` url param"
46
50
  end
47
51
  params.delete(name)
48
- path_string.gsub(":#{name}", v)
52
+ p.gsub(":#{name}", v)
49
53
  else
50
- path_string
54
+ p
51
55
  end
52
56
  end
53
57
  end
data/lib/deas/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Deas
2
- VERSION = "0.42.0"
2
+ VERSION = "0.43.0"
3
3
  end
@@ -65,7 +65,6 @@ module Deas
65
65
 
66
66
  # request
67
67
  def request; @deas_runner.request; end
68
- def session; @deas_runner.session; end
69
68
  def params; @deas_runner.params; end
70
69
  def splat; @deas_runner.splat; end
71
70
 
@@ -131,7 +130,6 @@ module Deas
131
130
  def test_runner(handler_class, args = nil)
132
131
  args ||= {}
133
132
  args[:request] ||= Rack::Request.new({})
134
- args[:session] ||= args[:request].session
135
133
  TestRunner.new(handler_class, args)
136
134
  end
137
135
 
@@ -1,9 +1,11 @@
1
1
  require 'assert/factory'
2
2
  require 'deas/logger'
3
+ require 'deas/request_data'
3
4
  require 'deas/router'
4
5
  require 'deas/server_data'
5
6
  require 'deas/template_source'
6
7
  require 'test/support/fake_request'
8
+ require 'test/support/fake_response'
7
9
  require 'test/support/fake_sinatra_call'
8
10
 
9
11
  module Factory
@@ -30,6 +32,20 @@ module Factory
30
32
  FakeRequest.new(args)
31
33
  end
32
34
 
35
+ def self.response(args = nil)
36
+ FakeResponse.new(args)
37
+ end
38
+
39
+ def self.request_data(args = nil)
40
+ args ||= {}
41
+ Deas::RequestData.new({
42
+ :request => args[:request] || Factory.request,
43
+ :response => args[:response] || Factory.response,
44
+ :params => args[:params] || { Factory.string => Factory.string },
45
+ :route_path => args[:route_path] || Factory.string
46
+ })
47
+ end
48
+
33
49
  def self.sinatra_call(settings = nil)
34
50
  FakeSinatraCall.new(settings)
35
51
  end
@@ -1,6 +1,7 @@
1
1
  require 'ostruct'
2
2
 
3
3
  class FakeRequest < Struct.new(:http_method, :path, :params, :session, :env)
4
+
4
5
  alias :request_method :http_method
5
6
 
6
7
  attr_reader :logging_msgs
@@ -0,0 +1,12 @@
1
+ class FakeResponse < Struct.new(:status, :headers, :body)
2
+
3
+ def initialize(args = nil)
4
+ args ||= {}
5
+ super(*[
6
+ args[:status] || Factory.integer,
7
+ args[:headers] || Rack::Utils::HeaderHash.new,
8
+ args[:body] || [Factory.text]
9
+ ])
10
+ end
11
+
12
+ end
@@ -1,4 +1,5 @@
1
1
  require 'test/support/fake_request'
2
+ require 'test/support/fake_response'
2
3
 
3
4
  class FakeSinatraCall
4
5
 
@@ -68,14 +69,3 @@ class FakeSinatraCall
68
69
  SendFileArgs = Struct.new(:file_path, :options, :block_call_result)
69
70
 
70
71
  end
71
-
72
- class FakeResponse < Struct.new(:status, :headers, :body)
73
- def initialize(args = nil)
74
- args ||= {}
75
- super(*[
76
- args[:status] || Factory.integer,
77
- args[:headers] || {},
78
- args[:body] || [Factory.text]
79
- ])
80
- end
81
- end
@@ -8,13 +8,11 @@ class DeasTestServer
8
8
  logger TEST_LOGGER
9
9
  verbose_logging Factory.boolean
10
10
 
11
- set :a_setting, 'something'
12
-
13
11
  error do |exception, context|
14
12
  case exception
15
13
  when Deas::NotFound
16
14
  [404, "Couldn't be found"]
17
- when Exception
15
+ when *Deas::SinatraApp::STANDARD_ERROR_CLASSES
18
16
  [500, "Oops, something went wrong"]
19
17
  end
20
18
  end
@@ -46,6 +44,10 @@ class DeasTestServer
46
44
  redirect('/:prefix/redirect'){ "/#{params['prefix']}/somewhere" }
47
45
  end
48
46
 
47
+ use Rack::Session::Cookie, :key => 'my.session',
48
+ :expire_after => Factory.integer,
49
+ :secret => Factory.string
50
+
49
51
  end
50
52
 
51
53
  class DeasDevServer
@@ -153,7 +155,7 @@ class ErrorHandler
153
155
  include Deas::ViewHandler
154
156
 
155
157
  def run!
156
- raise 'test'
158
+ raise Deas::SinatraApp::STANDARD_ERROR_CLASSES.sample, 'sinatra app standard error'
157
159
  end
158
160
 
159
161
  end
@@ -171,7 +173,7 @@ class SetSessionHandler
171
173
  include Deas::ViewHandler
172
174
 
173
175
  def run!
174
- session[:secret] = 'session_secret'
176
+ request.session[:secret] = 'session_secret'
175
177
  redirect '/session'
176
178
  end
177
179
 
@@ -181,7 +183,7 @@ class UseSessionHandler
181
183
  include Deas::ViewHandler
182
184
 
183
185
  def run!
184
- body session[:secret]
186
+ body request.session[:secret]
185
187
  end
186
188
 
187
189
  end
@@ -194,7 +196,6 @@ class HandlerTestsHandler
194
196
  set_data('logger_class_name'){ logger.class.name }
195
197
  set_data('request_method'){ request.request_method.to_s }
196
198
  set_data('params_a_param'){ params['a-param'] }
197
- set_data('session_inspect'){ session.inspect }
198
199
  end
199
200
 
200
201
  def set_data(a, &block)
@@ -111,14 +111,7 @@ module Deas
111
111
  end
112
112
 
113
113
  class SessionTests < RackTests
114
- desc "with sessions enabled"
115
- setup do
116
- @orig_sessions = @app.settings.sessions
117
- @app.set :sessions, true
118
- end
119
- teardown do
120
- @app.set :sessions, @orig_sessions
121
- end
114
+ desc "using sessions"
122
115
 
123
116
  should "return a 200 response and the session value" do
124
117
  post '/session'
@@ -141,8 +134,7 @@ module Deas
141
134
  exp = {
142
135
  'logger_class_name' => 'Logger',
143
136
  'request_method' => 'GET',
144
- 'params_a_param' => 'something',
145
- 'session_inspect' => '{}'
137
+ 'params_a_param' => 'something'
146
138
  }
147
139
  assert_equal exp.inspect, @data_inspect
148
140
  end
@@ -168,7 +160,7 @@ module Deas
168
160
 
169
161
  assert_equal 500, last_response.status
170
162
  assert_equal "text/plain", last_response.headers['Content-Type']
171
- assert_match "RuntimeError: test", last_response.body
163
+ assert_match "sinatra app standard error", last_response.body
172
164
  end
173
165
 
174
166
  end
@@ -12,9 +12,11 @@ class Deas::ErrorHandler
12
12
  @server_data = Factory.server_data(:error_procs => @error_proc_spies)
13
13
  @request = Factory.string
14
14
  @response = Factory.string
15
- @handler_class = Factory.string
15
+ @handler_class = Deas::ErrorHandler
16
16
  @handler = Factory.string
17
17
  @params = Factory.string
18
+ @splat = Factory.string
19
+ @route_path = Factory.string
18
20
 
19
21
  @context_hash = {
20
22
  :server_data => @server_data,
@@ -23,9 +25,9 @@ class Deas::ErrorHandler
23
25
  :handler_class => @handler_class,
24
26
  :handler => @handler,
25
27
  :params => @params,
28
+ :splat => @splat,
29
+ :route_path => @route_path
26
30
  }
27
-
28
- @handler_class = Deas::ErrorHandler
29
31
  end
30
32
  subject{ @handler_class }
31
33
 
@@ -113,7 +115,8 @@ class Deas::ErrorHandler
113
115
  subject{ @context }
114
116
 
115
117
  should have_readers :server_data
116
- should have_readers :request, :response, :handler_class, :handler, :params
118
+ should have_readers :request, :response, :handler_class, :handler
119
+ should have_readers :params, :splat, :route_path
117
120
 
118
121
  should "know its attributes" do
119
122
  assert_equal @context_hash[:server_data], subject.server_data
@@ -122,13 +125,24 @@ class Deas::ErrorHandler
122
125
  assert_equal @context_hash[:handler_class], subject.handler_class
123
126
  assert_equal @context_hash[:handler], subject.handler
124
127
  assert_equal @context_hash[:params], subject.params
128
+ assert_equal @context_hash[:splat], subject.splat
129
+ assert_equal @context_hash[:route_path], subject.route_path
125
130
  end
126
131
 
127
132
  should "know if it equals another context" do
128
133
  exp = Context.new(@context_hash)
129
134
  assert_equal exp, subject
130
135
 
131
- exp = Context.new({})
136
+ exp = Context.new({
137
+ :server_data => Factory.server_data,
138
+ :request => Factory.string,
139
+ :response => Factory.string,
140
+ :handler_class => Factory.string,
141
+ :handler => Factory.string,
142
+ :params => Factory.string,
143
+ :splat => Factory.string,
144
+ :route_path => Factory.string
145
+ })
132
146
  assert_not_equal exp, subject
133
147
  end
134
148