drillbit 2.11.0 → 3.0.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.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/lib/drillbit.rb +1 -0
  5. data/lib/drillbit/accept_header.rb +1 -0
  6. data/lib/drillbit/authorizable_resource.rb +61 -60
  7. data/lib/drillbit/authorizers/parameters.rb +1 -0
  8. data/lib/drillbit/authorizers/parameters/filtering.rb +7 -6
  9. data/lib/drillbit/authorizers/parameters/inclusions.rb +6 -9
  10. data/lib/drillbit/authorizers/parameters/resource.rb +20 -19
  11. data/lib/drillbit/authorizers/query.rb +1 -0
  12. data/lib/drillbit/authorizers/scope.rb +5 -4
  13. data/lib/drillbit/compatibility/controllers.rb +1 -0
  14. data/lib/drillbit/configuration.rb +14 -16
  15. data/lib/drillbit/errors/invalid_api_request.rb +1 -0
  16. data/lib/drillbit/errors/invalid_request_body.rb +1 -0
  17. data/lib/drillbit/errors/invalid_subdomain.rb +1 -0
  18. data/lib/drillbit/errors/invalid_token.rb +1 -0
  19. data/lib/drillbit/errors/unpermitted_inclusions.rb +1 -0
  20. data/lib/drillbit/matchers/accept_header.rb +1 -0
  21. data/lib/drillbit/matchers/generic.rb +4 -3
  22. data/lib/drillbit/matchers/subdomain.rb +5 -6
  23. data/lib/drillbit/matchers/version.rb +3 -2
  24. data/lib/drillbit/middleware/api_request_validator.rb +4 -3
  25. data/lib/drillbit/middleware/parameter_parser.rb +1 -0
  26. data/lib/drillbit/middleware/token_processor.rb +1 -0
  27. data/lib/drillbit/parameters/filter.rb +12 -11
  28. data/lib/drillbit/parameters/index.rb +3 -2
  29. data/lib/drillbit/parameters/page.rb +1 -0
  30. data/lib/drillbit/parameters/sort.rb +1 -0
  31. data/lib/drillbit/requests/base.rb +1 -1
  32. data/lib/drillbit/requests/rack.rb +3 -0
  33. data/lib/drillbit/requests/rails.rb +1 -0
  34. data/lib/drillbit/resource.rb +1 -0
  35. data/lib/drillbit/resource/model.rb +5 -4
  36. data/lib/drillbit/resource/naming.rb +11 -10
  37. data/lib/drillbit/resource/processors/filtering.rb +1 -0
  38. data/lib/drillbit/resource/processors/indexing.rb +1 -0
  39. data/lib/drillbit/resource/processors/paging.rb +4 -3
  40. data/lib/drillbit/resource/processors/sorting.rb +1 -0
  41. data/lib/drillbit/responses/invalid_api_request.rb +3 -0
  42. data/lib/drillbit/responses/invalid_request_body.rb +3 -0
  43. data/lib/drillbit/responses/invalid_subdomain.rb +3 -0
  44. data/lib/drillbit/responses/invalid_token.rb +3 -0
  45. data/lib/drillbit/serializers/json_api.rb +12 -11
  46. data/lib/drillbit/tokens/base64.rb +1 -0
  47. data/lib/drillbit/tokens/base64s/invalid.rb +1 -0
  48. data/lib/drillbit/tokens/base64s/null.rb +1 -0
  49. data/lib/drillbit/tokens/invalid.rb +1 -0
  50. data/lib/drillbit/tokens/json_web_token.rb +6 -5
  51. data/lib/drillbit/tokens/json_web_tokens/invalid.rb +1 -0
  52. data/lib/drillbit/tokens/json_web_tokens/null.rb +1 -0
  53. data/lib/drillbit/tokens/json_web_tokens/password_reset.rb +1 -0
  54. data/lib/drillbit/tokens/null.rb +1 -0
  55. data/lib/drillbit/utilities/string.rb +1 -0
  56. data/lib/drillbit/version.rb +2 -1
  57. metadata +28 -94
  58. metadata.gz.sig +0 -0
  59. data/Rakefile +0 -2
  60. data/spec/drillbit/accept_header_spec.rb +0 -119
  61. data/spec/drillbit/authorizers/parameters/filtering_spec.rb +0 -101
  62. data/spec/drillbit/authorizers/parameters/resource_spec.rb +0 -12
  63. data/spec/drillbit/authorizers/parameters_spec.rb +0 -19
  64. data/spec/drillbit/authorizers/query_spec.rb +0 -24
  65. data/spec/drillbit/authorizers/scope_spec.rb +0 -21
  66. data/spec/drillbit/errors/invalid_api_request_spec.rb +0 -31
  67. data/spec/drillbit/errors/invalid_request_body_spec.rb +0 -25
  68. data/spec/drillbit/errors/invalid_subdomain_spec.rb +0 -30
  69. data/spec/drillbit/errors/invalid_token_spec.rb +0 -24
  70. data/spec/drillbit/invalid_subdomain_spec.rb +0 -45
  71. data/spec/drillbit/invalid_token_spec.rb +0 -44
  72. data/spec/drillbit/matchers/accept_header_spec.rb +0 -114
  73. data/spec/drillbit/matchers/subdomain_spec.rb +0 -78
  74. data/spec/drillbit/matchers/version_spec.rb +0 -86
  75. data/spec/drillbit/middleware/api_request_validator_spec.rb +0 -185
  76. data/spec/drillbit/middleware/parameter_parser_spec.rb +0 -200
  77. data/spec/drillbit/middleware/token_processor_spec.rb +0 -27
  78. data/spec/drillbit/requests/base_spec.rb +0 -37
  79. data/spec/drillbit/requests/rack_spec.rb +0 -252
  80. data/spec/drillbit/requests/rails_spec.rb +0 -264
  81. data/spec/drillbit/resource/model_spec.rb +0 -64
  82. data/spec/drillbit/resource/processors/filtering_spec.rb +0 -106
  83. data/spec/drillbit/resource/processors/indexing_spec.rb +0 -45
  84. data/spec/drillbit/resource/processors/paging_spec.rb +0 -74
  85. data/spec/drillbit/resource/processors/sorting_spec.rb +0 -66
  86. data/spec/drillbit/tokens/base64_spec.rb +0 -44
  87. data/spec/drillbit/tokens/json_web_token_spec.rb +0 -231
  88. data/spec/drillbit/tokens/json_web_tokens/password_reset_spec.rb +0 -43
  89. data/spec/fixtures/test_rsa_key +0 -27
  90. data/spec/fixtures/test_rsa_key.pub +0 -9
  91. data/spec/spec_helper.rb +0 -4
  92. data/spec/support/private_keys.rb +0 -42
@@ -1,78 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'rspeckled/spec_helpers/rspeckled'
3
- require 'drillbit/requests/base'
4
- require 'drillbit/matchers/subdomain'
5
- require 'drillbit/configuration'
6
-
7
- module Drillbit
8
- module Matchers
9
- describe Subdomain do
10
- before(:each) do
11
- Drillbit.configuration.allowed_subdomains = %w{api}
12
- Drillbit.configuration.allowed_api_subdomains = %w{api}
13
- end
14
-
15
- it 'matches if the subdomain is API' do
16
- env = { 'HTTP_HOST' => 'api.example.com' }
17
- request = Requests::Base.resolve(env)
18
- matcher = Subdomain.new
19
-
20
- expect(matcher.matches?(request)).to be_a TrueClass
21
- end
22
-
23
- it 'matches if the first subdomain is API' do
24
- env = { 'HTTP_HOST' => 'api.westeros.example.com' }
25
- request = Requests::Base.resolve(env)
26
- matcher = Subdomain.new
27
-
28
- expect(matcher.matches?(request)).to be_a TrueClass
29
- end
30
-
31
- it 'does not match if the first subdomain is not API' do
32
- env = { 'HTTP_HOST' => 'westeros.example.com' }
33
- request = Requests::Base.resolve(env)
34
- matcher = Subdomain.new
35
-
36
- expect(matcher.matches?(request)).to be_a FalseClass
37
- end
38
-
39
- it 'allows the matched subdomain to be specified' do
40
- env = { 'HTTP_HOST' => 'westeros.example.com' }
41
- request = Requests::Base.resolve(env)
42
- matcher = Subdomain.new(allowed_subdomains: 'westeros')
43
-
44
- expect(matcher.matches?(request)).to be_a TrueClass
45
- end
46
-
47
- it 'allows more than one subdomain to be matched' do
48
- env = { 'HTTP_HOST' => 'westeros.example.com' }
49
- request = Requests::Base.resolve(env)
50
- matcher = Subdomain.new(allowed_subdomains: %w{api westeros})
51
-
52
- expect(matcher.matches?(request)).to be_a TrueClass
53
-
54
- env = { 'HTTP_HOST' => 'api.example.com' }
55
- request = Requests::Base.resolve(env)
56
- matcher = Subdomain.new(allowed_subdomains: %w{api westeros})
57
-
58
- expect(matcher.matches?(request)).to be_a TrueClass
59
- end
60
-
61
- it 'can match only the api subdomain' do
62
- env = { 'HTTP_HOST' => 'westeros.example.com' }
63
- request = Requests::Base.resolve(env)
64
- matcher = Subdomain.new(allowed_api_subdomains: %w{westeros})
65
-
66
- expect(matcher.matches_api_subdomain?(request)).to be_a TrueClass
67
- end
68
-
69
- it 'matches "api" as an api subdomain by default' do
70
- env = { 'HTTP_HOST' => 'api.example.com' }
71
- request = Requests::Base.resolve(env)
72
- matcher = Subdomain.new
73
-
74
- expect(matcher.matches_api_subdomain?(request)).to be_a TrueClass
75
- end
76
- end
77
- end
78
- end
@@ -1,86 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'rspeckled/spec_helpers/rspeckled'
3
- require 'drillbit/requests/base'
4
- require 'drillbit/matchers/version'
5
-
6
- module Drillbit
7
- module Matchers
8
- describe Version do
9
- context 'when the version is passed in the accept header' do
10
- it 'does not match if the subdomain is API but the requested version does not ' \
11
- 'equal the version constraint' do
12
-
13
- env = {
14
- 'HTTP_X_APPLICATION_NAME' => 'westeros',
15
- 'HTTP_ACCEPT' => 'application/vnd.westeros+redkeep;version=10.0',
16
- }
17
- request = Requests::Base.resolve(env)
18
-
19
- matcher = Version.new(version_constraint: '10.1')
20
-
21
- expect(matcher.matches?(request)).to be_a FalseClass
22
- end
23
-
24
- it 'does match if the subdomain is API and the requested version equals the ' \
25
- 'version constraint' do
26
-
27
- env = {
28
- 'HTTP_X_APPLICATION_NAME' => 'westeros',
29
- 'HTTP_ACCEPT' => 'application/vnd.westeros+redkeep;version=10.0',
30
- }
31
- request = Requests::Base.resolve(env)
32
-
33
- matcher = Version.new(version_constraint: '10.0')
34
-
35
- expect(matcher.matches?(request)).to be_a TrueClass
36
- end
37
- end
38
-
39
- context 'when the version is not passed in the accept header' do
40
- it 'does not match if the subdomain is API but the requested version does not ' \
41
- 'equal the version constraint' do
42
-
43
- env = {
44
- 'HTTP_X_APPLICATION_NAME' => 'westeros',
45
- 'HTTP_ACCEPT' => 'application/vnd.westeros+redkeep',
46
- }
47
- request = Requests::Base.resolve(env)
48
-
49
- matcher = Version.new(version_constraint: '10.1',
50
- default_version: '10.0')
51
-
52
- expect(matcher.matches?(request)).to be_a FalseClass
53
- end
54
-
55
- it 'does match if the subdomain is API and the requested version equals the ' \
56
- 'version constraint' do
57
-
58
- env = {
59
- 'HTTP_X_APPLICATION_NAME' => 'westeros',
60
- 'HTTP_ACCEPT' => 'application/vnd.westeros+redkeep',
61
- }
62
- request = Requests::Base.resolve(env)
63
-
64
- matcher = Version.new(version_constraint: '10.0',
65
- default_version: '10.0')
66
-
67
- expect(matcher.matches?(request)).to be_a TrueClass
68
- end
69
- end
70
-
71
- it 'matches the default version in the configuration if none is passed in' do
72
- Drillbit.configuration.default_api_version = '100.0'
73
-
74
- env = {
75
- 'HTTP_X_APPLICATION_NAME' => 'westeros',
76
- 'HTTP_ACCEPT' => 'application/vnd.westeros+redkeep',
77
- }
78
- request = Requests::Base.resolve(env)
79
-
80
- matcher = Version.new(version_constraint: '100.0')
81
-
82
- expect(matcher.matches?(request)).to be_a TrueClass
83
- end
84
- end
85
- end
86
- end
@@ -1,185 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'rspeckled/spec_helpers/rspeckled'
3
- require 'drillbit/middleware/api_request_validator'
4
-
5
- # rubocop:disable Metrics/LineLength
6
- module Drillbit
7
- module Middleware
8
- describe ApiRequestValidator, singletons: Erratum::Configuration do
9
- let(:app) { ->(_env) { [200, {}, 'response'] } }
10
-
11
- before(:each) do
12
- Erratum.configuration.url_mappings = {
13
- 'external_documentation_urls' => {
14
- 'errors.responses.invalid_subdomain' => 'http://example.com/foo',
15
- },
16
- 'developer_documentation_urls' => {
17
- 'errors.responses.invalid_subdomain' => 'http://example.com/foo',
18
- },
19
- }
20
-
21
- Drillbit.configure do |config|
22
- config.allowed_subdomains = %w{api westeros}
23
- config.allowed_api_subdomains = %w{api}
24
- config.application_name = 'westeros'
25
- end
26
- end
27
-
28
- it 'allows requests for allowed subdomains without accept headers' do
29
- api_request_middleware = ApiRequestValidator.new(app)
30
-
31
- request = {
32
- 'HTTP_HOST' => 'westeros.example.com',
33
- 'HTTP_ACCEPT' => '',
34
- 'QUERY_STRING' => '',
35
- }
36
-
37
- status, headers, response = api_request_middleware.call(request)
38
-
39
- expect(status).to eql 200
40
- expect(headers).to eql({})
41
- expect(response).to eql 'response'
42
- end
43
-
44
- it 'does not allow requests if they are not for an allowed subdomain' do
45
- api_request_middleware = ApiRequestValidator.new(app)
46
-
47
- request = {
48
- 'HTTP_HOST' => 'notvalid.example.com',
49
- 'HTTP_ACCEPT' => '',
50
- 'QUERY_STRING' => 'first=my_param&accept=application/vnd.silent+redkeep;version=1.0.0',
51
- }
52
-
53
- status, headers, response = api_request_middleware.call(request)
54
-
55
- expect(status).to eql 404
56
- expect(headers).to eql({})
57
- expect(JSON.load(response[0])).to include(
58
- 'errors' => [
59
- {
60
- 'id' => match(/[a-z0-9\-]+/),
61
- 'links' => {
62
- 'about' => nil,
63
- 'documentation' => nil,
64
- },
65
- 'status' => 404,
66
- 'code' => 'errors.invalid_subdomain',
67
- 'title' => 'Invalid Subdomain',
68
- 'detail' => 'The subdomain you attempted to access is not valid.' \
69
- ' Please try again.',
70
- 'source' => {
71
- 'http_host' => 'notvalid.example.com',
72
- },
73
- },
74
- ],
75
- )
76
- end
77
-
78
- it 'does not allow requests if they are for an allowed subdomain but does ' \
79
- 'not have a valid accept header' do
80
-
81
- api_request_middleware = ApiRequestValidator.new(app)
82
-
83
- request = {
84
- 'HTTP_HOST' => 'api.example.com',
85
- 'HTTP_ACCEPT' => '',
86
- 'QUERY_STRING' => 'first=my_param&accept=application/vnd.silent+redkeep;version=1.0.0',
87
- }
88
-
89
- status, headers, response = api_request_middleware.call(request)
90
-
91
- expect(status).to eql 400
92
- expect(headers).to eql({})
93
- expect(JSON.load(response[0])).to include(
94
- 'errors' => [
95
- {
96
- 'id' => match(/[a-z0-9\-]+/),
97
- 'links' => {
98
- 'about' => nil,
99
- 'documentation' => nil,
100
- },
101
- 'status' => 400,
102
- 'code' => 'errors.invalid_api_request',
103
- 'title' => 'Invalid API Request',
104
- 'detail' => 'The accept header that you passed in the request cannot be ' \
105
- 'parsed, please refer to the documentation to verify.',
106
- 'source' => {
107
- 'accept_header' => '',
108
- },
109
- },
110
- ],
111
- )
112
- end
113
-
114
- it 'does allow requests if both the subdomain and the accept header are valid' do
115
- api_request_middleware = ApiRequestValidator.new(app)
116
-
117
- request = {
118
- 'HTTP_HOST' => 'api.example.com',
119
- 'HTTP_ACCEPT' => 'application/vnd.westeros+redkeep;version=1.0.0',
120
- 'QUERY_STRING' => 'first=my_param&accept=application/vnd.westeros+redkeep;version=1.0.0',
121
- }
122
-
123
- status, headers, response = api_request_middleware.call(request)
124
-
125
- expect(status).to eql 200
126
- expect(headers).to eql({})
127
- expect(response).to eql 'response'
128
- end
129
-
130
- it 'does allow requests if the subdomain, the accept header and the token are valid' do
131
- Drillbit.configuration.token_private_key = test_private_key
132
- api_request_middleware = ApiRequestValidator.new(app)
133
-
134
- request = {
135
- 'HTTP_HOST' => 'api.example.com',
136
- 'HTTP_ACCEPT' => 'application/vnd.westeros+redkeep;version=1.0.0',
137
- 'HTTP_AUTHORIZATION' => "Token #{valid_jwe_token}",
138
- 'QUERY_STRING' => 'accept=application/vnd.westeros+redkeep;version=1.0.0',
139
- }
140
-
141
- status, headers, response = api_request_middleware.call(request)
142
-
143
- expect(status).to eql 200
144
- expect(headers).to eql({})
145
- expect(response).to eql 'response'
146
- end
147
-
148
- it 'properly converts the content type for Rails when it is the only one' do
149
- api_request_middleware = ApiRequestValidator.new(app)
150
-
151
- request = {
152
- 'CONTENT_TYPE' => 'application/vnd.api+json',
153
- 'HTTP_HOST' => 'westeros.example.com',
154
- 'HTTP_ACCEPT' => '',
155
- 'QUERY_STRING' => '',
156
- }
157
-
158
- allow(app).to receive(:call)
159
-
160
- _response = api_request_middleware.call(request)
161
-
162
- expect(app).to have_received(:call).
163
- with(a_hash_including('CONTENT_TYPE' => 'application/json'))
164
- end
165
-
166
- it 'properly converts the content type for Rails when it is not the only one' do
167
- api_request_middleware = ApiRequestValidator.new(app)
168
-
169
- request = {
170
- 'CONTENT_TYPE' => 'application/vnd.api+json;other',
171
- 'HTTP_HOST' => 'westeros.example.com',
172
- 'HTTP_ACCEPT' => '',
173
- 'QUERY_STRING' => '',
174
- }
175
-
176
- allow(app).to receive(:call)
177
-
178
- _response = api_request_middleware.call(request)
179
-
180
- expect(app).to have_received(:call).
181
- with(a_hash_including('CONTENT_TYPE' => 'application/json;other'))
182
- end
183
- end
184
- end
185
- end
@@ -1,200 +0,0 @@
1
- # frozen_string_literal: true
2
- require 'spec_helper'
3
- require 'drillbit/middleware/parameter_parser'
4
-
5
- module Drillbit
6
- module Middleware
7
- describe ParameterParser do
8
- let(:app) { ->(_env) { [200, {}, 'response'] } }
9
-
10
- it 'converts JSON API compliant dasherized query params to underscored' do
11
- app = ->(env) { [200, env, 'response'] }
12
- middleware = ParameterParser.new(app)
13
-
14
- request = {
15
- 'QUERY_STRING' => 'hello-there=bob-jones&' \
16
- 'nice-to-meet=you-bob&' \
17
- 'hows-the-weather=today-bob',
18
- }
19
-
20
- _status, headers, _response = middleware.call(request)
21
-
22
- expect(headers['QUERY_STRING']).to eql 'hello_there=bob-jones&' \
23
- 'nice_to_meet=you-bob&' \
24
- 'hows_the_weather=today-bob'
25
- end
26
-
27
- it 'does not touch query params with no dashes' do
28
- app = ->(env) { [200, env, 'response'] }
29
- middleware = ParameterParser.new(app)
30
-
31
- request = {
32
- 'QUERY_STRING' => 'hello_there=bob-jones',
33
- }
34
-
35
- _status, headers, _response = middleware.call(request)
36
-
37
- expect(headers['QUERY_STRING']).to eql 'hello_there=bob-jones'
38
- end
39
-
40
- it 'can handle weirdly formatted query string parameters' do
41
- app = ->(env) { [200, env, 'response'] }
42
- middleware = ParameterParser.new(app)
43
-
44
- request = {
45
- 'QUERY_STRING' => 'hello-there=bob-jones&' \
46
- 'nice-to-meet=you-bob&=',
47
- }
48
-
49
- _status, headers, _response = middleware.call(request)
50
-
51
- expect(headers['QUERY_STRING']).to eql 'hello_there=bob-jones&' \
52
- 'nice_to_meet=you-bob&='
53
- end
54
-
55
- it 'can handle query string parameters with no values' do
56
- app = ->(env) { [200, env, 'response'] }
57
- middleware = ParameterParser.new(app)
58
-
59
- request = {
60
- 'QUERY_STRING' => 'hello-there&nice-to-meet=you-bob&=',
61
- }
62
-
63
- _status, headers, _response = middleware.call(request)
64
-
65
- expect(headers['QUERY_STRING']).to eql 'hello_there&nice_to_meet=you-bob&='
66
- end
67
-
68
- it 'can handle query string parameters with parameter name' do
69
- app = ->(env) { [200, env, 'response'] }
70
- middleware = ParameterParser.new(app)
71
-
72
- request = {
73
- 'QUERY_STRING' => 'hello-there=bob-jones&=you-bob&nice-to-meet=you-bob&=',
74
- }
75
-
76
- _status, headers, _response = middleware.call(request)
77
-
78
- expect(headers['QUERY_STRING']).to eql 'hello_there=bob-jones&' \
79
- '=you-bob&' \
80
- 'nice_to_meet=you-bob&='
81
- end
82
-
83
- it 'converts JSON API compliant dasherized request params to underscored' do
84
- app = ->(env) { [200, env, 'response'] }
85
- middleware = ParameterParser.new(app)
86
-
87
- request = {
88
- 'CONTENT_LENGTH' => '1',
89
- 'CONTENT_TYPE' => 'application/json',
90
- 'RACK_INPUT' => <<-HEREDOC
91
- {
92
- "single": "word",
93
- "double-word": "double double",
94
- "triple": {
95
- "trippple-tripple": "mcdipple",
96
- "quad": {
97
- "another-level": "whoa inception"
98
- }
99
- },
100
- "quint": [
101
- {
102
- "quint-it-quit": "mc-dipple"
103
- },
104
- {
105
- "quint-it-quit": "big-maccle"
106
- }
107
- ]
108
- }
109
- HEREDOC
110
- }
111
-
112
- _status, headers, _response = middleware.call(request)
113
-
114
- expect(JSON.load(headers['RACK_INPUT'])).to eql(
115
- 'single' => 'word',
116
- 'double_word' => 'double double',
117
- 'triple' => {
118
- 'trippple_tripple' => 'mcdipple',
119
- 'quad' => {
120
- 'another_level' => 'whoa inception',
121
- },
122
- },
123
- 'quint' => [
124
- {
125
- 'quint_it_quit' => 'mc-dipple',
126
- },
127
- {
128
- 'quint_it_quit' => 'big-maccle',
129
- },
130
- ],
131
- )
132
- end
133
-
134
- it 'does not convert to JSON if the content type is not JSON' do
135
- app = ->(env) { [200, env, 'response'] }
136
- middleware = ParameterParser.new(app)
137
-
138
- request = {
139
- 'CONTENT_LENGTH' => '1',
140
- 'CONTENT_TYPE' => 'not_j_s_o_n',
141
- 'RACK_INPUT' => 'This is not JSON',
142
- }
143
-
144
- _status, headers, _response = middleware.call(request)
145
-
146
- expect(headers['RACK_INPUT']).to eql 'This is not JSON'
147
- end
148
-
149
- it 'does not convert to JSON if there is no content' do
150
- app = ->(env) { [200, env, 'response'] }
151
- middleware = ParameterParser.new(app)
152
-
153
- request = {
154
- 'CONTENT_LENGTH' => '0',
155
- 'CONTENT_TYPE' => 'application/json',
156
- 'RACK_INPUT' => 'empty',
157
- }
158
-
159
- _status, headers, _response = middleware.call(request)
160
-
161
- expect(headers['RACK_INPUT']).to eql 'empty'
162
- end
163
-
164
- it 'can handle incorrectly formatted JSON' do
165
- app = ->(env) { [200, env, 'response'] }
166
- middleware = ParameterParser.new(app)
167
-
168
- request = {
169
- 'CONTENT_LENGTH' => '1',
170
- 'CONTENT_TYPE' => 'application/json',
171
- 'RACK_INPUT' => 'something blah',
172
- }
173
-
174
- status, headers, response = middleware.call(request)
175
-
176
- expect(status).to eql 400
177
- expect(headers).to eql({})
178
- expect(JSON.load(response[0])).to include(
179
- 'errors' => [
180
- {
181
- 'id' => match(/[a-z0-9\-]+/),
182
- 'links' => {
183
- 'about' => nil,
184
- 'documentation' => nil,
185
- },
186
- 'status' => 400,
187
- 'code' => 'errors.invalid_request_body',
188
- 'title' => 'Invalid Request Body',
189
- 'detail' => 'The information you attempted to send in the ' \
190
- 'request cannot be parsed as a valid JSON document.',
191
- 'source' => {
192
- 'request_body' => 'something blah',
193
- },
194
- },
195
- ],
196
- )
197
- end
198
- end
199
- end
200
- end