hanami-controller 1.3.3 → 2.0.0.alpha4
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/CHANGELOG.md +82 -0
- data/LICENSE.md +1 -1
- data/README.md +299 -537
- data/hanami-controller.gemspec +4 -3
- data/lib/hanami/action/application_action.rb +131 -0
- data/lib/hanami/action/application_configuration/content_security_policy.rb +118 -0
- data/lib/hanami/action/application_configuration/cookies.rb +29 -0
- data/lib/hanami/action/application_configuration/sessions.rb +46 -0
- data/lib/hanami/action/application_configuration.rb +90 -0
- data/lib/hanami/action/base_params.rb +2 -2
- data/lib/hanami/action/cache/cache_control.rb +4 -4
- data/lib/hanami/action/cache/conditional_get.rb +3 -1
- data/lib/hanami/action/cache/directives.rb +1 -1
- data/lib/hanami/action/cache/expires.rb +3 -3
- data/lib/hanami/action/cache.rb +1 -139
- data/lib/hanami/action/configuration.rb +428 -0
- data/lib/hanami/action/cookie_jar.rb +3 -3
- data/lib/hanami/action/cookies.rb +3 -62
- data/lib/hanami/action/csrf_protection.rb +214 -0
- data/lib/hanami/action/flash.rb +102 -207
- data/lib/hanami/action/glue.rb +5 -31
- data/lib/hanami/action/halt.rb +12 -0
- data/lib/hanami/action/mime.rb +78 -485
- data/lib/hanami/action/params.rb +2 -2
- data/lib/hanami/action/rack/file.rb +1 -1
- data/lib/hanami/action/request.rb +30 -20
- data/lib/hanami/action/response.rb +193 -0
- data/lib/hanami/action/session.rb +11 -128
- data/lib/hanami/action/standalone_action.rb +578 -0
- data/lib/hanami/action/validatable.rb +1 -1
- data/lib/hanami/action/view_name_inferrer.rb +46 -0
- data/lib/hanami/action.rb +129 -73
- data/lib/hanami/controller/version.rb +1 -1
- data/lib/hanami/controller.rb +0 -227
- data/lib/hanami/http/status.rb +2 -2
- metadata +44 -26
- data/lib/hanami/action/callable.rb +0 -92
- data/lib/hanami/action/callbacks.rb +0 -214
- data/lib/hanami/action/configurable.rb +0 -50
- data/lib/hanami/action/exposable/guard.rb +0 -104
- data/lib/hanami/action/exposable.rb +0 -126
- data/lib/hanami/action/head.rb +0 -121
- data/lib/hanami/action/rack/callable.rb +0 -47
- data/lib/hanami/action/rack/errors.rb +0 -53
- data/lib/hanami/action/rack.rb +0 -411
- data/lib/hanami/action/redirect.rb +0 -59
- data/lib/hanami/action/throwable.rb +0 -169
- data/lib/hanami/controller/configuration.rb +0 -763
- data/lib/hanami-controller.rb +0 -1
@@ -1,47 +0,0 @@
|
|
1
|
-
module Hanami
|
2
|
-
module Action
|
3
|
-
module Rack
|
4
|
-
module Callable
|
5
|
-
# Callable module for actions. With this module, actions with middlewares
|
6
|
-
# will be able to work with rack builder.
|
7
|
-
#
|
8
|
-
# @param env [Hash] the full Rack env or the params. This value may vary,
|
9
|
-
# see the examples below.
|
10
|
-
#
|
11
|
-
# @since 0.4.0
|
12
|
-
# @api private
|
13
|
-
#
|
14
|
-
# @see Hanami::Action::Rack::ClassMethods#rack_builder
|
15
|
-
# @see Hanami::Action::Rack::ClassMethods#use
|
16
|
-
#
|
17
|
-
# @example
|
18
|
-
# require 'hanami/controller'
|
19
|
-
#
|
20
|
-
# class MyMiddleware
|
21
|
-
# def initialize(app)
|
22
|
-
# @app = app
|
23
|
-
# end
|
24
|
-
#
|
25
|
-
# def call(env)
|
26
|
-
# #...
|
27
|
-
# end
|
28
|
-
# end
|
29
|
-
#
|
30
|
-
# class Show
|
31
|
-
# include Hanami::Action
|
32
|
-
# use MyMiddleware
|
33
|
-
#
|
34
|
-
# def call(params)
|
35
|
-
# # ...
|
36
|
-
# puts params # => { id: 23 } extracted from Rack env
|
37
|
-
# end
|
38
|
-
# end
|
39
|
-
#
|
40
|
-
# Show.respond_to?(:call) # => true
|
41
|
-
def call(env)
|
42
|
-
rack_builder.call(env)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Hanami
|
4
|
-
module Action
|
5
|
-
module Rack
|
6
|
-
# This module provides method to set exceptions to Rack env:
|
7
|
-
#
|
8
|
-
# * `rack.errors` - IO for errors, as requested by Rack SPEC
|
9
|
-
# * `rack.exception` - De-facto standard for Ruby exception tracking SaaS
|
10
|
-
#
|
11
|
-
# @see http://www.rubydoc.info/github/rack/rack/file/SPEC#The_Error_Stream
|
12
|
-
# @see https://github.com/hanami/controller/issues/133
|
13
|
-
#
|
14
|
-
# @since 1.3.3
|
15
|
-
# @api private
|
16
|
-
module Errors
|
17
|
-
# @since 1.3.3
|
18
|
-
# @api private
|
19
|
-
RACK_ERRORS = "rack.errors"
|
20
|
-
|
21
|
-
# @since 1.3.3
|
22
|
-
# @api private
|
23
|
-
RACK_EXCEPTION = "rack.exception"
|
24
|
-
|
25
|
-
# Set exception in Rack env
|
26
|
-
#
|
27
|
-
# @param env [Hash] the Rack environment
|
28
|
-
# @param exception [Exception] the exception to set
|
29
|
-
#
|
30
|
-
# @since 1.3.3
|
31
|
-
# @api private
|
32
|
-
def self.set(env, exception)
|
33
|
-
env[RACK_EXCEPTION] = exception
|
34
|
-
|
35
|
-
return unless errors = env[RACK_ERRORS] # rubocop:disable Lint/AssignmentInCondition
|
36
|
-
|
37
|
-
errors.write(_dump_exception(exception))
|
38
|
-
errors.flush
|
39
|
-
end
|
40
|
-
|
41
|
-
# Format exception info with name and backtrace
|
42
|
-
#
|
43
|
-
# @param exception [Exception]
|
44
|
-
#
|
45
|
-
# @since 1.3.3
|
46
|
-
# @api private
|
47
|
-
def self._dump_exception(exception)
|
48
|
-
[[exception.class, exception.message].compact.join(": "), *exception.backtrace].join("\n\t")
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
data/lib/hanami/action/rack.rb
DELETED
@@ -1,411 +0,0 @@
|
|
1
|
-
require 'securerandom'
|
2
|
-
require 'hanami/action/request'
|
3
|
-
require 'hanami/action/base_params'
|
4
|
-
require 'hanami/action/rack/callable'
|
5
|
-
require 'hanami/action/rack/file'
|
6
|
-
require 'hanami/utils/deprecation'
|
7
|
-
|
8
|
-
module Hanami
|
9
|
-
module Action
|
10
|
-
# Rack integration API
|
11
|
-
#
|
12
|
-
# @since 0.1.0
|
13
|
-
module Rack
|
14
|
-
# Rack SPEC response code
|
15
|
-
#
|
16
|
-
# @since 1.0.0
|
17
|
-
# @api private
|
18
|
-
RESPONSE_CODE = 0
|
19
|
-
|
20
|
-
# Rack SPEC response headers
|
21
|
-
#
|
22
|
-
# @since 1.0.0
|
23
|
-
# @api private
|
24
|
-
RESPONSE_HEADERS = 1
|
25
|
-
|
26
|
-
# Rack SPEC response body
|
27
|
-
#
|
28
|
-
# @since 1.0.0
|
29
|
-
# @api private
|
30
|
-
RESPONSE_BODY = 2
|
31
|
-
|
32
|
-
# The default HTTP response code
|
33
|
-
#
|
34
|
-
# @since 0.1.0
|
35
|
-
# @api private
|
36
|
-
DEFAULT_RESPONSE_CODE = 200
|
37
|
-
|
38
|
-
# Not Found
|
39
|
-
#
|
40
|
-
# @since 1.0.0
|
41
|
-
# @api private
|
42
|
-
NOT_FOUND = 404
|
43
|
-
|
44
|
-
# The default Rack response body
|
45
|
-
#
|
46
|
-
# @since 0.1.0
|
47
|
-
# @api private
|
48
|
-
DEFAULT_RESPONSE_BODY = []
|
49
|
-
|
50
|
-
# The default HTTP Request ID length
|
51
|
-
#
|
52
|
-
# @since 0.3.0
|
53
|
-
# @api private
|
54
|
-
#
|
55
|
-
# @see Hanami::Action::Rack#request_id
|
56
|
-
DEFAULT_REQUEST_ID_LENGTH = 16
|
57
|
-
|
58
|
-
# The request method
|
59
|
-
#
|
60
|
-
# @since 0.3.2
|
61
|
-
# @api private
|
62
|
-
REQUEST_METHOD = 'REQUEST_METHOD'.freeze
|
63
|
-
|
64
|
-
# The Content-Length HTTP header
|
65
|
-
#
|
66
|
-
# @since 1.0.0
|
67
|
-
# @api private
|
68
|
-
CONTENT_LENGTH = 'Content-Length'.freeze
|
69
|
-
|
70
|
-
# The non-standard HTTP header to pass the control over when a resource
|
71
|
-
# cannot be found by the current endpoint
|
72
|
-
#
|
73
|
-
# @since 1.0.0
|
74
|
-
# @api private
|
75
|
-
X_CASCADE = 'X-Cascade'.freeze
|
76
|
-
|
77
|
-
# HEAD request
|
78
|
-
#
|
79
|
-
# @since 0.3.2
|
80
|
-
# @api private
|
81
|
-
HEAD = 'HEAD'.freeze
|
82
|
-
|
83
|
-
# The key that returns router parsed body from the Rack env
|
84
|
-
ROUTER_PARSED_BODY = 'router.parsed_body'.freeze
|
85
|
-
|
86
|
-
# This is the root directory for `#unsafe_send_file`
|
87
|
-
#
|
88
|
-
# @since 1.3.3
|
89
|
-
# @api private
|
90
|
-
#
|
91
|
-
# @see #unsafe_send_file
|
92
|
-
FILE_SYSTEM_ROOT = Pathname.new("/").freeze
|
93
|
-
|
94
|
-
# Override Ruby's hook for modules.
|
95
|
-
# It includes basic Hanami::Action modules to the given class.
|
96
|
-
#
|
97
|
-
# @param base [Class] the target action
|
98
|
-
#
|
99
|
-
# @since 0.1.0
|
100
|
-
# @api private
|
101
|
-
#
|
102
|
-
# @see http://www.ruby-doc.org/core-2.1.2/Module.html#method-i-included
|
103
|
-
def self.included(base)
|
104
|
-
base.class_eval do
|
105
|
-
extend ClassMethods
|
106
|
-
prepend InstanceMethods
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
# @api private
|
111
|
-
module ClassMethods
|
112
|
-
# Build rack builder
|
113
|
-
#
|
114
|
-
# @return [Rack::Builder]
|
115
|
-
# @api private
|
116
|
-
def rack_builder
|
117
|
-
@rack_builder ||= begin
|
118
|
-
extend Hanami::Action::Rack::Callable
|
119
|
-
rack_builder = ::Rack::Builder.new
|
120
|
-
rack_builder.run ->(env) { self.new.call(env) }
|
121
|
-
rack_builder
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
# Use a Rack middleware
|
126
|
-
#
|
127
|
-
# The middleware will be used as it is.
|
128
|
-
#
|
129
|
-
# At the runtime, the middleware be invoked with the raw Rack env.
|
130
|
-
#
|
131
|
-
# Multiple middlewares can be employed, just by using multiple times
|
132
|
-
# this method.
|
133
|
-
#
|
134
|
-
# @param middleware [#call] A Rack middleware
|
135
|
-
# @param args [Array] Array arguments for middleware
|
136
|
-
#
|
137
|
-
# @since 0.2.0
|
138
|
-
#
|
139
|
-
# @see Hanami::Action::Callbacks::ClassMethods#before
|
140
|
-
#
|
141
|
-
# @example Middleware
|
142
|
-
# require 'hanami/controller'
|
143
|
-
#
|
144
|
-
# module Sessions
|
145
|
-
# class Create
|
146
|
-
# include Hanami::Action
|
147
|
-
# use OmniAuth
|
148
|
-
#
|
149
|
-
# def call(params)
|
150
|
-
# # ...
|
151
|
-
# end
|
152
|
-
# end
|
153
|
-
# end
|
154
|
-
def use(middleware, *args, &block)
|
155
|
-
rack_builder.use middleware, *args, &block
|
156
|
-
end
|
157
|
-
|
158
|
-
# Returns the class which defines the params
|
159
|
-
#
|
160
|
-
# Returns the class which has been provided to define the
|
161
|
-
# params. By default this will be Hanami::Action::Params.
|
162
|
-
#
|
163
|
-
# @return [Class] A params class (when whitelisted) or
|
164
|
-
# Hanami::Action::Params
|
165
|
-
#
|
166
|
-
# @api private
|
167
|
-
# @since 0.7.0
|
168
|
-
def params_class
|
169
|
-
@params_class ||= BaseParams
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
# @since 0.7.0
|
174
|
-
# @api private
|
175
|
-
module InstanceMethods
|
176
|
-
# @since 0.7.0
|
177
|
-
# @api private
|
178
|
-
def initialize(*)
|
179
|
-
super
|
180
|
-
@_status = nil
|
181
|
-
@_body = nil
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
protected
|
186
|
-
# Gets the headers from the response
|
187
|
-
#
|
188
|
-
# @return [Hash] the HTTP headers from the response
|
189
|
-
#
|
190
|
-
# @since 0.1.0
|
191
|
-
#
|
192
|
-
# @example
|
193
|
-
# require 'hanami/controller'
|
194
|
-
#
|
195
|
-
# class Show
|
196
|
-
# include Hanami::Action
|
197
|
-
#
|
198
|
-
# def call(params)
|
199
|
-
# # ...
|
200
|
-
# self.headers # => { ... }
|
201
|
-
# self.headers.merge!({'X-Custom' => 'OK'})
|
202
|
-
# end
|
203
|
-
# end
|
204
|
-
def headers
|
205
|
-
@headers
|
206
|
-
end
|
207
|
-
|
208
|
-
# Returns a serialized Rack response (Array), according to the current
|
209
|
-
# status code, headers, and body.
|
210
|
-
#
|
211
|
-
# @return [Array] the serialized response
|
212
|
-
#
|
213
|
-
# @since 0.1.0
|
214
|
-
# @api private
|
215
|
-
#
|
216
|
-
# @see Hanami::Action::Rack::DEFAULT_RESPONSE_CODE
|
217
|
-
# @see Hanami::Action::Rack::DEFAULT_RESPONSE_BODY
|
218
|
-
# @see Hanami::Action::Rack#status=
|
219
|
-
# @see Hanami::Action::Rack#headers
|
220
|
-
# @see Hanami::Action::Rack#body=
|
221
|
-
def response
|
222
|
-
[ @_status || DEFAULT_RESPONSE_CODE, headers, @_body || DEFAULT_RESPONSE_BODY.dup ]
|
223
|
-
end
|
224
|
-
|
225
|
-
# Calculates an unique ID for the current request
|
226
|
-
#
|
227
|
-
# @return [String] The unique ID
|
228
|
-
#
|
229
|
-
# @since 0.3.0
|
230
|
-
def request_id
|
231
|
-
# FIXME make this number configurable and document the probabilities of clashes
|
232
|
-
@request_id ||= SecureRandom.hex(DEFAULT_REQUEST_ID_LENGTH)
|
233
|
-
end
|
234
|
-
|
235
|
-
# Returns a Hanami specialized rack request
|
236
|
-
#
|
237
|
-
# @return [Hanami::Action::Request] The request
|
238
|
-
#
|
239
|
-
# @since 0.3.1
|
240
|
-
#
|
241
|
-
# @example
|
242
|
-
# require 'hanami/controller'
|
243
|
-
#
|
244
|
-
# class Create
|
245
|
-
# include Hanami::Action
|
246
|
-
#
|
247
|
-
# def call(params)
|
248
|
-
# ip = request.ip
|
249
|
-
# secure = request.ssl?
|
250
|
-
# end
|
251
|
-
# end
|
252
|
-
def request
|
253
|
-
@request ||= ::Hanami::Action::Request.new(@_env)
|
254
|
-
end
|
255
|
-
|
256
|
-
# Return parsed request body
|
257
|
-
#
|
258
|
-
# @deprecated
|
259
|
-
def parsed_request_body
|
260
|
-
Hanami::Utils::Deprecation.new('#parsed_request_body is deprecated and it will be removed in future versions')
|
261
|
-
@_env.fetch(ROUTER_PARSED_BODY, nil)
|
262
|
-
end
|
263
|
-
|
264
|
-
private
|
265
|
-
|
266
|
-
# Sets the HTTP status code for the response
|
267
|
-
#
|
268
|
-
# @param status [Fixnum] an HTTP status code
|
269
|
-
# @return [void]
|
270
|
-
#
|
271
|
-
# @since 0.1.0
|
272
|
-
#
|
273
|
-
# @example
|
274
|
-
# require 'hanami/controller'
|
275
|
-
#
|
276
|
-
# class Create
|
277
|
-
# include Hanami::Action
|
278
|
-
#
|
279
|
-
# def call(params)
|
280
|
-
# # ...
|
281
|
-
# self.status = 201
|
282
|
-
# end
|
283
|
-
# end
|
284
|
-
def status=(status)
|
285
|
-
@_status = status
|
286
|
-
end
|
287
|
-
|
288
|
-
# Sets the body of the response
|
289
|
-
#
|
290
|
-
# @param body [String] the body of the response
|
291
|
-
# @return [void]
|
292
|
-
#
|
293
|
-
# @since 0.1.0
|
294
|
-
#
|
295
|
-
# @example
|
296
|
-
# require 'hanami/controller'
|
297
|
-
#
|
298
|
-
# class Show
|
299
|
-
# include Hanami::Action
|
300
|
-
#
|
301
|
-
# def call(params)
|
302
|
-
# # ...
|
303
|
-
# self.body = 'Hi!'
|
304
|
-
# end
|
305
|
-
# end
|
306
|
-
def body=(body)
|
307
|
-
body = Array(body) unless body.respond_to?(:each)
|
308
|
-
@_body = body
|
309
|
-
end
|
310
|
-
|
311
|
-
# Send a file as response.
|
312
|
-
# <tt>This method only sends files from the public directory</tt>
|
313
|
-
#
|
314
|
-
# It automatically handle the following cases:
|
315
|
-
#
|
316
|
-
# * <tt>Content-Type</tt> and <tt>Content-Length</tt>
|
317
|
-
# * File Not found (returns a 404)
|
318
|
-
# * Conditional GET (via <tt>If-Modified-Since</tt> header)
|
319
|
-
# * Range requests (via <tt>Range</tt> header)
|
320
|
-
#
|
321
|
-
# @param path [String, Pathname] the body of the response
|
322
|
-
# @return [void]
|
323
|
-
#
|
324
|
-
# @since 0.4.3
|
325
|
-
#
|
326
|
-
# @example
|
327
|
-
# require 'hanami/controller'
|
328
|
-
#
|
329
|
-
# class Show
|
330
|
-
# include Hanami::Action
|
331
|
-
#
|
332
|
-
# def call(params)
|
333
|
-
# # ...
|
334
|
-
# send_file Pathname.new('path/to/file')
|
335
|
-
# end
|
336
|
-
# end
|
337
|
-
def send_file(path)
|
338
|
-
_send_file(
|
339
|
-
File.new(path, self.class.configuration.public_directory).call(@_env)
|
340
|
-
)
|
341
|
-
end
|
342
|
-
|
343
|
-
# Send a file as response from anywhere in the file system.
|
344
|
-
#
|
345
|
-
# @see Hanami::Action::Rack#send_file
|
346
|
-
#
|
347
|
-
# @param path [String, Pathname] path to the file to be sent
|
348
|
-
# @return [void]
|
349
|
-
#
|
350
|
-
# @since 1.0.0
|
351
|
-
#
|
352
|
-
# @example
|
353
|
-
# require 'hanami/controller'
|
354
|
-
#
|
355
|
-
# class Show
|
356
|
-
# include Hanami::Action
|
357
|
-
#
|
358
|
-
# def call(params)
|
359
|
-
# # ...
|
360
|
-
# unsafe_send_file Pathname.new('/tmp/path/to/file')
|
361
|
-
# end
|
362
|
-
# end
|
363
|
-
def unsafe_send_file(path)
|
364
|
-
directory = if Pathname.new(path).relative?
|
365
|
-
self.class.configuration.root_directory
|
366
|
-
else
|
367
|
-
FILE_SYSTEM_ROOT
|
368
|
-
end
|
369
|
-
|
370
|
-
_send_file(
|
371
|
-
File.new(path, directory).call(@_env)
|
372
|
-
)
|
373
|
-
end
|
374
|
-
|
375
|
-
# Check if the current request is a HEAD
|
376
|
-
#
|
377
|
-
# @return [TrueClass,FalseClass] the result of the check
|
378
|
-
#
|
379
|
-
# @since 0.3.2
|
380
|
-
def head?
|
381
|
-
request_method == HEAD
|
382
|
-
end
|
383
|
-
|
384
|
-
# NOTE: <tt>Hanami::Action::CSRFProtection</tt> (<tt>hanamirb</tt> gem) depends on this.
|
385
|
-
#
|
386
|
-
# @api private
|
387
|
-
# @since 0.4.4
|
388
|
-
def request_method
|
389
|
-
@_env[REQUEST_METHOD]
|
390
|
-
end
|
391
|
-
|
392
|
-
# @since 1.0.0
|
393
|
-
# @api private
|
394
|
-
def _send_file(response)
|
395
|
-
headers.merge!(response[RESPONSE_HEADERS])
|
396
|
-
|
397
|
-
if response[RESPONSE_CODE] == NOT_FOUND
|
398
|
-
headers.delete(X_CASCADE)
|
399
|
-
headers.delete(CONTENT_LENGTH)
|
400
|
-
halt NOT_FOUND
|
401
|
-
else
|
402
|
-
# FIXME: this is a fix for https://github.com/hanami/controller/issues/240
|
403
|
-
# It's here to maintain the backward compat with 1.1, as we can't remove `#halt`
|
404
|
-
# We should review the workflow for 2.0, because I don't like callbacks to be referenced from here.
|
405
|
-
_run_after_callbacks(params)
|
406
|
-
halt response[RESPONSE_CODE], response[RESPONSE_BODY]
|
407
|
-
end
|
408
|
-
end
|
409
|
-
end
|
410
|
-
end
|
411
|
-
end
|
@@ -1,59 +0,0 @@
|
|
1
|
-
module Hanami
|
2
|
-
module Action
|
3
|
-
# HTTP redirect API
|
4
|
-
#
|
5
|
-
# @since 0.1.0
|
6
|
-
module Redirect
|
7
|
-
# The HTTP header for redirects
|
8
|
-
#
|
9
|
-
# @since 0.2.0
|
10
|
-
# @api private
|
11
|
-
LOCATION = 'Location'.freeze
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
# Redirect to the given URL and halt the request
|
16
|
-
#
|
17
|
-
# @param url [String] the destination URL
|
18
|
-
# @param status [Fixnum] the http code
|
19
|
-
#
|
20
|
-
# @since 0.1.0
|
21
|
-
#
|
22
|
-
# @see Hanami::Action::Throwable#halt
|
23
|
-
#
|
24
|
-
# @example With default status code (302)
|
25
|
-
# require 'hanami/controller'
|
26
|
-
#
|
27
|
-
# class Create
|
28
|
-
# include Hanami::Action
|
29
|
-
#
|
30
|
-
# def call(params)
|
31
|
-
# # ...
|
32
|
-
# redirect_to 'http://example.com/articles/23'
|
33
|
-
# end
|
34
|
-
# end
|
35
|
-
#
|
36
|
-
# action = Create.new
|
37
|
-
# action.call({}) # => [302, {'Location' => '/articles/23'}, '']
|
38
|
-
#
|
39
|
-
# @example With custom status code
|
40
|
-
# require 'hanami/controller'
|
41
|
-
#
|
42
|
-
# class Create
|
43
|
-
# include Hanami::Action
|
44
|
-
#
|
45
|
-
# def call(params)
|
46
|
-
# # ...
|
47
|
-
# redirect_to 'http://example.com/articles/23', status: 301
|
48
|
-
# end
|
49
|
-
# end
|
50
|
-
#
|
51
|
-
# action = Create.new
|
52
|
-
# action.call({}) # => [301, {'Location' => '/articles/23'}, '']
|
53
|
-
def redirect_to(url, status: 302)
|
54
|
-
headers[LOCATION] = ::String.new(url)
|
55
|
-
halt(status)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|