drillbit 2.11.0 → 3.0.0

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