grape 1.0.3 → 1.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 5e2e2a2c3e1ed64c7c75af7d0fb52467c4e596a9
4
- data.tar.gz: a23ce793ad55115be0300f310f7ec024769275e8
2
+ SHA256:
3
+ metadata.gz: 7768f2318b0b1045ec81b3a83cb08b5d80676da77aaa30f059fb056175578781
4
+ data.tar.gz: e19ecc4e39b33a19e43e7831ceab4d5a13fd186677cef84547066e48d24d98d0
5
5
  SHA512:
6
- metadata.gz: e754bfdf8d83d12ed4e770114a3a8b5e80ca2462be2d13cbbd68a15b5c528856d897715f630f381460bc4cdc4f2715dffd24945c5c510db397183f79a281af11
7
- data.tar.gz: 25da8c7eb6ef92e5ea4ac55103fb688738f3544818b6a971408f150fab4392bbe8e0e0f2a1be56cf47e0a121aabf790bd4389876ee9dfc11c00b6b77920a40ff
6
+ metadata.gz: afc16b3f2a5036029bb22615ded000eefb2c24f396efa1f2bc22b253bb84d1adb2a4f2ea7dad63a8d4f98a0c69e7720b828072e57bd8e5ce281c1d158f25cb02
7
+ data.tar.gz: b650ba30bc697feea23a4aa03a50e525b135e25c14707b85f4e95b7a95c5ba37e1565ddce147148885467516c1a7d48e74d58cabb1172679978dcbe28216674a
data/Appraisals CHANGED
@@ -16,7 +16,7 @@ appraise 'rack-1.5.2' do
16
16
  end
17
17
 
18
18
  appraise 'rails-edge' do
19
- gem 'arel', github: 'rails/arel'
19
+ gem 'rails', github: 'rails/rails'
20
20
  end
21
21
 
22
22
  appraise 'rack-edge' do
@@ -1,3 +1,18 @@
1
+ ### 1.1.0 (8/4/2018)
2
+
3
+ #### Features
4
+
5
+ * [#1759](https://github.com/ruby-grape/grape/pull/1759): Instrument serialization as `'format_response.grape'` - [@zvkemp](https://github.com/zvkemp).
6
+
7
+ #### Fixes
8
+
9
+
10
+ * [#1762](https://github.com/ruby-grape/grape/pull/1763): Fix unsafe HTML rendering on errors - [@ctennis](https://github.com/ctennis).
11
+ * [#1759](https://github.com/ruby-grape/grape/pull/1759): Update appraisal for rails_edge - [@zvkemp](https://github.com/zvkemp).
12
+ * [#1758](https://github.com/ruby-grape/grape/pull/1758): Fix expanding load_path in gemspec - [@2maz](https://github.com/2maz).
13
+ * [#1765](https://github.com/ruby-grape/grape/pull/1765): Use 415 when request body is of an unsupported media type - [@jdmurphy](https://github.com/jdmurphy).
14
+ * [#1771](https://github.com/ruby-grape/grape/pull/1771): Fix param aliases with 'given' blocks - [@jereynolds](https://github.com/jereynolds).
15
+
1
16
  ### 1.0.3 (4/23/2018)
2
17
 
3
18
  #### Fixes
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- grape (1.0.3)
4
+ grape (1.1.0)
5
5
  activesupport
6
6
  builder
7
7
  mustermann-grape (~> 1.0.0)
@@ -12,9 +12,9 @@ PATH
12
12
  GEM
13
13
  remote: https://rubygems.org/
14
14
  specs:
15
- activesupport (5.1.4)
15
+ activesupport (5.2.0)
16
16
  concurrent-ruby (~> 1.0, >= 1.0.2)
17
- i18n (~> 0.7)
17
+ i18n (>= 0.7, < 2)
18
18
  minitest (~> 5.1)
19
19
  tzinfo (~> 1.1)
20
20
  addressable (2.5.2)
@@ -44,9 +44,9 @@ GEM
44
44
  cookiejar (0.3.3)
45
45
  cork (0.3.0)
46
46
  colored2 (~> 3.1)
47
- coveralls (0.8.21)
47
+ coveralls (0.8.22)
48
48
  json (>= 1.8, < 3)
49
- simplecov (~> 0.14.1)
49
+ simplecov (~> 0.16.1)
50
50
  term-ansicolor (~> 1.3)
51
51
  thor (~> 0.19.4)
52
52
  tins (~> 1.6)
@@ -72,15 +72,15 @@ GEM
72
72
  descendants_tracker (0.0.4)
73
73
  thread_safe (~> 0.3, >= 0.3.1)
74
74
  diff-lcs (1.3)
75
- docile (1.1.5)
75
+ docile (1.3.1)
76
76
  equalizer (0.0.11)
77
- faraday (0.14.0)
77
+ faraday (0.15.2)
78
78
  multipart-post (>= 1.2, < 3)
79
79
  faraday-http-cache (1.3.1)
80
80
  faraday (~> 0.8)
81
- ffi (1.9.21)
81
+ ffi (1.9.25)
82
82
  formatador (0.2.5)
83
- git (1.3.0)
83
+ git (1.4.0)
84
84
  grape-entity (0.7.1)
85
85
  activesupport (>= 4.0)
86
86
  multi_json (>= 1.3.2)
@@ -102,16 +102,16 @@ GEM
102
102
  guard (~> 2.0)
103
103
  rubocop (~> 0.20)
104
104
  hashie (3.5.7)
105
- i18n (0.9.4)
105
+ i18n (1.0.1)
106
106
  concurrent-ruby (~> 1.0)
107
107
  ice_nine (0.11.2)
108
108
  json (2.1.0)
109
- kramdown (1.16.2)
109
+ kramdown (1.17.0)
110
110
  listen (3.1.5)
111
111
  rb-fsevent (~> 0.9, >= 0.9.4)
112
112
  rb-inotify (~> 0.9, >= 0.9.7)
113
113
  ruby_dep (~> 1.2)
114
- lumberjack (1.0.12)
114
+ lumberjack (1.0.13)
115
115
  maruku (0.7.3)
116
116
  method_source (0.9.0)
117
117
  mime-types (3.1)
@@ -120,7 +120,7 @@ GEM
120
120
  minitest (5.11.3)
121
121
  multi_json (1.13.1)
122
122
  multipart-post (2.0.0)
123
- mustermann (1.0.1)
123
+ mustermann (1.0.2)
124
124
  mustermann-grape (1.0.0)
125
125
  mustermann (~> 1.0.0)
126
126
  nap (1.1.0)
@@ -128,18 +128,18 @@ GEM
128
128
  notiffany (0.1.1)
129
129
  nenv (~> 0.1)
130
130
  shellany (~> 0.0)
131
- octokit (4.8.0)
131
+ octokit (4.9.0)
132
132
  sawyer (~> 0.8.0, >= 0.5.3)
133
133
  open4 (1.3.4)
134
134
  parallel (1.12.1)
135
- parser (2.4.0.2)
136
- ast (~> 2.3)
137
- powerpack (0.1.1)
135
+ parser (2.5.1.2)
136
+ ast (~> 2.4.0)
137
+ powerpack (0.1.2)
138
138
  pry (0.11.3)
139
139
  coderay (~> 1.1.0)
140
140
  method_source (~> 0.9.0)
141
- public_suffix (3.0.1)
142
- rack (2.0.4)
141
+ public_suffix (3.0.2)
142
+ rack (2.0.5)
143
143
  rack-accept (0.4.5)
144
144
  rack (>= 0.4)
145
145
  rack-jsonp (1.3.1)
@@ -148,8 +148,8 @@ GEM
148
148
  rack (>= 1.0)
149
149
  rainbow (2.2.2)
150
150
  rake
151
- rake (12.3.0)
152
- rb-fsevent (0.10.2)
151
+ rake (12.3.1)
152
+ rb-fsevent (0.10.3)
153
153
  rb-inotify (0.9.10)
154
154
  ffi (>= 0.5.0, < 2)
155
155
  rspec (3.7.0)
@@ -181,8 +181,8 @@ GEM
181
181
  addressable (>= 2.3.5, < 2.6)
182
182
  faraday (~> 0.8, < 1.0)
183
183
  shellany (0.0.1)
184
- simplecov (0.14.1)
185
- docile (~> 1.1.0)
184
+ simplecov (0.16.1)
185
+ docile (~> 1.1)
186
186
  json (>= 1.8, < 3)
187
187
  simplecov-html (~> 0.10.0)
188
188
  simplecov-html (0.10.2)
@@ -195,7 +195,7 @@ GEM
195
195
  tins (1.16.3)
196
196
  tzinfo (1.2.5)
197
197
  thread_safe (~> 0.1)
198
- unicode-display_width (1.3.0)
198
+ unicode-display_width (1.4.0)
199
199
  virtus (1.0.5)
200
200
  axiom-types (~> 0.1)
201
201
  coercible (~> 1.0)
@@ -228,4 +228,4 @@ DEPENDENCIES
228
228
  ruby-grape-danger (~> 0.1.0)
229
229
 
230
230
  BUNDLED WITH
231
- 1.15.3
231
+ 1.16.3
data/README.md CHANGED
@@ -129,6 +129,7 @@
129
129
  - [endpoint_render.grape](#endpoint_rendergrape)
130
130
  - [endpoint_run_filters.grape](#endpoint_run_filtersgrape)
131
131
  - [endpoint_run_validators.grape](#endpoint_run_validatorsgrape)
132
+ - [format_response.grape](#format_responsegrape)
132
133
  - [Monitoring Products](#monitoring-products)
133
134
  - [Contributing to Grape](#contributing-to-grape)
134
135
  - [License](#license)
@@ -144,7 +145,7 @@ content negotiation, versioning and much more.
144
145
 
145
146
  ## Stable Release
146
147
 
147
- You're reading the documentation for the stable release of Grape, **1.0.3**.
148
+ You're reading the documentation for the stable release of Grape, **1.1.0**.
148
149
  Please read [UPGRADING](UPGRADING.md) when upgrading from a previous version.
149
150
 
150
151
  ## Project Resources
@@ -1815,8 +1816,8 @@ module SharedParams
1815
1816
  extend Grape::API::Helpers
1816
1817
 
1817
1818
  params :order do |options|
1818
- optional :order_by, type:Symbol, values:options[:order_by], default:options[:default_order_by]
1819
- optional :order, type:Symbol, values:%i(asc desc), default:options[:default_order]
1819
+ optional :order_by, type: Symbol, values: options[:order_by], default: options[:default_order_by]
1820
+ optional :order, type: Symbol, values: %i(asc desc), default: options[:default_order]
1820
1821
  end
1821
1822
  end
1822
1823
 
@@ -1825,7 +1826,7 @@ class API < Grape::API
1825
1826
 
1826
1827
  desc 'Get a sorted collection.'
1827
1828
  params do
1828
- use :order, order_by:%i(id created_at), default_order_by: :created_at, default_order: :asc
1829
+ use :order, order_by: %i(id created_at), default_order_by: :created_at, default_order: :asc
1829
1830
  end
1830
1831
 
1831
1832
  get do
@@ -2549,6 +2550,9 @@ Built-in formatters are the following.
2549
2550
  * `:serializable_hash`: use object's `serializable_hash` when available, otherwise fallback to `:json`
2550
2551
  * `:binary`: data will be returned "as is"
2551
2552
 
2553
+ If a body is present in a request to an API, with a Content-Type header value that is of an unsupported type a
2554
+ "415 Unsupported Media Type" error code will be returned by Grape.
2555
+
2552
2556
  Response statuses that indicate no content as defined by [Rack](https://github.com/rack)
2553
2557
  [here](https://github.com/rack/rack/blob/master/lib/rack/utils.rb#L567)
2554
2558
  will bypass serialization and the body entity - though there should be none -
@@ -3483,6 +3487,13 @@ The execution of validators.
3483
3487
  * *validators* - The validators being executed
3484
3488
  * *request* - The request being validated
3485
3489
 
3490
+ #### format_response.grape
3491
+
3492
+ Serialization or template rendering.
3493
+
3494
+ * *env* - The request environment
3495
+ * *formatter* - The formatter object (e.g., `Grape::Formatter::Json`)
3496
+
3486
3497
  See the [ActiveSupport::Notifications documentation](http://api.rubyonrails.org/classes/ActiveSupport/Notifications.html) for information on how to subscribe to these events.
3487
3498
 
3488
3499
  ### Monitoring Products
@@ -1,6 +1,12 @@
1
1
  Upgrading Grape
2
2
  ===============
3
3
 
4
+ ### Upgrading to >= 1.1.0
5
+
6
+ #### Changes in HTTP Response Code for Unsupported Content Type
7
+
8
+ For PUT, POST, PATCH, and DELETE requests where a non-empty body and a "Content-Type" header is supplied that is not supported by the Grape API, Grape will no longer return a 406 "Not Acceptable" HTTP status code and will instead return a 415 "Unsupported Media Type" so that the usage of HTTP status code falls more in line with the specification of [RFC 2616](https://www.ietf.org/rfc/rfc2616.txt).
9
+
4
10
  ### Upgrading to >= 1.0.0
5
11
 
6
12
  #### Changes in XML and JSON Parsers
@@ -22,7 +22,7 @@ end
22
22
  group :test do
23
23
  gem 'cookiejar'
24
24
  gem 'coveralls', '~> 0.8.17', require: false
25
- gem 'danger-toc', '~> 0.1.0'
25
+ gem 'danger-toc', '~> 0.1.2'
26
26
  gem 'grape-entity', '~> 0.6'
27
27
  gem 'maruku'
28
28
  gem 'mime-types'
@@ -22,7 +22,7 @@ end
22
22
  group :test do
23
23
  gem 'cookiejar'
24
24
  gem 'coveralls', '~> 0.8.17', require: false
25
- gem 'danger-toc', '~> 0.1.0'
25
+ gem 'danger-toc', '~> 0.1.2'
26
26
  gem 'grape-entity', '~> 0.6'
27
27
  gem 'maruku'
28
28
  gem 'mime-types'
@@ -22,7 +22,7 @@ end
22
22
  group :test do
23
23
  gem 'cookiejar'
24
24
  gem 'coveralls', '~> 0.8.17', require: false
25
- gem 'danger-toc', '~> 0.1.0'
25
+ gem 'danger-toc', '~> 0.1.2'
26
26
  gem 'grape-entity', '~> 0.6'
27
27
  gem 'maruku'
28
28
  gem 'mime-types'
@@ -22,7 +22,7 @@ end
22
22
  group :test do
23
23
  gem 'cookiejar'
24
24
  gem 'coveralls', '~> 0.8.17', require: false
25
- gem 'danger-toc', '~> 0.1.0'
25
+ gem 'danger-toc', '~> 0.1.2'
26
26
  gem 'grape-entity', '~> 0.6'
27
27
  gem 'maruku'
28
28
  gem 'mime-types'
@@ -23,7 +23,7 @@ end
23
23
  group :test do
24
24
  gem 'cookiejar'
25
25
  gem 'coveralls', '~> 0.8.17', require: false
26
- gem 'danger-toc', '~> 0.1.0'
26
+ gem 'danger-toc', '~> 0.1.2'
27
27
  gem 'grape-entity', '~> 0.6'
28
28
  gem 'maruku'
29
29
  gem 'mime-types'
@@ -22,7 +22,7 @@ end
22
22
  group :test do
23
23
  gem 'cookiejar'
24
24
  gem 'coveralls', '~> 0.8.17', require: false
25
- gem 'danger-toc', '~> 0.1.0'
25
+ gem 'danger-toc', '~> 0.1.2'
26
26
  gem 'grape-entity', '~> 0.6'
27
27
  gem 'maruku'
28
28
  gem 'mime-types'
@@ -22,7 +22,7 @@ end
22
22
  group :test do
23
23
  gem 'cookiejar'
24
24
  gem 'coveralls', '~> 0.8.17', require: false
25
- gem 'danger-toc', '~> 0.1.0'
25
+ gem 'danger-toc', '~> 0.1.2'
26
26
  gem 'grape-entity', '~> 0.6'
27
27
  gem 'maruku'
28
28
  gem 'mime-types'
@@ -2,7 +2,7 @@
2
2
 
3
3
  source 'https://rubygems.org'
4
4
 
5
- gem 'arel', github: 'rails/arel'
5
+ gem 'rails', github: 'rails/rails'
6
6
 
7
7
  group :development, :test do
8
8
  gem 'bundler'
@@ -22,7 +22,7 @@ end
22
22
  group :test do
23
23
  gem 'cookiejar'
24
24
  gem 'coveralls', '~> 0.8.17', require: false
25
- gem 'danger-toc', '~> 0.1.0'
25
+ gem 'danger-toc', '~> 0.1.2'
26
26
  gem 'grape-entity', '~> 0.6'
27
27
  gem 'maruku'
28
28
  gem 'mime-types'
@@ -1,4 +1,4 @@
1
- $LOAD_PATH.push File.expand_path('../lib', __FILE__)
1
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
2
2
  require 'grape/version'
3
3
 
4
4
  Gem::Specification.new do |s|
@@ -1,4 +1,5 @@
1
1
  require 'grape/middleware/base'
2
+ require 'active_support/core_ext/string/output_safety'
2
3
 
3
4
  module Grape
4
5
  module Middleware
@@ -69,6 +70,9 @@ module Grape
69
70
  end
70
71
 
71
72
  def rack_response(message, status = options[:default_status], headers = { Grape::Http::Headers::CONTENT_TYPE => content_type })
73
+ if headers[Grape::Http::Headers::CONTENT_TYPE] == TEXT_HTML
74
+ message = ERB::Util.html_escape(message)
75
+ end
72
76
  Rack::Response.new([message], status, headers).finish
73
77
  end
74
78
 
@@ -41,7 +41,9 @@ module Grape
41
41
  else
42
42
  # Allow content-type to be explicitly overwritten
43
43
  formatter = fetch_formatter(headers, options)
44
- bodymap = bodies.collect { |body| formatter.call(body, env) }
44
+ bodymap = ActiveSupport::Notifications.instrument('format_response.grape', formatter: formatter, env: env) do
45
+ bodies.collect { |body| formatter.call(body, env) }
46
+ end
45
47
  Rack::Response.new(bodymap, status, headers)
46
48
  end
47
49
  rescue Grape::Exceptions::InvalidFormatter => e
@@ -93,7 +95,7 @@ module Grape
93
95
  fmt = request.media_type ? mime_types[request.media_type] : options[:default_format]
94
96
 
95
97
  unless content_type_for(fmt)
96
- throw :error, status: 406, message: "The requested content-type '#{request.media_type}' is not supported."
98
+ throw :error, status: 415, message: "The provided content-type '#{request.media_type}' is not supported."
97
99
  end
98
100
  parser = Grape::Parser.parser_for fmt, options
99
101
  if parser
@@ -116,7 +116,7 @@ module Grape
116
116
  # @param attrs [Array] (see Grape::DSL::Parameters#requires)
117
117
  def push_declared_params(attrs, **opts)
118
118
  if lateral?
119
- @parent.push_declared_params(attrs)
119
+ @parent.push_declared_params(attrs, opts)
120
120
  else
121
121
  if opts && opts[:as]
122
122
  @api.route_setting(:aliased_params, @api.route_setting(:aliased_params) || [])
@@ -1,4 +1,4 @@
1
1
  module Grape
2
2
  # The current version of Grape.
3
- VERSION = '1.0.3'.freeze
3
+ VERSION = '1.1.0'.freeze
4
4
  end
Binary file
Binary file
@@ -2142,7 +2142,11 @@ XML
2142
2142
  end
2143
2143
  get '/excel.json'
2144
2144
  expect(last_response.status).to eq(406)
2145
- expect(last_response.body).to eq("The requested format 'txt' is not supported.")
2145
+ if ActiveSupport::VERSION::MAJOR == 3
2146
+ expect(last_response.body).to eq('The requested format &#x27;txt&#x27; is not supported.')
2147
+ else
2148
+ expect(last_response.body).to eq('The requested format &#39;txt&#39; is not supported.')
2149
+ end
2146
2150
  end
2147
2151
  end
2148
2152
 
@@ -3524,7 +3528,27 @@ XML
3524
3528
  end
3525
3529
  get '/something'
3526
3530
  expect(last_response.status).to eq(406)
3527
- expect(last_response.body).to eq("{\"error\":\"The requested format 'txt' is not supported.\"}")
3531
+ if ActiveSupport::VERSION::MAJOR == 3
3532
+ expect(last_response.body).to eq('{&quot;error&quot;:&quot;The requested format &#x27;txt&#x27; is not supported.&quot;}')
3533
+ else
3534
+ expect(last_response.body).to eq('{&quot;error&quot;:&quot;The requested format &#39;txt&#39; is not supported.&quot;}')
3535
+ end
3536
+ end
3537
+ end
3538
+
3539
+ context 'with unsafe HTML format specified' do
3540
+ it 'escapes the HTML' do
3541
+ subject.content_type :json, 'application/json'
3542
+ subject.get '/something' do
3543
+ 'foo'
3544
+ end
3545
+ get '/something?format=<script>blah</script>'
3546
+ expect(last_response.status).to eq(406)
3547
+ if ActiveSupport::VERSION::MAJOR == 3
3548
+ expect(last_response.body).to eq('The requested format &#x27;&lt;script&gt;blah&lt;/script&gt;&#x27; is not supported.')
3549
+ else
3550
+ expect(last_response.body).to eq('The requested format &#39;&lt;script&gt;blah&lt;/script&gt;&#39; is not supported.')
3551
+ end
3528
3552
  end
3529
3553
  end
3530
3554
 
@@ -941,15 +941,15 @@ describe Grape::Endpoint do
941
941
  end
942
942
  end
943
943
 
944
- it 'responds with a 406 for an unsupported content-type' do
944
+ it 'responds with a 415 for an unsupported content-type' do
945
945
  subject.format :json
946
946
  # subject.content_type :json, "application/json"
947
947
  subject.put '/request_body' do
948
948
  params[:user]
949
949
  end
950
950
  put '/request_body', '<user>Bobby T.</user>', 'CONTENT_TYPE' => 'application/xml'
951
- expect(last_response.status).to eq(406)
952
- expect(last_response.body).to eq('{"error":"The requested content-type \'application/xml\' is not supported."}')
951
+ expect(last_response.status).to eq(415)
952
+ expect(last_response.body).to eq('{"error":"The provided content-type \'application/xml\' is not supported."}')
953
953
  end
954
954
 
955
955
  it 'does not accept text/plain in JSON format if application/json is specified as content type' do
@@ -960,8 +960,8 @@ describe Grape::Endpoint do
960
960
  end
961
961
  put '/request_body', ::Grape::Json.dump(user: 'Bob'), 'CONTENT_TYPE' => 'text/plain'
962
962
 
963
- expect(last_response.status).to eq(406)
964
- expect(last_response.body).to eq('{"error":"The requested content-type \'text/plain\' is not supported."}')
963
+ expect(last_response.status).to eq(415)
964
+ expect(last_response.body).to eq('{"error":"The provided content-type \'text/plain\' is not supported."}')
965
965
  end
966
966
 
967
967
  context 'content type with params' do
@@ -1493,7 +1493,9 @@ describe Grape::Endpoint do
1493
1493
  filters: [],
1494
1494
  type: :after }),
1495
1495
  have_attributes(name: 'endpoint_run.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1496
- env: an_instance_of(Hash) })
1496
+ env: an_instance_of(Hash) }),
1497
+ have_attributes(name: 'format_response.grape', payload: { env: an_instance_of(Hash),
1498
+ formatter: a_kind_of(Module) })
1497
1499
  )
1498
1500
 
1499
1501
  # In order that events were initialized
@@ -1515,7 +1517,9 @@ describe Grape::Endpoint do
1515
1517
  have_attributes(name: 'endpoint_render.grape', payload: { endpoint: a_kind_of(Grape::Endpoint) }),
1516
1518
  have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1517
1519
  filters: [],
1518
- type: :after })
1520
+ type: :after }),
1521
+ have_attributes(name: 'format_response.grape', payload: { env: an_instance_of(Hash),
1522
+ formatter: a_kind_of(Module) })
1519
1523
  )
1520
1524
  end
1521
1525
  end
@@ -192,7 +192,7 @@ describe Grape::Middleware::Error do
192
192
  end
193
193
  it 'is possible to return errors in jsonapi format' do
194
194
  get '/'
195
- expect(last_response.body).to eq('{"error":"rain!"}')
195
+ expect(last_response.body).to eq('{&quot;error&quot;:&quot;rain!&quot;}')
196
196
  end
197
197
  end
198
198
 
@@ -207,8 +207,8 @@ describe Grape::Middleware::Error do
207
207
 
208
208
  it 'is possible to return hash errors in jsonapi format' do
209
209
  get '/'
210
- expect(['{"error":"rain!","detail":"missing widget"}',
211
- '{"detail":"missing widget","error":"rain!"}']).to include(last_response.body)
210
+ expect(['{&quot;error&quot;:&quot;rain!&quot;,&quot;detail&quot;:&quot;missing widget&quot;}',
211
+ '{&quot;detail&quot;:&quot;missing widget&quot;,&quot;error&quot;:&quot;rain!&quot;}']).to include(last_response.body)
212
212
  end
213
213
  end
214
214
 
@@ -258,7 +258,7 @@ describe Grape::Middleware::Error do
258
258
  end
259
259
  it 'is possible to specify a custom formatter' do
260
260
  get '/'
261
- expect(last_response.body).to eq('{:custom_formatter=>"rain!"}')
261
+ expect(last_response.body).to eq('{:custom_formatter=&gt;&quot;rain!&quot;}')
262
262
  end
263
263
  end
264
264
 
@@ -224,6 +224,80 @@ describe Grape::Middleware::Formatter do
224
224
 
225
225
  context 'input' do
226
226
  %w[POST PATCH PUT DELETE].each do |method|
227
+ context 'when body is not nil or empty' do
228
+ context 'when Content-Type is supported' do
229
+ let(:io) { StringIO.new('{"is_boolean":true,"string":"thing"}') }
230
+ let(:content_type) { 'application/json' }
231
+
232
+ it "parses the body from #{method} and copies values into rack.request.form_hash" do
233
+ subject.call(
234
+ 'PATH_INFO' => '/info',
235
+ 'REQUEST_METHOD' => method,
236
+ 'CONTENT_TYPE' => content_type,
237
+ 'rack.input' => io,
238
+ 'CONTENT_LENGTH' => io.length
239
+ )
240
+ expect(subject.env['rack.request.form_hash']['is_boolean']).to be true
241
+ expect(subject.env['rack.request.form_hash']['string']).to eq('thing')
242
+ end
243
+ end
244
+
245
+ context 'when Content-Type is not supported' do
246
+ let(:io) { StringIO.new('{"is_boolean":true,"string":"thing"}') }
247
+ let(:content_type) { 'application/atom+xml' }
248
+
249
+ it 'returns a 415 HTTP error status' do
250
+ error = catch(:error) {
251
+ subject.call(
252
+ 'PATH_INFO' => '/info',
253
+ 'REQUEST_METHOD' => method,
254
+ 'CONTENT_TYPE' => content_type,
255
+ 'rack.input' => io,
256
+ 'CONTENT_LENGTH' => io.length
257
+ )
258
+ }
259
+ expect(error[:status]).to eq(415)
260
+ expect(error[:message]).to eq("The provided content-type 'application/atom+xml' is not supported.")
261
+ end
262
+ end
263
+ end
264
+
265
+ context 'when body is nil' do
266
+ let(:io) { double }
267
+ before do
268
+ allow(io).to receive_message_chain(:rewind, :read).and_return(nil)
269
+ end
270
+
271
+ it 'does not read and parse the body' do
272
+ expect(subject).not_to receive(:read_rack_input)
273
+ subject.call(
274
+ 'PATH_INFO' => '/info',
275
+ 'REQUEST_METHOD' => method,
276
+ 'CONTENT_TYPE' => 'application/json',
277
+ 'rack.input' => io,
278
+ 'CONTENT_LENGTH' => 0
279
+ )
280
+ end
281
+ end
282
+
283
+ context 'when body is empty' do
284
+ let(:io) { double }
285
+ before do
286
+ allow(io).to receive_message_chain(:rewind, :read).and_return('')
287
+ end
288
+
289
+ it 'does not read and parse the body' do
290
+ expect(subject).not_to receive(:read_rack_input)
291
+ subject.call(
292
+ 'PATH_INFO' => '/info',
293
+ 'REQUEST_METHOD' => method,
294
+ 'CONTENT_TYPE' => 'application/json',
295
+ 'rack.input' => io,
296
+ 'CONTENT_LENGTH' => 0
297
+ )
298
+ end
299
+ end
300
+
227
301
  ['application/json', 'application/json; charset=utf-8'].each do |content_type|
228
302
  context content_type do
229
303
  it "parses the body from #{method} and copies values into rack.request.form_hash" do
@@ -479,6 +479,24 @@ describe Grape::Validations::ParamsScope do
479
479
  end.to_not raise_error
480
480
  end
481
481
 
482
+ it 'allows aliasing of dependent parameters' do
483
+ subject.params do
484
+ optional :a
485
+ given :a do
486
+ requires :b, as: :c
487
+ end
488
+ end
489
+
490
+ subject.get('/multiple') { declared(params).to_json }
491
+
492
+ get '/multiple', a: 'a', b: 'b'
493
+
494
+ body = JSON.parse(last_response.body)
495
+
496
+ expect(body.keys).to include('c')
497
+ expect(body.keys).to_not include('b')
498
+ end
499
+
482
500
  it 'does not validate nested requires when given is false' do
483
501
  subject.params do
484
502
  requires :a, type: String, allow_blank: false, values: %w[x y z]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Bleigh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-23 00:00:00.000000000 Z
11
+ date: 2018-08-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -250,7 +250,8 @@ files:
250
250
  - lib/grape/validations/validators/regexp.rb
251
251
  - lib/grape/validations/validators/values.rb
252
252
  - lib/grape/version.rb
253
- - pkg/grape-1.0.0.gem
253
+ - pkg/grape-0.17.0.gem
254
+ - pkg/grape-0.19.0.gem
254
255
  - spec/grape/api/custom_validations_spec.rb
255
256
  - spec/grape/api/deeply_included_options_spec.rb
256
257
  - spec/grape/api/inherited_helpers_spec.rb
@@ -368,7 +369,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
368
369
  version: '0'
369
370
  requirements: []
370
371
  rubyforge_project:
371
- rubygems_version: 2.6.12
372
+ rubygems_version: 2.7.6
372
373
  signing_key:
373
374
  specification_version: 4
374
375
  summary: A simple Ruby framework for building REST-like APIs.
Binary file