deas 0.37.0 → 0.37.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/deas/logging.rb +7 -5
- data/lib/deas/show_exceptions.rb +7 -12
- data/lib/deas/version.rb +1 -1
- data/test/support/fake_sinatra_call.rb +5 -1
- data/test/support/routes.rb +1 -1
- data/test/unit/logging_tests.rb +259 -11
- data/test/unit/show_exceptions_tests.rb +49 -16
- metadata +5 -5
data/lib/deas/logging.rb
CHANGED
@@ -41,7 +41,7 @@ module Deas
|
|
41
41
|
log_error(env['sinatra.error'])
|
42
42
|
env['deas.time_taken'] = RoundedTime.new(benchmark.real)
|
43
43
|
|
44
|
-
[
|
44
|
+
[status, headers, body]
|
45
45
|
end
|
46
46
|
|
47
47
|
def log(message)
|
@@ -81,11 +81,11 @@ module Deas
|
|
81
81
|
status, headers, body = super(env)
|
82
82
|
log " Redir: #{headers['Location']}" if headers.key?('Location')
|
83
83
|
log "===== Completed in #{env['deas.time_taken']}ms (#{response_display(status)}) ====="
|
84
|
-
[
|
84
|
+
[status, headers, body]
|
85
85
|
end
|
86
86
|
|
87
87
|
def response_display(status)
|
88
|
-
[
|
88
|
+
[status, RESPONSE_STATUS_NAMES[status.to_i]].compact.join(', ')
|
89
89
|
end
|
90
90
|
|
91
91
|
end
|
@@ -101,16 +101,18 @@ module Deas
|
|
101
101
|
line_attrs = {
|
102
102
|
'method' => request.request_method,
|
103
103
|
'path' => request.path,
|
104
|
-
'handler' => env['deas.handler_class'].name,
|
105
104
|
'params' => env['deas.params'],
|
106
105
|
'time' => env['deas.time_taken'],
|
107
106
|
'status' => status
|
108
107
|
}
|
108
|
+
if env['deas.handler_class']
|
109
|
+
line_attrs['handler'] = env['deas.handler_class'].name
|
110
|
+
end
|
109
111
|
if headers.key?('Location')
|
110
112
|
line_attrs['redir'] = headers['Location']
|
111
113
|
end
|
112
114
|
log SummaryLine.new(line_attrs)
|
113
|
-
[
|
115
|
+
[status, headers, body]
|
114
116
|
end
|
115
117
|
|
116
118
|
end
|
data/lib/deas/show_exceptions.rb
CHANGED
@@ -27,24 +27,19 @@ module Deas
|
|
27
27
|
error_body = Body.new(error)
|
28
28
|
|
29
29
|
headers['Content-Length'] = error_body.size.to_s
|
30
|
-
headers['Content-Type']
|
30
|
+
headers['Content-Type'] = error_body.mime_type.to_s
|
31
31
|
body = [error_body.content]
|
32
32
|
end
|
33
|
-
[
|
33
|
+
[status, headers, body]
|
34
34
|
end
|
35
35
|
|
36
36
|
class Body
|
37
|
-
attr_reader :content
|
38
|
-
def initialize(e)
|
39
|
-
@content ||= "#{e.class}: #{e.message}\n#{(e.backtrace || []).join("\n")}"
|
40
|
-
end
|
37
|
+
attr_reader :content, :size, :mime_type
|
41
38
|
|
42
|
-
def
|
43
|
-
@
|
44
|
-
|
45
|
-
|
46
|
-
def mime_type
|
47
|
-
@mime_type ||= "text/plain"
|
39
|
+
def initialize(e)
|
40
|
+
@content = "#{e.class}: #{e.message}\n#{e.backtrace.join("\n")}"
|
41
|
+
@size = Rack::Utils.bytesize(@content)
|
42
|
+
@mime_type = "text/plain"
|
48
43
|
end
|
49
44
|
end
|
50
45
|
|
data/lib/deas/version.rb
CHANGED
@@ -10,7 +10,7 @@ class FakeSinatraCall
|
|
10
10
|
|
11
11
|
def initialize(settings = nil)
|
12
12
|
@request = FakeRequest.new('GET','/something', {}, OpenStruct.new)
|
13
|
-
@response = FakeResponse.new
|
13
|
+
@response = FakeResponse.new(Factory.integer, {}, [Factory.text])
|
14
14
|
@session = @request.session
|
15
15
|
@params = @request.params
|
16
16
|
@logger = Deas::NullLogger.new
|
@@ -26,6 +26,10 @@ class FakeSinatraCall
|
|
26
26
|
}.merge(settings || {}))
|
27
27
|
end
|
28
28
|
|
29
|
+
def call(env)
|
30
|
+
[@response.status, @response.headers, [@response.body]]
|
31
|
+
end
|
32
|
+
|
29
33
|
def halt(*args)
|
30
34
|
throw :halt, args
|
31
35
|
end
|
data/test/support/routes.rb
CHANGED
data/test/unit/logging_tests.rb
CHANGED
@@ -5,41 +5,277 @@ module Deas::Logging
|
|
5
5
|
|
6
6
|
class UnitTests < Assert::Context
|
7
7
|
desc "Deas::Logging"
|
8
|
-
setup do
|
9
|
-
@app = Factory.sinatra_call
|
10
|
-
end
|
11
8
|
subject{ Deas::Logging }
|
12
9
|
|
13
10
|
should have_imeths :middleware
|
14
11
|
|
12
|
+
should "return a middleware class given a verbose flag" do
|
13
|
+
assert_equal Deas::VerboseLogging, subject.middleware(true)
|
14
|
+
assert_equal Deas::SummaryLogging, subject.middleware(false)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
class CallSetupTests < UnitTests
|
20
|
+
setup do
|
21
|
+
@logger = SpyLogger.new
|
22
|
+
@app = Factory.sinatra_call({
|
23
|
+
:deas_server_data => Factory.server_data(:logger => @logger)
|
24
|
+
})
|
25
|
+
|
26
|
+
@app_call_env = nil
|
27
|
+
@resp_status = Factory.integer
|
28
|
+
@resp_headers = { 'Location' => Factory.path }
|
29
|
+
@app_response = [@resp_status, @resp_headers, [Factory.text]]
|
30
|
+
Assert.stub(@app, :call) do |env|
|
31
|
+
# dup so we can see what keys were added before supering
|
32
|
+
@app_call_env = env.dup
|
33
|
+
@app_response
|
34
|
+
end
|
35
|
+
|
36
|
+
@env = {
|
37
|
+
'REQUEST_METHOD' => Factory.string(3).upcase,
|
38
|
+
'PATH_INFO' => Factory.path,
|
39
|
+
'rack.run_once' => true
|
40
|
+
}
|
41
|
+
end
|
42
|
+
subject{ @middleware_class }
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
class BaseLoggingTests < CallSetupTests
|
47
|
+
desc "Deas::BaseLogging"
|
48
|
+
setup do
|
49
|
+
@middleware_class = Deas::BaseLogging
|
50
|
+
end
|
51
|
+
|
15
52
|
end
|
16
53
|
|
17
|
-
class
|
54
|
+
class BaseLoggingInitTests < BaseLoggingTests
|
55
|
+
desc "when init"
|
56
|
+
setup do
|
57
|
+
@benchmark = Benchmark.measure{}
|
58
|
+
Assert.stub(Benchmark, :measure) do |&block|
|
59
|
+
block.call
|
60
|
+
@benchmark
|
61
|
+
end
|
62
|
+
|
63
|
+
@middleware = @middleware_class.new(@app)
|
64
|
+
end
|
65
|
+
subject{ @middleware }
|
66
|
+
|
67
|
+
should have_imeths :call, :call!
|
68
|
+
|
69
|
+
should "call the app and return its response when called" do
|
70
|
+
response = subject.call(@env)
|
71
|
+
assert_not_nil @app_call_env
|
72
|
+
assert_equal @app_response, response
|
73
|
+
end
|
74
|
+
|
75
|
+
should "set the rack.logger env key before its app is called" do
|
76
|
+
subject.call(@env)
|
77
|
+
assert_equal @logger, @env['rack.logger']
|
78
|
+
assert_same @env['rack.logger'], @app_call_env['rack.logger']
|
79
|
+
end
|
80
|
+
|
81
|
+
should "benchmark calling its app and set the deas.time_taken env key" do
|
82
|
+
assert_nil @env['deas.time_taken']
|
83
|
+
subject.call(@env)
|
84
|
+
exp = Deas::RoundedTime.new(@benchmark.real)
|
85
|
+
assert_equal exp, @env['deas.time_taken']
|
86
|
+
end
|
87
|
+
|
88
|
+
should "log a sinatra.error env key if it exists" do
|
89
|
+
@env.delete('sinatra.error')
|
90
|
+
subject.call(@env)
|
91
|
+
assert_empty @logger.info_logged
|
92
|
+
|
93
|
+
@env['sinatra.error'] = Factory.exception(Sinatra::NotFound)
|
94
|
+
subject.call(@env)
|
95
|
+
assert_empty @logger.info_logged
|
96
|
+
|
97
|
+
@env['sinatra.error'] = error = Factory.exception
|
98
|
+
subject.call(@env)
|
99
|
+
exp = "[Deas] #{error.class}: #{error.message}\n#{error.backtrace.join("\n")}"
|
100
|
+
assert_includes exp, @logger.info_logged
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
class VerboseLoggingTests < CallSetupTests
|
18
106
|
desc "Deas::VerboseLogging"
|
19
107
|
setup do
|
108
|
+
@middleware_class = Deas::VerboseLogging
|
109
|
+
end
|
110
|
+
|
111
|
+
should "be a base logging middleware" do
|
112
|
+
assert subject < Deas::BaseLogging
|
113
|
+
end
|
114
|
+
|
115
|
+
should "know its response status names" do
|
116
|
+
exp = {
|
117
|
+
200 => 'OK',
|
118
|
+
302 => 'FOUND',
|
119
|
+
400 => 'BAD REQUEST',
|
120
|
+
401 => 'UNAUTHORIZED',
|
121
|
+
403 => 'FORBIDDEN',
|
122
|
+
404 => 'NOT FOUND',
|
123
|
+
408 => 'TIMEOUT',
|
124
|
+
500 => 'ERROR'
|
125
|
+
}
|
126
|
+
assert_equal exp, @middleware_class::RESPONSE_STATUS_NAMES
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
class VerboseLoggingInitTests < VerboseLoggingTests
|
132
|
+
desc "when init"
|
133
|
+
setup do
|
134
|
+
@resp_status = @middleware_class::RESPONSE_STATUS_NAMES.keys.choice
|
135
|
+
@app_response[0] = @resp_status
|
136
|
+
|
20
137
|
@middleware = Deas::VerboseLogging.new(@app)
|
21
138
|
end
|
22
139
|
subject{ @middleware }
|
23
140
|
|
24
|
-
should have_imeths :call
|
141
|
+
should have_imeths :call!
|
142
|
+
|
143
|
+
should "call the app and return its response when called" do
|
144
|
+
response = subject.call(@env)
|
145
|
+
assert_not_nil @app_call_env
|
146
|
+
assert_equal @app_response, response
|
147
|
+
end
|
148
|
+
|
149
|
+
should "set the deas.logging env key before calling its app" do
|
150
|
+
assert_nil @env['deas.logging']
|
151
|
+
subject.call(@env)
|
152
|
+
assert_instance_of Proc, @env['deas.logging']
|
153
|
+
|
154
|
+
message = Factory.text
|
155
|
+
@env['deas.logging'].call(message)
|
156
|
+
assert_includes "[Deas] #{message}", @logger.info_logged
|
157
|
+
|
158
|
+
assert_same @env['deas.logging'], @app_call_env['deas.logging']
|
159
|
+
end
|
25
160
|
|
26
|
-
should "
|
27
|
-
|
161
|
+
should "log the request when called" do
|
162
|
+
assert_empty @logger.info_logged
|
163
|
+
subject.call(@env)
|
164
|
+
status = "#{@resp_status}, " \
|
165
|
+
"#{@middleware_class::RESPONSE_STATUS_NAMES[@resp_status]}"
|
166
|
+
exp = [
|
167
|
+
"[Deas] ===== Received request =====",
|
168
|
+
"[Deas] Method: #{@env['REQUEST_METHOD'].inspect}",
|
169
|
+
"[Deas] Path: #{@env['PATH_INFO'].inspect}",
|
170
|
+
"[Deas] Redir: #{@resp_headers['Location']}",
|
171
|
+
"[Deas] ===== Completed in #{@env['deas.time_taken']}ms (#{status}) ====="
|
172
|
+
]
|
173
|
+
assert_equal exp, @logger.info_logged
|
174
|
+
end
|
175
|
+
|
176
|
+
should "not log a redir line if it doesn't have a Location header" do
|
177
|
+
@resp_headers.delete('Location')
|
178
|
+
subject.call(@env)
|
179
|
+
|
180
|
+
exp = "[Deas] Redir: #{@resp_headers['Location']}"
|
181
|
+
assert_not_includes exp, @logger.info_logged
|
182
|
+
end
|
183
|
+
|
184
|
+
should "not log a status name for unknown statuses" do
|
185
|
+
@resp_status = Factory.integer
|
186
|
+
@app_response[0] = @resp_status
|
187
|
+
subject.call(@env)
|
188
|
+
|
189
|
+
exp = "[Deas] ===== Completed in #{@env['deas.time_taken']}ms (#{@resp_status}) ====="
|
190
|
+
assert_includes exp, @logger.info_logged
|
28
191
|
end
|
29
192
|
|
30
193
|
end
|
31
194
|
|
32
|
-
class SummaryLoggingTests <
|
195
|
+
class SummaryLoggingTests < CallSetupTests
|
33
196
|
desc "Deas::SummaryLogging"
|
34
197
|
setup do
|
198
|
+
@middleware_class = Deas::SummaryLogging
|
199
|
+
end
|
200
|
+
|
201
|
+
should "be a base logging middleware" do
|
202
|
+
assert subject < Deas::BaseLogging
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
|
207
|
+
class SummaryLoggingInitTests < SummaryLoggingTests
|
208
|
+
desc "when init"
|
209
|
+
setup do
|
210
|
+
@params = { Factory.string => Factory.string }
|
211
|
+
@handler_class = TestHandler
|
212
|
+
@env.merge!({
|
213
|
+
'deas.params' => @params,
|
214
|
+
'deas.handler_class' => @handler_class
|
215
|
+
})
|
216
|
+
|
35
217
|
@middleware = Deas::SummaryLogging.new(@app)
|
36
218
|
end
|
37
219
|
subject{ @middleware }
|
38
220
|
|
39
|
-
should
|
221
|
+
should "call the app and return its response when called" do
|
222
|
+
response = subject.call(@env)
|
223
|
+
assert_not_nil @app_call_env
|
224
|
+
assert_equal @app_response, response
|
225
|
+
end
|
40
226
|
|
41
|
-
should "
|
42
|
-
|
227
|
+
should "set the deas.logging env key before calling its app" do
|
228
|
+
assert_nil @env['deas.logging']
|
229
|
+
subject.call(@env)
|
230
|
+
assert_instance_of Proc, @env['deas.logging']
|
231
|
+
assert_nil @env['deas.logging'].call(Factory.text)
|
232
|
+
assert_same @env['deas.logging'], @app_call_env['deas.logging']
|
233
|
+
end
|
234
|
+
|
235
|
+
should "log the request when called" do
|
236
|
+
assert_empty @logger.info_logged
|
237
|
+
subject.call(@env)
|
238
|
+
|
239
|
+
summary_line = Deas::SummaryLine.new({
|
240
|
+
'method' => @env['REQUEST_METHOD'],
|
241
|
+
'path' => @env['PATH_INFO'],
|
242
|
+
'params' => @env['deas.params'],
|
243
|
+
'time' => @env['deas.time_taken'],
|
244
|
+
'status' => @resp_status,
|
245
|
+
'handler' => @handler_class.name,
|
246
|
+
'redir' => @resp_headers['Location']
|
247
|
+
})
|
248
|
+
assert_includes "[Deas] #{summary_line}", @logger.info_logged
|
249
|
+
end
|
250
|
+
|
251
|
+
should "not log a handler when it doesn't have a handler class" do
|
252
|
+
@env.delete('deas.handler_class')
|
253
|
+
subject.call(@env)
|
254
|
+
|
255
|
+
summary_line = Deas::SummaryLine.new({
|
256
|
+
'method' => @env['REQUEST_METHOD'],
|
257
|
+
'path' => @env['PATH_INFO'],
|
258
|
+
'params' => @env['deas.params'],
|
259
|
+
'time' => @env['deas.time_taken'],
|
260
|
+
'status' => @resp_status,
|
261
|
+
'redir' => @resp_headers['Location']
|
262
|
+
})
|
263
|
+
assert_includes "[Deas] #{summary_line}", @logger.info_logged
|
264
|
+
end
|
265
|
+
|
266
|
+
should "not log a redir if it doesn't have a Location header" do
|
267
|
+
@resp_headers.delete('Location')
|
268
|
+
subject.call(@env)
|
269
|
+
|
270
|
+
summary_line = Deas::SummaryLine.new({
|
271
|
+
'method' => @env['REQUEST_METHOD'],
|
272
|
+
'path' => @env['PATH_INFO'],
|
273
|
+
'params' => @env['deas.params'],
|
274
|
+
'time' => @env['deas.time_taken'],
|
275
|
+
'status' => @resp_status,
|
276
|
+
'handler' => @handler_class.name,
|
277
|
+
})
|
278
|
+
assert_includes "[Deas] #{summary_line}", @logger.info_logged
|
43
279
|
end
|
44
280
|
|
45
281
|
end
|
@@ -88,4 +324,16 @@ module Deas::Logging
|
|
88
324
|
|
89
325
|
end
|
90
326
|
|
327
|
+
TestHandler = Class.new
|
328
|
+
|
329
|
+
class SpyLogger
|
330
|
+
attr_reader :info_logged
|
331
|
+
|
332
|
+
def initialize
|
333
|
+
@info_logged = []
|
334
|
+
end
|
335
|
+
|
336
|
+
def info(message); @info_logged << message; end
|
337
|
+
end
|
338
|
+
|
91
339
|
end
|
@@ -8,27 +8,60 @@ class Deas::ShowExceptions
|
|
8
8
|
class UnitTests < Assert::Context
|
9
9
|
desc "Deas::ShowExceptions"
|
10
10
|
setup do
|
11
|
-
|
12
|
-
@app = proc do |env|
|
13
|
-
env['sinatra.error'] = exception
|
14
|
-
[ 404, {}, [] ]
|
15
|
-
end
|
16
|
-
@exception = exception
|
17
|
-
@show_exceptions = Deas::ShowExceptions.new(@app)
|
11
|
+
@middleware_class = Deas::ShowExceptions
|
18
12
|
end
|
19
|
-
subject{ @
|
13
|
+
subject{ @middleware_class }
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
class InitTests < UnitTests
|
18
|
+
desc "when init"
|
19
|
+
setup do
|
20
|
+
@app = Factory.sinatra_call
|
21
|
+
@env = { 'sinatra.error' => Factory.exception }
|
22
|
+
@middleware = @middleware_class.new(@app)
|
23
|
+
end
|
24
|
+
subject{ @middleware }
|
20
25
|
|
21
26
|
should have_imeths :call, :call!
|
22
27
|
|
23
|
-
should "return a
|
24
|
-
status, headers, body = subject.call(
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
+
should "return a response for the exception when called" do
|
29
|
+
status, headers, body = subject.call(@env)
|
30
|
+
error_body = Body.new(@env['sinatra.error'])
|
31
|
+
|
32
|
+
assert_equal @app.response.status, status
|
33
|
+
assert_equal error_body.size.to_s, headers['Content-Length']
|
34
|
+
assert_equal error_body.mime_type, headers['Content-Type']
|
35
|
+
assert_equal [error_body.content], body
|
36
|
+
end
|
37
|
+
|
38
|
+
should "return the apps response if there isn't an exception" do
|
39
|
+
@env.delete('sinatra.error')
|
40
|
+
status, headers, body = subject.call(@env)
|
41
|
+
|
42
|
+
assert_equal @app.response.status, status
|
43
|
+
assert_equal @app.response.headers, headers
|
44
|
+
assert_equal [@app.response.body], body
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
class BodyTests < UnitTests
|
50
|
+
desc "Body"
|
51
|
+
setup do
|
52
|
+
@exception = Factory.exception
|
53
|
+
@body = Body.new(@exception)
|
54
|
+
end
|
55
|
+
subject{ @body }
|
56
|
+
|
57
|
+
should have_readers :content, :size, :mime_type
|
28
58
|
|
29
|
-
|
30
|
-
|
31
|
-
|
59
|
+
should "know its attributes" do
|
60
|
+
exp_content = "#{@exception.class}: #{@exception.message}\n" \
|
61
|
+
"#{@exception.backtrace.join("\n")}"
|
62
|
+
assert_equal exp_content, subject.content
|
63
|
+
assert_equal Rack::Utils.bytesize(exp_content), subject.size
|
64
|
+
assert_equal "text/plain", subject.mime_type
|
32
65
|
end
|
33
66
|
|
34
67
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deas
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 137
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 37
|
9
|
-
-
|
10
|
-
version: 0.37.
|
9
|
+
- 1
|
10
|
+
version: 0.37.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Kelly Redding
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2015-
|
19
|
+
date: 2015-10-07 00:00:00 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
requirement: &id001 !ruby/object:Gem::Requirement
|
@@ -206,7 +206,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
206
206
|
requirements: []
|
207
207
|
|
208
208
|
rubyforge_project:
|
209
|
-
rubygems_version: 1.8.
|
209
|
+
rubygems_version: 1.8.25
|
210
210
|
signing_key:
|
211
211
|
specification_version: 3
|
212
212
|
summary: Handler-based web framework powered by Sinatra
|