grape 0.11.0 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of grape might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +23 -80
- data/.travis.yml +1 -1
- data/CHANGELOG.md +27 -0
- data/Gemfile +1 -1
- data/Guardfile +1 -1
- data/LICENSE +1 -1
- data/README.md +131 -30
- data/Rakefile +1 -1
- data/UPGRADING.md +110 -1
- data/gemfiles/rails_3.gemfile +1 -1
- data/gemfiles/rails_4.gemfile +1 -1
- data/grape.gemspec +4 -4
- data/lib/grape.rb +92 -62
- data/lib/grape/api.rb +10 -10
- data/lib/grape/cookies.rb +1 -1
- data/lib/grape/dsl/configuration.rb +7 -7
- data/lib/grape/dsl/helpers.rb +3 -3
- data/lib/grape/dsl/inside_route.rb +50 -21
- data/lib/grape/dsl/parameters.rb +25 -6
- data/lib/grape/dsl/request_response.rb +1 -1
- data/lib/grape/dsl/routing.rb +11 -10
- data/lib/grape/dsl/settings.rb +1 -1
- data/lib/grape/endpoint.rb +21 -19
- data/lib/grape/error_formatter/json.rb +1 -1
- data/lib/grape/exceptions/base.rb +1 -1
- data/lib/grape/exceptions/validation.rb +1 -1
- data/lib/grape/exceptions/validation_errors.rb +2 -2
- data/lib/grape/formatter/base.rb +1 -1
- data/lib/grape/formatter/json.rb +1 -1
- data/lib/grape/formatter/serializable_hash.rb +4 -4
- data/lib/grape/formatter/txt.rb +1 -1
- data/lib/grape/formatter/xml.rb +1 -1
- data/lib/grape/http/headers.rb +27 -0
- data/lib/grape/http/request.rb +1 -1
- data/lib/grape/middleware/error.rb +10 -4
- data/lib/grape/middleware/formatter.rb +13 -9
- data/lib/grape/middleware/globals.rb +2 -1
- data/lib/grape/middleware/versioner/accept_version_header.rb +2 -2
- data/lib/grape/middleware/versioner/header.rb +4 -4
- data/lib/grape/middleware/versioner/param.rb +2 -2
- data/lib/grape/middleware/versioner/path.rb +1 -1
- data/lib/grape/namespace.rb +2 -1
- data/lib/grape/parser/json.rb +1 -1
- data/lib/grape/parser/xml.rb +1 -1
- data/lib/grape/path.rb +3 -3
- data/lib/grape/presenters/presenter.rb +9 -0
- data/lib/grape/validations/params_scope.rb +3 -3
- data/lib/grape/validations/validators/allow_blank.rb +1 -1
- data/lib/grape/validations/validators/coerce.rb +6 -5
- data/lib/grape/validations/validators/default.rb +2 -2
- data/lib/grape/validations/validators/multiple_params_base.rb +1 -0
- data/lib/grape/validations/validators/regexp.rb +1 -1
- data/lib/grape/version.rb +1 -1
- data/spec/grape/api/custom_validations_spec.rb +47 -0
- data/spec/grape/api/deeply_included_options_spec.rb +56 -0
- data/spec/grape/api_spec.rb +64 -42
- data/spec/grape/dsl/configuration_spec.rb +2 -2
- data/spec/grape/dsl/helpers_spec.rb +1 -1
- data/spec/grape/dsl/inside_route_spec.rb +75 -19
- data/spec/grape/dsl/parameters_spec.rb +59 -10
- data/spec/grape/dsl/request_response_spec.rb +62 -2
- data/spec/grape/dsl/routing_spec.rb +116 -18
- data/spec/grape/endpoint_spec.rb +57 -5
- data/spec/grape/entity_spec.rb +1 -1
- data/spec/grape/exceptions/body_parse_errors_spec.rb +5 -5
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +32 -32
- data/spec/grape/exceptions/validation_errors_spec.rb +1 -1
- data/spec/grape/integration/rack_spec.rb +4 -3
- data/spec/grape/middleware/auth/strategies_spec.rb +2 -2
- data/spec/grape/middleware/base_spec.rb +2 -2
- data/spec/grape/middleware/error_spec.rb +1 -1
- data/spec/grape/middleware/exception_spec.rb +5 -5
- data/spec/grape/middleware/formatter_spec.rb +10 -10
- data/spec/grape/middleware/globals_spec.rb +27 -0
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +1 -1
- data/spec/grape/middleware/versioner/header_spec.rb +1 -1
- data/spec/grape/middleware/versioner/param_spec.rb +1 -1
- data/spec/grape/middleware/versioner/path_spec.rb +1 -1
- data/spec/grape/path_spec.rb +6 -4
- data/spec/grape/presenters/presenter_spec.rb +70 -0
- data/spec/grape/util/inheritable_values_spec.rb +1 -1
- data/spec/grape/util/stackable_values_spec.rb +1 -1
- data/spec/grape/util/strict_hash_configuration_spec.rb +1 -1
- data/spec/grape/validations/params_scope_spec.rb +64 -0
- data/spec/grape/validations/validators/allow_blank_spec.rb +10 -0
- data/spec/grape/validations/validators/coerce_spec.rb +48 -18
- data/spec/grape/validations/validators/default_spec.rb +110 -20
- data/spec/grape/validations/validators/presence_spec.rb +41 -3
- data/spec/grape/validations/validators/regexp_spec.rb +7 -2
- data/spec/grape/validations_spec.rb +20 -1
- data/spec/support/file_streamer.rb +11 -0
- data/spec/support/versioned_helpers.rb +1 -1
- metadata +14 -2
data/Rakefile
CHANGED
@@ -52,7 +52,7 @@ begin
|
|
52
52
|
end
|
53
53
|
|
54
54
|
desc 'Generate and publish YARD docs to GitHub pages.'
|
55
|
-
task :
|
55
|
+
task publish: ['doc:pages:checkout', 'doc:pages'] do
|
56
56
|
Dir.chdir(File.dirname(__FILE__) + '/../grape.doc') do
|
57
57
|
system('git checkout gh-pages')
|
58
58
|
system('git add .')
|
data/UPGRADING.md
CHANGED
@@ -1,9 +1,118 @@
|
|
1
1
|
Upgrading Grape
|
2
2
|
===============
|
3
3
|
|
4
|
+
### Upgrading to >= 0.12.0
|
5
|
+
|
6
|
+
#### Changes in middleware
|
7
|
+
|
8
|
+
The Rack response object is no longer converted to an array by the formatter, enabling streaming. If your custom middleware is accessing `@app_response`, update it to expect a `Rack::Response` instance instead of an array.
|
9
|
+
|
10
|
+
For example,
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
class CacheBusterMiddleware < Grape::Middleware::Base
|
14
|
+
def after
|
15
|
+
@app_response[1]['Expires'] = Time.at(0).utc.to_s
|
16
|
+
@app_response
|
17
|
+
end
|
18
|
+
end
|
19
|
+
```
|
20
|
+
|
21
|
+
becomes
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
class CacheBusterMiddleware < Grape::Middleware::Base
|
25
|
+
def after
|
26
|
+
@app_response.headers['Expires'] = Time.at(0).utc.to_s
|
27
|
+
@app_response
|
28
|
+
end
|
29
|
+
end
|
30
|
+
```
|
31
|
+
|
32
|
+
See [#1029](https://github.com/intridea/grape/pull/1029) for more information.
|
33
|
+
|
34
|
+
#### Changes in present
|
35
|
+
|
36
|
+
Using `present` with objects that responded to `merge` would cause early evaluation of the represented object, with unexpected side-effects, such as missing parameters or environment within rendering code. Grape now only merges represented objects with a previously rendered body, usually when multiple `present` calls are made in the same route.
|
37
|
+
|
38
|
+
See [grape-with-roar#5](https://github.com/dblock/grape-with-roar/issues/5) and [#1023](https://github.com/intridea/grape/issues/1023).
|
39
|
+
|
40
|
+
#### Changes to regexp validator
|
41
|
+
|
42
|
+
Parameters with `nil` value will now pass `regexp` validation. To disallow `nil` value for an endpoint, add `allow_blank: false`.
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
params do
|
46
|
+
requires :email, allow_blank: false, regexp: /.+@.+/
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
See [#957](https://github.com/intridea/grape/pull/957) for more information.
|
51
|
+
|
52
|
+
#### Replace error_response with error! in rescue_from blocks
|
53
|
+
|
54
|
+
Note: `error_response` is being deprecated, not removed.
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
def error!(message, status = options[:default_status], headers = {}, backtrace = [])
|
58
|
+
headers = { 'Content-Type' => content_type }.merge(headers)
|
59
|
+
rack_response(format_message(message, backtrace), status, headers)
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
For example,
|
64
|
+
|
65
|
+
```
|
66
|
+
error_response({ message: { message: 'No such page.', id: 'missing_page' }, status: 404, headers: { 'Content-Type' => 'api/error' })
|
67
|
+
```
|
68
|
+
|
69
|
+
becomes
|
70
|
+
|
71
|
+
```
|
72
|
+
error!({ message: 'No such page.', id: 'missing_page' }, 404, { 'Content-Type' => 'api/error' })
|
73
|
+
```
|
74
|
+
|
75
|
+
`error!` also supports just passing a message. `error!('Server error.')` and `format: :json` returns the following JSON response
|
76
|
+
|
77
|
+
```
|
78
|
+
{ 'error': 'Server error. }
|
79
|
+
```
|
80
|
+
|
81
|
+
with a status code of 500 and a Content Type of text/error.
|
82
|
+
|
83
|
+
Optionally, also replace `Rack::Response.new` with `error!.`
|
84
|
+
The following are equivalent:
|
85
|
+
|
86
|
+
```
|
87
|
+
Rack::Response.new([ e.message ], 500, { "Content-type" => "text/error" }).finish
|
88
|
+
error!(e)
|
89
|
+
```
|
90
|
+
|
91
|
+
See [#889](https://github.com/intridea/grape/issues/889) for more information.
|
92
|
+
|
93
|
+
#### Changes to routes when using `format`
|
94
|
+
|
95
|
+
Version 0.10.0 has introduced a change via [#809](https://github.com/intridea/grape/pull/809) whereas routes no longer got file-type suffixes added if you declared a single API `format`. This has been reverted, it's now again possible to call API with proper suffix when single `format` is defined:
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
class API < Grape::API
|
99
|
+
format :json
|
100
|
+
|
101
|
+
get :hello do
|
102
|
+
{ hello: 'world' }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
```
|
106
|
+
|
107
|
+
Will respond with JSON to `/hello` **and** `/hello.json`.
|
108
|
+
|
109
|
+
Will respond with 404 to `/hello.xml`, `/hello.txt` etc.
|
110
|
+
|
111
|
+
See the [#1001](https://github.com/intridea/grape/pull/1001) and [#914](https://github.com/intridea/grape/issues/914) for more info.
|
112
|
+
|
4
113
|
### Upgrading to >= 0.11.0
|
5
114
|
|
6
|
-
#### Added Rack 1.6.0
|
115
|
+
#### Added Rack 1.6.0 support
|
7
116
|
|
8
117
|
Grape now supports, but doesn't require Rack 1.6.0. If you encounter an issue with parsing requests larger than 128KB, explictly require Rack 1.6.0 in your Gemfile.
|
9
118
|
|
data/gemfiles/rails_3.gemfile
CHANGED
data/gemfiles/rails_4.gemfile
CHANGED
data/grape.gemspec
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
$LOAD_PATH.push File.expand_path('../lib', __FILE__)
|
2
2
|
require 'grape/version'
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
@@ -8,8 +8,8 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.authors = ['Michael Bleigh']
|
9
9
|
s.email = ['michael@intridea.com']
|
10
10
|
s.homepage = 'https://github.com/intridea/grape'
|
11
|
-
s.summary =
|
12
|
-
s.description =
|
11
|
+
s.summary = 'A simple Ruby framework for building REST-like APIs.'
|
12
|
+
s.description = 'A Ruby framework for rapid API development with great conventions.'
|
13
13
|
s.license = 'MIT'
|
14
14
|
|
15
15
|
s.rubyforge_project = 'grape'
|
@@ -38,6 +38,6 @@ Gem::Specification.new do |s|
|
|
38
38
|
|
39
39
|
s.files = `git ls-files`.split("\n")
|
40
40
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
41
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
41
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
42
42
|
s.require_paths = ['lib']
|
43
43
|
end
|
data/lib/grape.rb
CHANGED
@@ -20,6 +20,7 @@ require 'active_support/ordered_hash'
|
|
20
20
|
require 'active_support/core_ext/object/conversions'
|
21
21
|
require 'active_support/core_ext/array/extract_options'
|
22
22
|
require 'active_support/core_ext/hash/deep_merge'
|
23
|
+
require 'active_support/dependencies/autoload'
|
23
24
|
require 'grape/util/content_types'
|
24
25
|
require 'multi_json'
|
25
26
|
require 'multi_xml'
|
@@ -30,102 +31,131 @@ require 'thread'
|
|
30
31
|
I18n.load_path << File.expand_path('../grape/locale/en.yml', __FILE__)
|
31
32
|
|
32
33
|
module Grape
|
33
|
-
|
34
|
-
autoload :Endpoint, 'grape/endpoint'
|
34
|
+
extend ActiveSupport::Autoload
|
35
35
|
|
36
|
-
|
37
|
-
|
36
|
+
eager_autoload do
|
37
|
+
autoload :API
|
38
|
+
autoload :Endpoint
|
38
39
|
|
39
|
-
|
40
|
+
autoload :Route
|
41
|
+
autoload :Namespace
|
40
42
|
|
41
|
-
|
42
|
-
|
43
|
-
|
43
|
+
autoload :Path
|
44
|
+
|
45
|
+
autoload :Cookies
|
46
|
+
autoload :Validations
|
47
|
+
autoload :Request, 'grape/http/request'
|
48
|
+
end
|
49
|
+
|
50
|
+
module Http
|
51
|
+
extend ActiveSupport::Autoload
|
52
|
+
eager_autoload do
|
53
|
+
autoload :Headers
|
54
|
+
end
|
55
|
+
end
|
44
56
|
|
45
57
|
module Exceptions
|
46
|
-
|
47
|
-
autoload :
|
48
|
-
autoload :
|
49
|
-
autoload :
|
50
|
-
autoload :
|
51
|
-
autoload :
|
52
|
-
autoload :
|
53
|
-
autoload :
|
54
|
-
autoload :
|
55
|
-
autoload :
|
56
|
-
autoload :
|
57
|
-
autoload :
|
58
|
+
extend ActiveSupport::Autoload
|
59
|
+
autoload :Base
|
60
|
+
autoload :Validation
|
61
|
+
autoload :ValidationErrors
|
62
|
+
autoload :MissingVendorOption
|
63
|
+
autoload :MissingMimeType
|
64
|
+
autoload :MissingOption
|
65
|
+
autoload :InvalidFormatter
|
66
|
+
autoload :InvalidVersionerOption
|
67
|
+
autoload :UnknownValidator
|
68
|
+
autoload :UnknownOptions
|
69
|
+
autoload :InvalidWithOptionForRepresent
|
70
|
+
autoload :IncompatibleOptionValues
|
58
71
|
autoload :MissingGroupTypeError, 'grape/exceptions/missing_group_type'
|
59
72
|
autoload :UnsupportedGroupTypeError, 'grape/exceptions/unsupported_group_type'
|
60
|
-
autoload :InvalidMessageBody
|
61
|
-
autoload :InvalidAcceptHeader
|
73
|
+
autoload :InvalidMessageBody
|
74
|
+
autoload :InvalidAcceptHeader
|
62
75
|
end
|
63
76
|
|
64
77
|
module ErrorFormatter
|
65
|
-
|
66
|
-
autoload :
|
67
|
-
autoload :
|
68
|
-
autoload :
|
78
|
+
extend ActiveSupport::Autoload
|
79
|
+
autoload :Base
|
80
|
+
autoload :Json
|
81
|
+
autoload :Txt
|
82
|
+
autoload :Xml
|
69
83
|
end
|
70
84
|
|
71
85
|
module Formatter
|
72
|
-
|
73
|
-
autoload :
|
74
|
-
autoload :
|
75
|
-
autoload :
|
76
|
-
autoload :
|
86
|
+
extend ActiveSupport::Autoload
|
87
|
+
autoload :Base
|
88
|
+
autoload :Json
|
89
|
+
autoload :SerializableHash
|
90
|
+
autoload :Txt
|
91
|
+
autoload :Xml
|
77
92
|
end
|
78
93
|
|
79
94
|
module Parser
|
80
|
-
|
81
|
-
autoload :
|
82
|
-
autoload :
|
95
|
+
extend ActiveSupport::Autoload
|
96
|
+
autoload :Base
|
97
|
+
autoload :Json
|
98
|
+
autoload :Xml
|
83
99
|
end
|
84
100
|
|
85
101
|
module Middleware
|
86
|
-
|
87
|
-
autoload :
|
88
|
-
autoload :
|
89
|
-
autoload :
|
102
|
+
extend ActiveSupport::Autoload
|
103
|
+
autoload :Base
|
104
|
+
autoload :Versioner
|
105
|
+
autoload :Formatter
|
106
|
+
autoload :Error
|
107
|
+
autoload :Globals
|
90
108
|
|
91
109
|
module Auth
|
92
|
-
|
93
|
-
autoload :
|
94
|
-
autoload :
|
95
|
-
autoload :
|
110
|
+
extend ActiveSupport::Autoload
|
111
|
+
autoload :Base
|
112
|
+
autoload :DSL
|
113
|
+
autoload :StrategyInfo
|
114
|
+
autoload :Strategies
|
96
115
|
end
|
97
116
|
|
98
117
|
module Versioner
|
99
|
-
|
100
|
-
autoload :
|
101
|
-
autoload :
|
102
|
-
autoload :
|
118
|
+
extend ActiveSupport::Autoload
|
119
|
+
autoload :Path
|
120
|
+
autoload :Header
|
121
|
+
autoload :Param
|
122
|
+
autoload :AcceptVersionHeader
|
103
123
|
end
|
104
124
|
end
|
105
125
|
|
106
126
|
module Util
|
107
|
-
|
108
|
-
autoload :
|
109
|
-
autoload :
|
110
|
-
autoload :
|
127
|
+
extend ActiveSupport::Autoload
|
128
|
+
autoload :InheritableValues
|
129
|
+
autoload :StackableValues
|
130
|
+
autoload :InheritableSetting
|
131
|
+
autoload :StrictHashConfiguration
|
111
132
|
end
|
112
133
|
|
113
134
|
module DSL
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
135
|
+
extend ActiveSupport::Autoload
|
136
|
+
eager_autoload do
|
137
|
+
autoload :API
|
138
|
+
autoload :Callbacks
|
139
|
+
autoload :Settings
|
140
|
+
autoload :Configuration
|
141
|
+
autoload :InsideRoute
|
142
|
+
autoload :Helpers
|
143
|
+
autoload :Middleware
|
144
|
+
autoload :Parameters
|
145
|
+
autoload :RequestResponse
|
146
|
+
autoload :Routing
|
147
|
+
autoload :Validations
|
148
|
+
end
|
125
149
|
end
|
126
150
|
|
127
151
|
class API
|
128
|
-
|
152
|
+
extend ActiveSupport::Autoload
|
153
|
+
autoload :Helpers
|
154
|
+
end
|
155
|
+
|
156
|
+
module Presenters
|
157
|
+
extend ActiveSupport::Autoload
|
158
|
+
autoload :Presenter
|
129
159
|
end
|
130
160
|
end
|
131
161
|
|
data/lib/grape/api.rb
CHANGED
@@ -36,7 +36,7 @@ module Grape
|
|
36
36
|
# Create a scope without affecting the URL.
|
37
37
|
#
|
38
38
|
# @param name [Symbol] Purely placebo, just allows to name the scope to make the code more readable.
|
39
|
-
def scope(
|
39
|
+
def scope(_name = nil, &block)
|
40
40
|
within_namespace do
|
41
41
|
nest(block)
|
42
42
|
end
|
@@ -95,9 +95,9 @@ module Grape
|
|
95
95
|
end
|
96
96
|
|
97
97
|
def call(env)
|
98
|
-
|
99
|
-
|
100
|
-
|
98
|
+
result = @route_set.call(env)
|
99
|
+
result[1].delete(Grape::Http::Headers::X_CASCADE) unless cascade?
|
100
|
+
result
|
101
101
|
end
|
102
102
|
|
103
103
|
# Some requests may return a HTTP 404 error if grape cannot find a matching
|
@@ -142,12 +142,12 @@ module Grape
|
|
142
142
|
methods_per_path.each do |path, methods|
|
143
143
|
allowed_methods = methods.dup
|
144
144
|
unless self.class.namespace_inheritable(:do_not_route_head)
|
145
|
-
allowed_methods |= [
|
145
|
+
allowed_methods |= [Grape::Http::Headers::HEAD] if allowed_methods.include?(Grape::Http::Headers::GET)
|
146
146
|
end
|
147
147
|
|
148
|
-
allow_header = ([
|
148
|
+
allow_header = ([Grape::Http::Headers::OPTIONS] | allowed_methods).join(', ')
|
149
149
|
unless self.class.namespace_inheritable(:do_not_route_options)
|
150
|
-
unless allowed_methods.include?(
|
150
|
+
unless allowed_methods.include?(Grape::Http::Headers::OPTIONS)
|
151
151
|
self.class.options(path, {}) do
|
152
152
|
header 'Allow', allow_header
|
153
153
|
status 204
|
@@ -157,7 +157,7 @@ module Grape
|
|
157
157
|
end
|
158
158
|
|
159
159
|
not_allowed_methods = %w(GET PUT POST DELETE PATCH HEAD) - allowed_methods
|
160
|
-
not_allowed_methods <<
|
160
|
+
not_allowed_methods << Grape::Http::Headers::OPTIONS if self.class.namespace_inheritable(:do_not_route_options)
|
161
161
|
self.class.route(not_allowed_methods, path) do
|
162
162
|
header 'Allow', allow_header
|
163
163
|
status 405
|
@@ -168,7 +168,7 @@ module Grape
|
|
168
168
|
end
|
169
169
|
end
|
170
170
|
|
171
|
-
def without_versioning(&
|
171
|
+
def without_versioning(&_block)
|
172
172
|
old_version = self.class.namespace_inheritable(:version)
|
173
173
|
old_version_options = self.class.namespace_inheritable(:version_options)
|
174
174
|
|
@@ -181,7 +181,7 @@ module Grape
|
|
181
181
|
self.class.namespace_inheritable(:version_options, old_version_options)
|
182
182
|
end
|
183
183
|
|
184
|
-
def without_root_prefix(&
|
184
|
+
def without_root_prefix(&_block)
|
185
185
|
old_prefix = self.class.namespace_inheritable(:root_prefix)
|
186
186
|
|
187
187
|
self.class.namespace_inheritable_to_nil(:root_prefix)
|
data/lib/grape/cookies.rb
CHANGED
@@ -12,7 +12,7 @@ module Grape
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def write(header)
|
15
|
-
@cookies.select { |key,
|
15
|
+
@cookies.select { |key, _value| @send_cookies[key] == true }.each do |name, value|
|
16
16
|
cookie_value = value.is_a?(Hash) ? value : { value: value }
|
17
17
|
Rack::Utils.set_cookie_header! header, name, cookie_value
|
18
18
|
end
|