api_hammer 0.19.0 → 0.19.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/README.md +0 -2
- data/api_hammer.gemspec +14 -14
- data/lib/api_hammer/body.rb +1 -1
- data/lib/api_hammer/content_type_attrs.rb +2 -0
- data/lib/api_hammer/version.rb +1 -1
- metadata +11 -137
- data/.simplecov +0 -1
- data/.travis.yml +0 -13
- data/Gemfile +0 -10
- data/Rakefile.rb +0 -12
- data/gemfiles/Gemfile_rack_1 +0 -13
- data/gemfiles/Gemfile_rack_2 +0 -12
- data/test/check_required_params_test.rb +0 -80
- data/test/faraday_request_logger_test.rb +0 -228
- data/test/halt_test.rb +0 -66
- data/test/helper.rb +0 -15
- data/test/public_instance_exec_test.rb +0 -43
- data/test/request_logger_test.rb +0 -136
- data/test/show_text_exceptions_test.rb +0 -29
- data/test/trailing_newline_test.rb +0 -24
- data/test/weblink_test.rb +0 -83
- data/test/ycomb_test.rb +0 -13
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 822c3220d1b6c07c850f3b0c66a5f18c6026bfd6415b059ff3c18569af48939b
|
|
4
|
+
data.tar.gz: 3ef1009398f37e4322809a381ccaa23072e3dbb2a32396012ba4f6754ec81d8d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 87b589dc7d2228051c011483ac37738f32b82d2761d6a43b72a86cad0711ce214126657fee707ff3a2ef3d1f872f58e8b664be0786cfa1df4f4791cbb0b5940b
|
|
7
|
+
data.tar.gz: 61f839239d5997277a7ea88e47b20109b6fd2bb0ee81e54520da2f784088a592f8c3d35d91108455efd1b93a331849ccda861077ce884f9c1e94ea7682b1c73c
|
data/README.md
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# ApiHammer
|
|
2
2
|
|
|
3
|
-
[](https://travis-ci.org/notEthan/api_hammer)
|
|
4
|
-
|
|
5
3
|
a collection of little tools I have used when creating APIs. these are generally too small to have their own
|
|
6
4
|
library, so have been collected here.
|
|
7
5
|
|
data/api_hammer.gemspec
CHANGED
|
@@ -13,27 +13,27 @@ Gem::Specification.new do |spec|
|
|
|
13
13
|
'is one large tool.'
|
|
14
14
|
spec.homepage = 'https://github.com/notEthan/api_hammer'
|
|
15
15
|
spec.license = 'MIT'
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
spec.files = [
|
|
17
|
+
*%w(
|
|
18
|
+
.yardopts
|
|
19
|
+
CHANGELOG.md
|
|
20
|
+
LICENSE.txt
|
|
21
|
+
README.md
|
|
22
|
+
api_hammer.gemspec
|
|
23
|
+
bin/hc
|
|
24
|
+
),
|
|
25
|
+
*Dir['lib/**/*'],
|
|
26
|
+
].reject { |f| File.lstat(f).ftype == 'directory' }
|
|
27
|
+
spec.bindir = 'bin'
|
|
28
|
+
spec.executables = ['hc']
|
|
22
29
|
spec.require_paths = ['lib']
|
|
23
30
|
|
|
24
31
|
spec.add_dependency 'rack'
|
|
25
|
-
spec.add_dependency 'faraday'
|
|
32
|
+
spec.add_dependency 'faraday', '~> 1.0'
|
|
26
33
|
spec.add_dependency 'term-ansicolor'
|
|
27
34
|
spec.add_dependency 'json'
|
|
28
35
|
spec.add_dependency 'json_pure'
|
|
29
36
|
spec.add_dependency 'addressable'
|
|
30
37
|
spec.add_dependency 'coderay'
|
|
31
38
|
spec.add_dependency 'i18n'
|
|
32
|
-
spec.add_development_dependency 'rake'
|
|
33
|
-
spec.add_development_dependency 'rack-test'
|
|
34
|
-
spec.add_development_dependency 'minitest'
|
|
35
|
-
spec.add_development_dependency 'minitest-reporters'
|
|
36
|
-
spec.add_development_dependency 'yard'
|
|
37
|
-
spec.add_development_dependency 'simplecov'
|
|
38
|
-
spec.add_development_dependency 'actionpack'
|
|
39
39
|
end
|
data/lib/api_hammer/body.rb
CHANGED
|
@@ -82,7 +82,7 @@ module ApiHammer
|
|
|
82
82
|
end
|
|
83
83
|
begin
|
|
84
84
|
JSON.generate([body])
|
|
85
|
-
rescue Encoding::UndefinedConversionError
|
|
85
|
+
rescue Encoding::UndefinedConversionError, JSON::GeneratorError
|
|
86
86
|
# if updating by content-type didn't do it, try UTF8 since JSON wants that - but only
|
|
87
87
|
# if it seems to be valid utf8.
|
|
88
88
|
# don't try utf8 if the response content-type indicated something else.
|
data/lib/api_hammer/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: api_hammer
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.19.
|
|
4
|
+
version: 0.19.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ethan
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2024-11-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rack
|
|
@@ -28,16 +28,16 @@ dependencies:
|
|
|
28
28
|
name: faraday
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
-
- - "
|
|
31
|
+
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '0'
|
|
33
|
+
version: '1.0'
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
|
-
- - "
|
|
38
|
+
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '0'
|
|
40
|
+
version: '1.0'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: term-ansicolor
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -122,104 +122,6 @@ dependencies:
|
|
|
122
122
|
- - ">="
|
|
123
123
|
- !ruby/object:Gem::Version
|
|
124
124
|
version: '0'
|
|
125
|
-
- !ruby/object:Gem::Dependency
|
|
126
|
-
name: rake
|
|
127
|
-
requirement: !ruby/object:Gem::Requirement
|
|
128
|
-
requirements:
|
|
129
|
-
- - ">="
|
|
130
|
-
- !ruby/object:Gem::Version
|
|
131
|
-
version: '0'
|
|
132
|
-
type: :development
|
|
133
|
-
prerelease: false
|
|
134
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
135
|
-
requirements:
|
|
136
|
-
- - ">="
|
|
137
|
-
- !ruby/object:Gem::Version
|
|
138
|
-
version: '0'
|
|
139
|
-
- !ruby/object:Gem::Dependency
|
|
140
|
-
name: rack-test
|
|
141
|
-
requirement: !ruby/object:Gem::Requirement
|
|
142
|
-
requirements:
|
|
143
|
-
- - ">="
|
|
144
|
-
- !ruby/object:Gem::Version
|
|
145
|
-
version: '0'
|
|
146
|
-
type: :development
|
|
147
|
-
prerelease: false
|
|
148
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
149
|
-
requirements:
|
|
150
|
-
- - ">="
|
|
151
|
-
- !ruby/object:Gem::Version
|
|
152
|
-
version: '0'
|
|
153
|
-
- !ruby/object:Gem::Dependency
|
|
154
|
-
name: minitest
|
|
155
|
-
requirement: !ruby/object:Gem::Requirement
|
|
156
|
-
requirements:
|
|
157
|
-
- - ">="
|
|
158
|
-
- !ruby/object:Gem::Version
|
|
159
|
-
version: '0'
|
|
160
|
-
type: :development
|
|
161
|
-
prerelease: false
|
|
162
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
163
|
-
requirements:
|
|
164
|
-
- - ">="
|
|
165
|
-
- !ruby/object:Gem::Version
|
|
166
|
-
version: '0'
|
|
167
|
-
- !ruby/object:Gem::Dependency
|
|
168
|
-
name: minitest-reporters
|
|
169
|
-
requirement: !ruby/object:Gem::Requirement
|
|
170
|
-
requirements:
|
|
171
|
-
- - ">="
|
|
172
|
-
- !ruby/object:Gem::Version
|
|
173
|
-
version: '0'
|
|
174
|
-
type: :development
|
|
175
|
-
prerelease: false
|
|
176
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
177
|
-
requirements:
|
|
178
|
-
- - ">="
|
|
179
|
-
- !ruby/object:Gem::Version
|
|
180
|
-
version: '0'
|
|
181
|
-
- !ruby/object:Gem::Dependency
|
|
182
|
-
name: yard
|
|
183
|
-
requirement: !ruby/object:Gem::Requirement
|
|
184
|
-
requirements:
|
|
185
|
-
- - ">="
|
|
186
|
-
- !ruby/object:Gem::Version
|
|
187
|
-
version: '0'
|
|
188
|
-
type: :development
|
|
189
|
-
prerelease: false
|
|
190
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
191
|
-
requirements:
|
|
192
|
-
- - ">="
|
|
193
|
-
- !ruby/object:Gem::Version
|
|
194
|
-
version: '0'
|
|
195
|
-
- !ruby/object:Gem::Dependency
|
|
196
|
-
name: simplecov
|
|
197
|
-
requirement: !ruby/object:Gem::Requirement
|
|
198
|
-
requirements:
|
|
199
|
-
- - ">="
|
|
200
|
-
- !ruby/object:Gem::Version
|
|
201
|
-
version: '0'
|
|
202
|
-
type: :development
|
|
203
|
-
prerelease: false
|
|
204
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
205
|
-
requirements:
|
|
206
|
-
- - ">="
|
|
207
|
-
- !ruby/object:Gem::Version
|
|
208
|
-
version: '0'
|
|
209
|
-
- !ruby/object:Gem::Dependency
|
|
210
|
-
name: actionpack
|
|
211
|
-
requirement: !ruby/object:Gem::Requirement
|
|
212
|
-
requirements:
|
|
213
|
-
- - ">="
|
|
214
|
-
- !ruby/object:Gem::Version
|
|
215
|
-
version: '0'
|
|
216
|
-
type: :development
|
|
217
|
-
prerelease: false
|
|
218
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
219
|
-
requirements:
|
|
220
|
-
- - ">="
|
|
221
|
-
- !ruby/object:Gem::Version
|
|
222
|
-
version: '0'
|
|
223
125
|
description: actually a set of small API-related tools. very much unlike a hammer
|
|
224
126
|
at all, which is one large tool.
|
|
225
127
|
email:
|
|
@@ -229,18 +131,12 @@ executables:
|
|
|
229
131
|
extensions: []
|
|
230
132
|
extra_rdoc_files: []
|
|
231
133
|
files:
|
|
232
|
-
- ".simplecov"
|
|
233
|
-
- ".travis.yml"
|
|
234
134
|
- ".yardopts"
|
|
235
135
|
- CHANGELOG.md
|
|
236
|
-
- Gemfile
|
|
237
136
|
- LICENSE.txt
|
|
238
137
|
- README.md
|
|
239
|
-
- Rakefile.rb
|
|
240
138
|
- api_hammer.gemspec
|
|
241
139
|
- bin/hc
|
|
242
|
-
- gemfiles/Gemfile_rack_1
|
|
243
|
-
- gemfiles/Gemfile_rack_2
|
|
244
140
|
- lib/api_hammer.rb
|
|
245
141
|
- lib/api_hammer/body.rb
|
|
246
142
|
- lib/api_hammer/content_type_attrs.rb
|
|
@@ -275,21 +171,11 @@ files:
|
|
|
275
171
|
- lib/logstash/filters/request_bodies_parsed.rb
|
|
276
172
|
- lib/logstash/filters/ruby_logger.rb
|
|
277
173
|
- lib/logstash/filters/sidekiq.rb
|
|
278
|
-
- test/check_required_params_test.rb
|
|
279
|
-
- test/faraday_request_logger_test.rb
|
|
280
|
-
- test/halt_test.rb
|
|
281
|
-
- test/helper.rb
|
|
282
|
-
- test/public_instance_exec_test.rb
|
|
283
|
-
- test/request_logger_test.rb
|
|
284
|
-
- test/show_text_exceptions_test.rb
|
|
285
|
-
- test/trailing_newline_test.rb
|
|
286
|
-
- test/weblink_test.rb
|
|
287
|
-
- test/ycomb_test.rb
|
|
288
174
|
homepage: https://github.com/notEthan/api_hammer
|
|
289
175
|
licenses:
|
|
290
176
|
- MIT
|
|
291
177
|
metadata: {}
|
|
292
|
-
post_install_message:
|
|
178
|
+
post_install_message:
|
|
293
179
|
rdoc_options: []
|
|
294
180
|
require_paths:
|
|
295
181
|
- lib
|
|
@@ -304,20 +190,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
304
190
|
- !ruby/object:Gem::Version
|
|
305
191
|
version: '0'
|
|
306
192
|
requirements: []
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
signing_key:
|
|
193
|
+
rubygems_version: 3.5.0.dev
|
|
194
|
+
signing_key:
|
|
310
195
|
specification_version: 4
|
|
311
196
|
summary: an API tool
|
|
312
|
-
test_files:
|
|
313
|
-
- test/check_required_params_test.rb
|
|
314
|
-
- test/faraday_request_logger_test.rb
|
|
315
|
-
- test/halt_test.rb
|
|
316
|
-
- test/helper.rb
|
|
317
|
-
- test/public_instance_exec_test.rb
|
|
318
|
-
- test/request_logger_test.rb
|
|
319
|
-
- test/show_text_exceptions_test.rb
|
|
320
|
-
- test/trailing_newline_test.rb
|
|
321
|
-
- test/weblink_test.rb
|
|
322
|
-
- test/ycomb_test.rb
|
|
323
|
-
- ".simplecov"
|
|
197
|
+
test_files: []
|
data/.simplecov
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
SimpleCov.start
|
data/.travis.yml
DELETED
data/Gemfile
DELETED
data/Rakefile.rb
DELETED
data/gemfiles/Gemfile_rack_1
DELETED
data/gemfiles/Gemfile_rack_2
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('.', File.dirname(__FILE__)))
|
|
2
|
-
require 'helper'
|
|
3
|
-
|
|
4
|
-
class FakeController
|
|
5
|
-
def self.rescue_from(*args)
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
include(ApiHammer::Rails)
|
|
9
|
-
attr_accessor :params
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
# strong parameters doesn't require its dependencies so good
|
|
13
|
-
require 'rack/test'
|
|
14
|
-
require 'active_support/core_ext/module'
|
|
15
|
-
require 'action_controller/metal/strong_parameters'
|
|
16
|
-
|
|
17
|
-
[Hash, ActionController::Parameters].each do |params_class|
|
|
18
|
-
describe "ApiHammer::Rails#check_required_params with #{params_class}" do
|
|
19
|
-
define_method(:controller_with_params) do |params|
|
|
20
|
-
FakeController.new.tap { |c| c.params = params_class.new.merge(params) }
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
describe 'a moderately complex set of checks' do
|
|
24
|
-
let(:checks) { [:id, :person => [:name, :height], :lucky_numbers => Array] }
|
|
25
|
-
|
|
26
|
-
it 'passes with a moderately complex example' do
|
|
27
|
-
c = controller_with_params(:id => '99', :person => {:name => 'hammer', :height => '3'}, :lucky_numbers => ['2'])
|
|
28
|
-
c.check_required_params(checks)
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
it 'is missing id' do
|
|
32
|
-
c = controller_with_params(:person => {:name => 'hammer', :height => '3'}, :lucky_numbers => ['2'])
|
|
33
|
-
err = assert_raises(ApiHammer::Rails::Halt) { c.check_required_params(checks) }
|
|
34
|
-
assert_equal({'error_message' => 'id is required but was not provided', 'errors' => {'id' => ['id is required but was not provided']}}, err.body)
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
it 'is missing person' do
|
|
38
|
-
c = controller_with_params(:id => '99', :lucky_numbers => ['2'])
|
|
39
|
-
err = assert_raises(ApiHammer::Rails::Halt) { c.check_required_params(checks) }
|
|
40
|
-
assert_equal({'error_message' => 'person is required but was not provided', 'errors' => {'person' => ['person is required but was not provided']}}, err.body)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
it 'is has the wrong type for person' do
|
|
44
|
-
c = controller_with_params(:id => '99', :person => ['hammer', '3'], :lucky_numbers => ['2'])
|
|
45
|
-
err = assert_raises(ApiHammer::Rails::Halt) { c.check_required_params(checks) }
|
|
46
|
-
assert_equal({'error_message' => 'person must be a Hash', 'errors' => {'person' => ['person must be a Hash']}}, err.body)
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
it 'is has the wrong type for person with hash check' do
|
|
50
|
-
c = controller_with_params(:person => [])
|
|
51
|
-
err = assert_raises(ApiHammer::Rails::Halt) { c.check_required_params(:person => {:id => Fixnum}) }
|
|
52
|
-
assert_equal({'error_message' => 'person must be a Hash', 'errors' => {'person' => ['person must be a Hash']}}, err.body)
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
it 'is missing person#name' do
|
|
56
|
-
c = controller_with_params(:id => '99', :person => {:height => '3'}, :lucky_numbers => ['2'])
|
|
57
|
-
err = assert_raises(ApiHammer::Rails::Halt) { c.check_required_params(checks) }
|
|
58
|
-
assert_equal({'error_message' => 'person#name is required but was not provided', 'errors' => {'person#name' => ['person#name is required but was not provided']}}, err.body)
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
it 'is missing lucky_numbers' do
|
|
62
|
-
c = controller_with_params(:id => '99', :person => {:name => 'hammer', :height => '3'})
|
|
63
|
-
err = assert_raises(ApiHammer::Rails::Halt) { c.check_required_params(checks) }
|
|
64
|
-
assert_equal({'error_message' => 'lucky_numbers is required but was not provided', 'errors' => {'lucky_numbers' => ['lucky_numbers is required but was not provided']}}, err.body)
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
it 'has the wrong type for lucky_numbers' do
|
|
68
|
-
c = controller_with_params(:id => '99', :person => {:name => 'hammer', :height => '3'}, :lucky_numbers => '2')
|
|
69
|
-
err = assert_raises(ApiHammer::Rails::Halt) { c.check_required_params(checks) }
|
|
70
|
-
assert_equal({'error_message' => 'lucky_numbers must be a Array', 'errors' => {'lucky_numbers' => ['lucky_numbers must be a Array']}}, err.body)
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
it 'has multiple problems' do
|
|
74
|
-
c = controller_with_params({})
|
|
75
|
-
err = assert_raises(ApiHammer::Rails::Halt) { c.check_required_params(checks) }
|
|
76
|
-
assert_equal({'error_message' => 'id is required but was not provided. person is required but was not provided. lucky_numbers is required but was not provided.', 'errors' => {'id' => ['id is required but was not provided'], 'person' => ['person is required but was not provided'], 'lucky_numbers' => ['lucky_numbers is required but was not provided']}}, err.body)
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
end
|
|
80
|
-
end
|
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
# encoding: utf-8
|
|
2
|
-
|
|
3
|
-
proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('.', File.dirname(__FILE__)))
|
|
4
|
-
require 'helper'
|
|
5
|
-
require 'logger'
|
|
6
|
-
require 'stringio'
|
|
7
|
-
|
|
8
|
-
describe ApiHammer::RequestLogger do
|
|
9
|
-
let(:logio) { StringIO.new }
|
|
10
|
-
let(:logger) { Logger.new(logio) }
|
|
11
|
-
|
|
12
|
-
it 'logs' do
|
|
13
|
-
conn = Faraday.new do |f|
|
|
14
|
-
f.use ApiHammer::Faraday::RequestLogger, logger
|
|
15
|
-
f.use Faraday::Adapter::Rack, proc { |env| [200, {}, []] }
|
|
16
|
-
end
|
|
17
|
-
conn.get '/'
|
|
18
|
-
assert_match(/200/, logio.string)
|
|
19
|
-
lines = logio.string.split("\n")
|
|
20
|
-
assert_equal(2, lines.size)
|
|
21
|
-
assert lines.last =~ /INFO -- : /
|
|
22
|
-
json_bit = $'
|
|
23
|
-
JSON.parse json_bit # should not raise
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
{200 => :intense_green, 400 => :intense_yellow, 500 => :intense_red, 300 => :white}.each do |status, color|
|
|
27
|
-
it "colors by #{status} status" do
|
|
28
|
-
conn = Faraday.new do |f|
|
|
29
|
-
f.use ApiHammer::Faraday::RequestLogger, logger
|
|
30
|
-
f.use Faraday::Adapter::Rack, proc { |env| [status, {}, []] }
|
|
31
|
-
end
|
|
32
|
-
conn.get '/'
|
|
33
|
-
assert(logio.string.include?(Term::ANSIColor.send(color, status.to_s)))
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
it 'registers by name' do
|
|
38
|
-
conn = Faraday.new do |f|
|
|
39
|
-
f.request :api_hammer_request_logger, logger
|
|
40
|
-
f.use Faraday::Adapter::Rack, proc { |env| [200, {}, []] }
|
|
41
|
-
end
|
|
42
|
-
conn.get '/'
|
|
43
|
-
assert_match(/200/, logio.string)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
describe 'response body encoding' do
|
|
47
|
-
it 'deals with encoding specified properly by the content type' do
|
|
48
|
-
app = proc do |env|
|
|
49
|
-
[200, {'Content-Type' => 'text/plain; charset=utf-8'}, ["Jalapeños".force_encoding("ASCII-8BIT")]]
|
|
50
|
-
end
|
|
51
|
-
conn = Faraday.new do |f|
|
|
52
|
-
f.request :api_hammer_request_logger, logger
|
|
53
|
-
f.use Faraday::Adapter::Rack, app
|
|
54
|
-
end
|
|
55
|
-
conn.get '/'
|
|
56
|
-
assert_match(/Jalapeños/, logio.string)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
it 'deals content type specifying no encoding' do
|
|
60
|
-
app = proc do |env|
|
|
61
|
-
[200, {'Content-Type' => 'text/plain; x=y'}, ["Jalapeños".force_encoding("ASCII-8BIT")]]
|
|
62
|
-
end
|
|
63
|
-
conn = Faraday.new do |f|
|
|
64
|
-
f.request :api_hammer_request_logger, logger
|
|
65
|
-
f.use Faraday::Adapter::Rack, app
|
|
66
|
-
end
|
|
67
|
-
conn.get '/'
|
|
68
|
-
assert_match(/Jalapeños/, logio.string)
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
it 'deals with no content type' do
|
|
72
|
-
app = proc do |env|
|
|
73
|
-
[200, {}, ["Jalapeños".force_encoding("ASCII-8BIT")]]
|
|
74
|
-
end
|
|
75
|
-
conn = Faraday.new do |f|
|
|
76
|
-
f.request :api_hammer_request_logger, logger
|
|
77
|
-
f.use Faraday::Adapter::Rack, app
|
|
78
|
-
end
|
|
79
|
-
conn.get '/'
|
|
80
|
-
assert_match(/Jalapeños/, logio.string)
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
it 'falls back to array of codepoints when encoding is improperly specified by the content type' do
|
|
84
|
-
app = proc do |env|
|
|
85
|
-
[200, {'Content-Type' => 'text/plain; charset=utf-8'}, ["xx" + [195].pack("C*")]]
|
|
86
|
-
end
|
|
87
|
-
conn = Faraday.new do |f|
|
|
88
|
-
f.request :api_hammer_request_logger, logger
|
|
89
|
-
f.use Faraday::Adapter::Rack, app
|
|
90
|
-
end
|
|
91
|
-
conn.get '/'
|
|
92
|
-
assert_match('[120,120,195]', logio.string)
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
it 'falls back to array of codepoints when encoding is not specified and not valid utf8' do
|
|
96
|
-
app = proc do |env|
|
|
97
|
-
[200, {}, ["xx" + [195].pack("C*")]]
|
|
98
|
-
end
|
|
99
|
-
conn = Faraday.new do |f|
|
|
100
|
-
f.request :api_hammer_request_logger, logger
|
|
101
|
-
f.use Faraday::Adapter::Rack, app
|
|
102
|
-
end
|
|
103
|
-
conn.get '/'
|
|
104
|
-
assert_match('[120,120,195]', logio.string)
|
|
105
|
-
end
|
|
106
|
-
end
|
|
107
|
-
describe 'logging body by content-type' do
|
|
108
|
-
{
|
|
109
|
-
'application/octet-stream' => false,
|
|
110
|
-
'image/png' => false,
|
|
111
|
-
'image/png; charset=what' => false,
|
|
112
|
-
'text/plain' => true,
|
|
113
|
-
'text/plain; charset=utf-8' => true,
|
|
114
|
-
}.each do |content_type, istext|
|
|
115
|
-
it "does #{istext ? '' : 'not'} log body for #{content_type}" do
|
|
116
|
-
app = proc do |env|
|
|
117
|
-
[200, {'Content-Type' => content_type}, ['data go here']]
|
|
118
|
-
end
|
|
119
|
-
conn = Faraday.new do |f|
|
|
120
|
-
f.request :api_hammer_request_logger, logger
|
|
121
|
-
f.use Faraday::Adapter::Rack, app
|
|
122
|
-
end
|
|
123
|
-
conn.get '/'
|
|
124
|
-
assert(logio.string.include?('data go here') == istext)
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
describe 'log_bodies' do
|
|
130
|
-
it 'does not log bodies when log_bodies is false' do
|
|
131
|
-
app = proc do |env|
|
|
132
|
-
[200, {'Content-Type' => 'text/plain'}, ['data go here']]
|
|
133
|
-
end
|
|
134
|
-
conn = Faraday.new do |f|
|
|
135
|
-
f.request :api_hammer_request_logger, logger, :log_bodies => false
|
|
136
|
-
f.use Faraday::Adapter::Rack, app
|
|
137
|
-
end
|
|
138
|
-
conn.get '/'
|
|
139
|
-
assert(!logio.string.include?('data go here'))
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
describe 'filtering' do
|
|
144
|
-
describe 'json response' do
|
|
145
|
-
it 'filters' do
|
|
146
|
-
app = proc { |env| [200, {'Content-Type' => 'application/json'}, ['{"pin": "foobar", "bar": "baz"}']] }
|
|
147
|
-
conn = Faraday.new do |f|
|
|
148
|
-
f.request :api_hammer_request_logger, logger, :filter_keys => 'pin'
|
|
149
|
-
f.use Faraday::Adapter::Rack, app
|
|
150
|
-
end
|
|
151
|
-
conn.get '/'
|
|
152
|
-
assert_includes(logio.string, %q("body":"{\"pin\": \"[FILTERED]\", \"bar\": \"baz\"}"))
|
|
153
|
-
end
|
|
154
|
-
it 'filters nested' do
|
|
155
|
-
app = proc { |env| [200, {'Content-Type' => 'application/json'}, ['{"object": {"pin": "foobar"}, "bar": "baz"}']] }
|
|
156
|
-
conn = Faraday.new do |f|
|
|
157
|
-
f.request :api_hammer_request_logger, logger, :filter_keys => 'pin'
|
|
158
|
-
f.use Faraday::Adapter::Rack, app
|
|
159
|
-
end
|
|
160
|
-
conn.get '/'
|
|
161
|
-
assert_includes(logio.string, %q("body":"{\"object\": {\"pin\": \"[FILTERED]\"}, \"bar\": \"baz\"}"))
|
|
162
|
-
end
|
|
163
|
-
it 'filters in array' do
|
|
164
|
-
app = proc { |env| [200, {'Content-Type' => 'application/json'}, ['[{"object": [{"pin": ["foobar"]}], "bar": "baz"}]']] }
|
|
165
|
-
conn = Faraday.new do |f|
|
|
166
|
-
f.request :api_hammer_request_logger, logger, :filter_keys => 'pin'
|
|
167
|
-
f.use Faraday::Adapter::Rack, app
|
|
168
|
-
end
|
|
169
|
-
conn.get '/'
|
|
170
|
-
assert_includes(logio.string, %q("body":"[{\"object\": [{\"pin\": \"[FILTERED]\"}], \"bar\": \"baz\"}]"))
|
|
171
|
-
end
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
describe 'json request' do
|
|
175
|
-
it 'filters a json request' do
|
|
176
|
-
app = proc { |env| [200, {}, []] }
|
|
177
|
-
conn = Faraday.new do |f|
|
|
178
|
-
f.request :api_hammer_request_logger, logger, :filter_keys => 'pin'
|
|
179
|
-
f.use Faraday::Adapter::Rack, app
|
|
180
|
-
end
|
|
181
|
-
conn.post '/', '[{"object": [{"pin": ["foobar"]}], "bar": "baz"}]', {'Content-Type' => 'application/json'}
|
|
182
|
-
assert_includes(logio.string, %q("body":"[{\"object\": [{\"pin\": \"[FILTERED]\"}], \"bar\": \"baz\"}]"))
|
|
183
|
-
end
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
describe 'form encoded response' do
|
|
187
|
-
it 'filters' do
|
|
188
|
-
app = proc { |env| [200, {'Content-Type' => 'application/x-www-form-urlencoded'}, ['pin=foobar&bar=baz']] }
|
|
189
|
-
conn = Faraday.new do |f|
|
|
190
|
-
f.request :api_hammer_request_logger, logger, :filter_keys => 'pin'
|
|
191
|
-
f.use Faraday::Adapter::Rack, app
|
|
192
|
-
end
|
|
193
|
-
conn.get '/'
|
|
194
|
-
assert_includes(logio.string, %q("body":"pin=[FILTERED]&bar=baz"))
|
|
195
|
-
end
|
|
196
|
-
it 'filters nested' do
|
|
197
|
-
app = proc { |env| [200, {'Content-Type' => 'application/x-www-form-urlencoded'}, ['object[pin]=foobar&bar=baz']] }
|
|
198
|
-
conn = Faraday.new do |f|
|
|
199
|
-
f.request :api_hammer_request_logger, logger, :filter_keys => 'pin'
|
|
200
|
-
f.use Faraday::Adapter::Rack, app
|
|
201
|
-
end
|
|
202
|
-
conn.get '/'
|
|
203
|
-
assert_includes(logio.string, %q("body":"object[pin]=[FILTERED]&bar=baz"))
|
|
204
|
-
end
|
|
205
|
-
it 'filters in array' do
|
|
206
|
-
app = proc { |env| [200, {'Content-Type' => 'application/x-www-form-urlencoded'}, ['object[][pin][]=foobar&bar=baz']] }
|
|
207
|
-
conn = Faraday.new do |f|
|
|
208
|
-
f.request :api_hammer_request_logger, logger, :filter_keys => 'pin'
|
|
209
|
-
f.use Faraday::Adapter::Rack, app
|
|
210
|
-
end
|
|
211
|
-
conn.get '/'
|
|
212
|
-
assert_includes(logio.string, %q("body":"object[][pin][]=[FILTERED]&bar=baz"))
|
|
213
|
-
end
|
|
214
|
-
end
|
|
215
|
-
|
|
216
|
-
describe 'form encoded request' do
|
|
217
|
-
it 'filters a json request' do
|
|
218
|
-
app = proc { |env| [200, {}, []] }
|
|
219
|
-
conn = Faraday.new do |f|
|
|
220
|
-
f.request :api_hammer_request_logger, logger, :filter_keys => 'pin'
|
|
221
|
-
f.use Faraday::Adapter::Rack, app
|
|
222
|
-
end
|
|
223
|
-
conn.post '/', 'object[pin]=foobar&bar=baz', {'Content-Type' => 'application/x-www-form-urlencoded'}
|
|
224
|
-
assert_includes(logio.string, %q(object[pin]=[FILTERED]&bar=baz))
|
|
225
|
-
end
|
|
226
|
-
end
|
|
227
|
-
end
|
|
228
|
-
end
|
data/test/halt_test.rb
DELETED
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('.', File.dirname(__FILE__)))
|
|
2
|
-
require 'helper'
|
|
3
|
-
|
|
4
|
-
class FakeController
|
|
5
|
-
def self.rescue_from(*args)
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
include(ApiHammer::Rails)
|
|
9
|
-
|
|
10
|
-
attr_reader :rendered
|
|
11
|
-
def render(opts)
|
|
12
|
-
@rendered = opts
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
describe 'ApiHammer::Rails#halt' do
|
|
17
|
-
it 'raises ApiHammer::Rails::Halt' do
|
|
18
|
-
haltex = assert_raises(ApiHammer::Rails::Halt) { FakeController.new.halt(200, {}) }
|
|
19
|
-
assert_equal({}, haltex.body)
|
|
20
|
-
assert_equal(200, haltex.render_options[:status])
|
|
21
|
-
end
|
|
22
|
-
describe 'status-specific halts' do
|
|
23
|
-
it 'halts ok' do
|
|
24
|
-
haltex = assert_raises(ApiHammer::Rails::Halt) { FakeController.new.halt_ok({}) }
|
|
25
|
-
assert_equal({}, haltex.body)
|
|
26
|
-
assert_equal(200, haltex.render_options[:status])
|
|
27
|
-
end
|
|
28
|
-
it 'halts unprocessable entity' do
|
|
29
|
-
haltex = assert_raises(ApiHammer::Rails::Halt) { FakeController.new.halt_unprocessable_entity({}) }
|
|
30
|
-
assert_equal({'errors' => {}}, haltex.body)
|
|
31
|
-
assert_equal(422, haltex.render_options[:status])
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
describe 'find_or_halt' do
|
|
36
|
-
it 'returns a record if it exists' do
|
|
37
|
-
record = Object.new
|
|
38
|
-
model = Class.new do
|
|
39
|
-
define_singleton_method(:where) { |attrs| [record] }
|
|
40
|
-
define_singleton_method(:table_name) { 'records' }
|
|
41
|
-
end
|
|
42
|
-
assert_equal record, FakeController.new.find_or_halt(model, {:id => 'anid'})
|
|
43
|
-
end
|
|
44
|
-
it 'it halts with 404 if not' do
|
|
45
|
-
model = Class.new do
|
|
46
|
-
(class << self; self; end).class_eval do
|
|
47
|
-
define_method(:where) { |attrs| [] }
|
|
48
|
-
define_method(:table_name) { 'record' }
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
haltex = assert_raises(ApiHammer::Rails::Halt) { FakeController.new.find_or_halt(model, {:id => 'anid'}) }
|
|
52
|
-
assert_equal({'error_message' => 'Unknown record! id: anid', 'errors' => {'record' => ['Unknown record! id: anid']}}, haltex.body)
|
|
53
|
-
assert_equal(404, haltex.render_options[:status])
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
describe 'ApiHammer::Rails#handle_halt' do
|
|
59
|
-
it 'renders the things from the error' do
|
|
60
|
-
controller = FakeController.new
|
|
61
|
-
haltex = (FakeController.new.halt_unprocessable_entity({}) rescue $!)
|
|
62
|
-
controller.handle_halt(haltex)
|
|
63
|
-
assert_equal(422, controller.rendered[:status])
|
|
64
|
-
assert_equal({'errors' => {}}, controller.rendered[:json])
|
|
65
|
-
end
|
|
66
|
-
end
|
data/test/helper.rb
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('../lib', File.dirname(__FILE__)))
|
|
2
|
-
|
|
3
|
-
require 'bundler'
|
|
4
|
-
Bundler.setup
|
|
5
|
-
|
|
6
|
-
require 'simplecov'
|
|
7
|
-
|
|
8
|
-
# NO EXPECTATIONS
|
|
9
|
-
ENV["MT_NO_EXPECTATIONS"] = ''
|
|
10
|
-
|
|
11
|
-
require 'minitest/autorun'
|
|
12
|
-
require 'minitest/reporters'
|
|
13
|
-
Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new
|
|
14
|
-
|
|
15
|
-
require 'api_hammer'
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('.', File.dirname(__FILE__)))
|
|
2
|
-
require 'helper'
|
|
3
|
-
|
|
4
|
-
require 'api_hammer/public_instance_exec'
|
|
5
|
-
|
|
6
|
-
class Foo
|
|
7
|
-
def public_method(arg = :public)
|
|
8
|
-
arg
|
|
9
|
-
end
|
|
10
|
-
protected
|
|
11
|
-
def protected_method(arg = :protected)
|
|
12
|
-
arg
|
|
13
|
-
end
|
|
14
|
-
private
|
|
15
|
-
def private_method(arg = :private)
|
|
16
|
-
arg
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
describe '#public_instance_exec' do
|
|
21
|
-
it 'does things' do
|
|
22
|
-
foo = Foo.new
|
|
23
|
-
assert_equal(:public_exec, foo.public_instance_exec(:public_exec) { |arg| public_method(arg) })
|
|
24
|
-
regularex = (foo.protected_method rescue $!)
|
|
25
|
-
ex = assert_raises(regularex.class) { foo.public_instance_exec(:protected_exec) { |arg| protected_method(arg) } }
|
|
26
|
-
assert_includes(regularex.message, ex.message)
|
|
27
|
-
regularex = (foo.private_method rescue $!)
|
|
28
|
-
ex = assert_raises(regularex.class) { foo.public_instance_exec(:private_exec) { |arg| private_method(arg) } }
|
|
29
|
-
assert_includes(regularex.message, ex.message)
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
describe '#public_instance_eval' do
|
|
33
|
-
it 'does things' do
|
|
34
|
-
foo = Foo.new
|
|
35
|
-
assert_equal(:public, foo.public_instance_eval { public_method })
|
|
36
|
-
regularex = (foo.protected_method rescue $!)
|
|
37
|
-
ex = assert_raises(regularex.class) { foo.public_instance_eval { protected_method } }
|
|
38
|
-
assert_includes(regularex.message, ex.message)
|
|
39
|
-
regularex = (foo.private_method rescue $!)
|
|
40
|
-
ex = assert_raises(regularex.class) { foo.public_instance_eval { private_method } }
|
|
41
|
-
assert_includes(regularex.message, ex.message)
|
|
42
|
-
end
|
|
43
|
-
end
|
data/test/request_logger_test.rb
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('.', File.dirname(__FILE__)))
|
|
3
|
-
require 'helper'
|
|
4
|
-
require 'logger'
|
|
5
|
-
require 'stringio'
|
|
6
|
-
|
|
7
|
-
describe ApiHammer::RequestLogger do
|
|
8
|
-
let(:logio) { StringIO.new }
|
|
9
|
-
let(:logger) { Logger.new(logio) }
|
|
10
|
-
|
|
11
|
-
it 'logs' do
|
|
12
|
-
app = ApiHammer::RequestLogger.new(proc { |env| [200, {}, []] }, logger)
|
|
13
|
-
app.call(Rack::MockRequest.env_for('/')).last.close
|
|
14
|
-
assert_match(/200/, logio.string)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
it 'colors by status' do
|
|
18
|
-
{200 => :intense_green, 400 => :intense_yellow, 500 => :intense_red, 300 => :white}.each do |status, color|
|
|
19
|
-
app = ApiHammer::RequestLogger.new(proc { |env| [status, {}, []] }, logger)
|
|
20
|
-
app.call(Rack::MockRequest.env_for('/')).last.close
|
|
21
|
-
assert(logio.string.include?(Term::ANSIColor.send(color, status.to_s)))
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
it 'logs id and uuid (json)' do
|
|
26
|
-
body = %Q({"uuid": "theuuid", "foo_uuid": "thefoouuid", "id": "theid", "id_for_x": "theidforx", "bar.id": "thebarid", "baz-guid": "bazzz", "bigthing": "#{' ' * 4096}"})
|
|
27
|
-
app = ApiHammer::RequestLogger.new(proc { |env| [200, {"Content-Type" => 'application/json; charset=UTF8'}, [body]] }, logger)
|
|
28
|
-
app.call(Rack::MockRequest.env_for('/')).last.close
|
|
29
|
-
assert_match(%q("body_ids":{"uuid":"theuuid","foo_uuid":"thefoouuid","id":"theid","id_for_x":"theidforx","bar.id":"thebarid","baz-guid":"bazzz"}), logio.string)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
it 'logs id and uuid (json array)' do
|
|
33
|
-
body = %Q([{"uuid": "theuuid", "foo_uuid": "thefoouuid"}, {"id": "theid", "id_for_x": "theidforx"}, {"bar.id": "thebarid", "baz-guid": "bazzz", "bigthing": "#{' ' * 4096}"}])
|
|
34
|
-
app = ApiHammer::RequestLogger.new(proc { |env| [200, {"Content-Type" => 'application/json; charset=UTF8'}, [body]] }, logger)
|
|
35
|
-
app.call(Rack::MockRequest.env_for('/')).last.close
|
|
36
|
-
assert_match(%q("body_ids":[{"uuid":"theuuid","foo_uuid":"thefoouuid"},{"id":"theid","id_for_x":"theidforx"},{"bar.id":"thebarid","baz-guid":"bazzz"}]), logio.string)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
it 'logs id and uuid (form encoded)' do
|
|
40
|
-
body = %Q(uuid=theuuid&foo_uuid=thefoouuid&id=theid&id_for_x=theidforx&bar.id=thebarid&baz-guid=bazzz&bigthing=#{' ' * 4096})
|
|
41
|
-
app = ApiHammer::RequestLogger.new(proc { |env| [200, {"Content-Type" => 'application/x-www-form-urlencoded; charset=UTF8'}, [body]] }, logger)
|
|
42
|
-
app.call(Rack::MockRequest.env_for('/')).last.close
|
|
43
|
-
assert_match(%q("body_ids":{"uuid":"theuuid","foo_uuid":"thefoouuid","id":"theid","id_for_x":"theidforx","bar.id":"thebarid","baz-guid":"bazzz"}), logio.string)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
it 'logs not-too-big request response bodies' do
|
|
47
|
-
app = ApiHammer::RequestLogger.new(proc { |env| [200, {}, ['the_response_body']] }, logger)
|
|
48
|
-
app.call(Rack::MockRequest.env_for('/', :input => 'the_request_body')).last.close
|
|
49
|
-
assert_match(/"request":\{.*"body":"the_request_body/, logio.string)
|
|
50
|
-
assert_match(/"response":\{.*"body":"the_response_body/, logio.string)
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
it 'logs request and response body on error (even if big)' do
|
|
54
|
-
app = ApiHammer::RequestLogger.new(proc { |env| [400, {}, ["the_response_body #{' ' * 4096}"]] }, logger)
|
|
55
|
-
app.call(Rack::MockRequest.env_for('/', :input => "the_request_body #{' ' * 4096}")).last.close
|
|
56
|
-
assert_match(/"request":\{.*"body":"the_request_body/, logio.string)
|
|
57
|
-
assert_match(/"response":\{.*"body":"the_response_body/, logio.string)
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
describe 'filtering' do
|
|
61
|
-
describe 'json response' do
|
|
62
|
-
it 'filters' do
|
|
63
|
-
body = %Q({"pin": "foobar"})
|
|
64
|
-
app = proc { |env| [200, {"Content-Type" => 'application/json; charset=UTF8'}, [body]] }
|
|
65
|
-
app = ApiHammer::RequestLogger.new(app, logger, :filter_keys => 'pin')
|
|
66
|
-
app.call(Rack::MockRequest.env_for('/')).last.close
|
|
67
|
-
|
|
68
|
-
assert_includes(logio.string, %q("body":"{\"pin\": \"[FILTERED]\"}"))
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
it 'filters unicode' do
|
|
72
|
-
body = %Q({"key": "Björn"})
|
|
73
|
-
app = proc { |env| [200, {"Content-Type" => 'application/json; charset=utf-8'}, [body]] }
|
|
74
|
-
app = ApiHammer::RequestLogger.new(app, logger)
|
|
75
|
-
app.call(Rack::MockRequest.env_for('/')).last.close
|
|
76
|
-
|
|
77
|
-
assert_includes(logio.string, %q("body":"{\"key\": \"Björn\"}"))
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
it 'filters nested' do
|
|
81
|
-
body = %Q({"object": {"pin": "foobar"}})
|
|
82
|
-
app = proc { |env| [200, {"Content-Type" => 'application/json; charset=UTF8'}, [body]] }
|
|
83
|
-
app = ApiHammer::RequestLogger.new(app, logger, :filter_keys => 'pin')
|
|
84
|
-
app.call(Rack::MockRequest.env_for('/')).last.close
|
|
85
|
-
|
|
86
|
-
assert_includes(logio.string, %q("body":"{\"object\": {\"pin\": \"[FILTERED]\"}}"))
|
|
87
|
-
end
|
|
88
|
-
it 'filters in array' do
|
|
89
|
-
body = %Q([{"object": [{"pin": ["foobar"]}]}])
|
|
90
|
-
app = proc { |env| [200, {"Content-Type" => 'application/json; charset=UTF8'}, [body]] }
|
|
91
|
-
app = ApiHammer::RequestLogger.new(app, logger, :filter_keys => 'pin')
|
|
92
|
-
app.call(Rack::MockRequest.env_for('/')).last.close
|
|
93
|
-
|
|
94
|
-
assert_includes(logio.string, %q("body":"[{\"object\": [{\"pin\": \"[FILTERED]\"}]}]"))
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
describe 'json request' do
|
|
99
|
-
it 'filters a json request' do
|
|
100
|
-
app = ApiHammer::RequestLogger.new(proc { |env| [200, {}, []] }, logger, :filter_keys => 'pin')
|
|
101
|
-
app.call(Rack::MockRequest.env_for('/', :input => '[{"object": [{"pin": ["foobar"]}]}]', 'CONTENT_TYPE' => 'application/json')).last.close
|
|
102
|
-
assert_includes(logio.string, %q("body":"[{\"object\": [{\"pin\": \"[FILTERED]\"}]}]"))
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
describe('form encoded response') do
|
|
107
|
-
it 'filters' do
|
|
108
|
-
app = proc { |env| [200, {"Content-Type" => 'application/x-www-form-urlencoded'}, ['pin=foobar']] }
|
|
109
|
-
app = ApiHammer::RequestLogger.new(app, logger, :filter_keys => 'pin')
|
|
110
|
-
app.call(Rack::MockRequest.env_for('/')).last.close
|
|
111
|
-
assert_includes(logio.string, %q("body":"pin=[FILTERED]"))
|
|
112
|
-
end
|
|
113
|
-
it 'filters nested' do
|
|
114
|
-
app = proc { |env| [200, {'Content-Type' => 'application/x-www-form-urlencoded'}, ['object[pin]=foobar']] }
|
|
115
|
-
app = ApiHammer::RequestLogger.new(app, logger, :filter_keys => 'pin')
|
|
116
|
-
app.call(Rack::MockRequest.env_for('/')).last.close
|
|
117
|
-
assert_includes(logio.string, %q("body":"object[pin]=[FILTERED]"))
|
|
118
|
-
end
|
|
119
|
-
it 'filters in array' do
|
|
120
|
-
app = proc { |env| [200, {'Content-Type' => 'application/x-www-form-urlencoded'}, ['object[][pin][]=foobar']] }
|
|
121
|
-
app = ApiHammer::RequestLogger.new(app, logger, :filter_keys => 'pin')
|
|
122
|
-
app.call(Rack::MockRequest.env_for('/')).last.close
|
|
123
|
-
assert_includes(logio.string, %q("body":"object[][pin][]=[FILTERED]"))
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
describe 'form encoded request' do
|
|
128
|
-
it 'filters a json request' do
|
|
129
|
-
app = proc { |env| [200, {}, []] }
|
|
130
|
-
app = ApiHammer::RequestLogger.new(app, logger, :filter_keys => 'pin')
|
|
131
|
-
app.call(Rack::MockRequest.env_for('/', :input => 'object[pin]=foobar', 'CONTENT_TYPE' => 'application/x-www-form-urlencoded')).last.close
|
|
132
|
-
assert_includes(logio.string, %q(object[pin]=[FILTERED]))
|
|
133
|
-
end
|
|
134
|
-
end
|
|
135
|
-
end
|
|
136
|
-
end
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('.', File.dirname(__FILE__)))
|
|
2
|
-
require 'helper'
|
|
3
|
-
|
|
4
|
-
describe ApiHammer::ShowTextExceptions do
|
|
5
|
-
it 'lets normal responses through untouched' do
|
|
6
|
-
orig_response = [200, {}, []]
|
|
7
|
-
app = ApiHammer::ShowTextExceptions.new(proc { |env| orig_response }, {})
|
|
8
|
-
app_response = app.call(Rack::MockRequest.env_for('/'))
|
|
9
|
-
assert_equal(orig_response, app_response)
|
|
10
|
-
end
|
|
11
|
-
it '500s' do
|
|
12
|
-
app = ApiHammer::ShowTextExceptions.new(proc { |env| raise }, :full_error => true)
|
|
13
|
-
assert_equal(500, app.call(Rack::MockRequest.env_for('/')).first)
|
|
14
|
-
end
|
|
15
|
-
it 'includes the full error' do
|
|
16
|
-
app = ApiHammer::ShowTextExceptions.new(proc { |env| raise 'foo' }, :full_error => true)
|
|
17
|
-
assert_match(/RuntimeError: foo/, app.call(Rack::MockRequest.env_for('/')).last.to_enum.to_a.join)
|
|
18
|
-
end
|
|
19
|
-
it 'does not include the full error' do
|
|
20
|
-
app = ApiHammer::ShowTextExceptions.new(proc { |env| raise }, :full_error => false)
|
|
21
|
-
assert_equal("Internal Server Error\n", app.call(Rack::MockRequest.env_for('/')).last.to_enum.to_a.join)
|
|
22
|
-
end
|
|
23
|
-
it 'logs' do
|
|
24
|
-
logio=StringIO.new
|
|
25
|
-
app = ApiHammer::ShowTextExceptions.new(proc { |env| raise 'foo' }, :logger => Logger.new(logio))
|
|
26
|
-
app.call(Rack::MockRequest.env_for('/'))
|
|
27
|
-
assert_match(/RuntimeError: foo/, logio.string)
|
|
28
|
-
end
|
|
29
|
-
end
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('.', File.dirname(__FILE__)))
|
|
2
|
-
require 'helper'
|
|
3
|
-
|
|
4
|
-
describe ApiHammer::TrailingNewline do
|
|
5
|
-
it 'adds a trailing newline when one is missing' do
|
|
6
|
-
app = ApiHammer::TrailingNewline.new(proc { |env| [200, {}, ["foo"]] })
|
|
7
|
-
assert_equal("foo\n", app.call(Rack::MockRequest.env_for('/')).last.to_enum.to_a.join)
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
it 'does not add a trailing newline when one is present' do
|
|
11
|
-
app = ApiHammer::TrailingNewline.new(proc { |env| [200, {}, ["foo\n"]] })
|
|
12
|
-
assert_equal("foo\n", app.call(Rack::MockRequest.env_for('/')).last.to_enum.to_a.join)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
it 'does not add a trailing newline when the response is blank' do
|
|
16
|
-
app = ApiHammer::TrailingNewline.new(proc { |env| [200, {}, []] })
|
|
17
|
-
assert_equal([], app.call(Rack::MockRequest.env_for('/')).last.to_enum.to_a)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
it 'updates Content-Length if present' do
|
|
21
|
-
app = ApiHammer::TrailingNewline.new(proc { |env| [200, {'Content-Length' => '3'}, ['foo']] })
|
|
22
|
-
assert_equal('4', app.call(Rack::MockRequest.env_for('/'))[1]['Content-Length'])
|
|
23
|
-
end
|
|
24
|
-
end
|
data/test/weblink_test.rb
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('.', File.dirname(__FILE__)))
|
|
2
|
-
require 'helper'
|
|
3
|
-
|
|
4
|
-
describe ApiHammer::Weblink do
|
|
5
|
-
describe '#parse_link_value' do
|
|
6
|
-
it 'parses link headers' do
|
|
7
|
-
examples = [
|
|
8
|
-
# one link with some attributes
|
|
9
|
-
[ %q(<http://example.com>; rel=foo; title=example; title*="an example"),
|
|
10
|
-
'http://example.com',
|
|
11
|
-
{'rel' => 'foo', 'title' => 'example', 'title*' => 'an example'},
|
|
12
|
-
],
|
|
13
|
-
# two links
|
|
14
|
-
[ %q(<http://example.com>; rel=foo; title=example; title*="an example", <http://example2.com>; rel=bar),
|
|
15
|
-
'http://example.com',
|
|
16
|
-
{'rel' => 'foo', 'title' => 'example', 'title*' => 'an example'},
|
|
17
|
-
'http://example2.com',
|
|
18
|
-
{'rel' => 'bar'},
|
|
19
|
-
],
|
|
20
|
-
# spaces
|
|
21
|
-
[ %q( <http://example.com> ;rel = foo ;title=example; title*="an example" ),
|
|
22
|
-
'http://example.com',
|
|
23
|
-
{'rel' => 'foo', 'title' => 'example', 'title*' => 'an example'},
|
|
24
|
-
],
|
|
25
|
-
# empty returns no links
|
|
26
|
-
[''],
|
|
27
|
-
]
|
|
28
|
-
examples.each do |example|
|
|
29
|
-
link_value = example.shift
|
|
30
|
-
links = ApiHammer::Weblink.parse_link_value(link_value)
|
|
31
|
-
assert_equal(example.size, links.size * 2)
|
|
32
|
-
example.each_slice(2).zip(links).each do |((target_uri, attributes), link)|
|
|
33
|
-
assert_equal(Addressable::URI.parse(target_uri), link.target_uri)
|
|
34
|
-
assert_equal(attributes, link.attributes)
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
it 'gives an absolute uri based on context' do
|
|
40
|
-
link = ApiHammer::Weblink.parse_link_value('</bar>; rel=foo', 'http://example.com/foo').first
|
|
41
|
-
assert_equal(Addressable::URI.parse('http://example.com/bar'), link.absolute_target_uri)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
it 'errors without context, trying to generate an absolute uri' do
|
|
45
|
-
link = ApiHammer::Weblink.parse_link_value('</bar>; rel=foo').first
|
|
46
|
-
assert_raises(ApiHammer::Weblink::NoContextError) { link.absolute_target_uri }
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
it 'returns an empty array for nil link header' do
|
|
50
|
-
assert_equal([], ApiHammer::Weblink.parse_link_value(nil))
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
it 'parse errors' do
|
|
54
|
-
examples = [
|
|
55
|
-
# missing >
|
|
56
|
-
%q(<http://example.com),
|
|
57
|
-
# missing <
|
|
58
|
-
%q(http://example.com>; rel=foo),
|
|
59
|
-
# , instead of ;
|
|
60
|
-
%q(<http://example.com>, rel=foo),
|
|
61
|
-
# non-ptoken characters (\,) unquoted
|
|
62
|
-
%q(<http://example.com>; rel=b\\ar; title=example),
|
|
63
|
-
%q(<http://example.com>; rel=b,ar; title=example),
|
|
64
|
-
]
|
|
65
|
-
examples.each do |example|
|
|
66
|
-
assert_raises(ApiHammer::Weblink::ParseError) { ApiHammer::Weblink.parse_link_value(example) }
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
describe '#to_s' do
|
|
71
|
-
it 'makes a string' do
|
|
72
|
-
link = ApiHammer::Weblink.new('http://example.com', :rel => 'foo', :title => 'example', 'title*' => 'an example')
|
|
73
|
-
assert_equal(%q(<http://example.com>; rel="foo"; title="example"; title*="an example"), link.to_s)
|
|
74
|
-
end
|
|
75
|
-
it 'parses the string to the same values' do
|
|
76
|
-
link = ApiHammer::Weblink.new('http://example.com', 'rel' => 'foo', 'title' => 'example', 'title*' => 'an example')
|
|
77
|
-
parsed_link = ApiHammer::Weblink.parse_link_value(link.to_s).first
|
|
78
|
-
assert_equal(link.target_uri, parsed_link.target_uri)
|
|
79
|
-
assert_equal(link.attributes, parsed_link.attributes)
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
data/test/ycomb_test.rb
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
proc { |p| $:.unshift(p) unless $:.any? { |lp| File.expand_path(lp) == p } }.call(File.expand_path('.', File.dirname(__FILE__)))
|
|
2
|
-
require 'helper'
|
|
3
|
-
|
|
4
|
-
require 'api_hammer/ycomb'
|
|
5
|
-
describe 'ycomb' do
|
|
6
|
-
it 'does the needful' do
|
|
7
|
-
length = ycomb do |len|
|
|
8
|
-
proc{|list| list == [] ? 0 : 1 + len.call(list[1..-1]) }
|
|
9
|
-
end
|
|
10
|
-
assert_equal(0, length.call([]))
|
|
11
|
-
assert_equal(3, length.call([:a, :b, :c]))
|
|
12
|
-
end
|
|
13
|
-
end
|