deas 0.42.0 → 0.43.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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