Module: Roda::RodaPlugins::Base::RequestMethods

Defined in:
lib/roda.rb

Overview

Instance methods for RodaRequest, mostly related to handling routing for the request.

Constant Summary collapse

PATH_INFO =
"PATH_INFO".freeze
SCRIPT_NAME =
"SCRIPT_NAME".freeze
REQUEST_METHOD =
"REQUEST_METHOD".freeze
EMPTY_STRING =
"".freeze
SLASH =
"/".freeze
COLON =
":".freeze
SEGMENT =
"([^\\/]+)".freeze
TERM_INSPECT =
"TERM".freeze
GET_REQUEST_METHOD =
'GET'.freeze
SESSION_KEY =
'rack.session'.freeze
TERM =
Object.new

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#capturesObject (readonly)

The current captures for the request. This gets modified as routing occurs.



361
362
363
# File 'lib/roda.rb', line 361

def captures
  @captures
end

#remaining_pathObject (readonly)

The current path to match requests against.



528
529
530
# File 'lib/roda.rb', line 528

def remaining_path
  @remaining_path
end

#scopeObject (readonly)

The Roda instance related to this request object. Useful if routing methods need access to the scope of the Roda route block.



365
366
367
# File 'lib/roda.rb', line 365

def scope
  @scope
end

Instance Method Details

#block_result(result) ⇒ Object

Handle match block return values. By default, if a string is given and the response is empty, use the string as the response body.



377
378
379
380
381
382
# File 'lib/roda.rb', line 377

def block_result(result)
  res = response
  if res.empty? && (body = block_result_body(result))
    res.write(body)
  end
end

#get(*args, &block) ⇒ Object

Match GET requests. If no arguments are provided, matches all GET requests, otherwise, matches only GET requests where the arguments given fully consume the path.



387
388
389
# File 'lib/roda.rb', line 387

def get(*args, &block)
  _verb(args, &block) if is_get?
end

#halt(res = response.finish) ⇒ Object

Immediately stop execution of the route block and return the given rack response array of status, headers, and body. If no argument is given, uses the current response.

r.halt [200, {'Content-Type'=>'text/html'}, ['Hello World!']]

response.status = 200
response['Content-Type'] = 'text/html'
response.write 'Hello World!'
r.halt


401
402
403
# File 'lib/roda.rb', line 401

def halt(res=response.finish)
  throw :halt, res
end

#initialize(scope, env) ⇒ Object

Store the roda instance and environment.



368
369
370
371
372
373
# File 'lib/roda.rb', line 368

def initialize(scope, env)
  @scope = scope
  @captures = []
  @remaining_path = _remaining_path(env)
  super(env)
end

#inspectObject

Show information about current request, including request class, request method and full path.

r.inspect
# => '#<Roda::RodaRequest GET /foo/bar>'


410
411
412
# File 'lib/roda.rb', line 410

def inspect
  "#<#{self.class.inspect} #{@env[REQUEST_METHOD]} #{path}>"
end

#is(*args, &block) ⇒ Object

Does a terminal match on the current path, matching only if the arguments have fully matched the path. If it matches, the match block is executed, and when the match block returns, the rack response is returned.

r.remaining_path
# => "/foo/bar"

r.is 'foo' do
  # does not match, as path isn't fully matched (/bar remaining)
end

r.is 'foo/bar' do
  # matches as path is empty after matching
end

If no arguments are given, matches if the path is already fully matched.

r.on 'foo/bar' do
  r.is do
    # matches as path is already empty
  end
end

Note that this matches only if the path after matching the arguments is empty, not if it still contains a trailing slash:

r.remaining_path
# =>  "/foo/bar/"

r.is 'foo/bar' do
  # does not match, as path isn't fully matched (/ remaining)
end

r.is 'foo/bar/' do
  # matches as path is empty after matching
end

r.on 'foo/bar' do
  r.is "" do
    # matches as path is empty after matching
  end
end


457
458
459
460
461
462
463
464
465
466
# File 'lib/roda.rb', line 457

def is(*args, &block)
  if args.empty?
    if empty_path?
      always(&block)
    end
  else
    args << TERM
    if_match(args, &block)
  end
end

#is_get?Boolean

Optimized method for whether this request is a GET request. Similar to the default Rack::Request get? method, but can be overridden without changing rack’s behavior.

Returns:

  • (Boolean)


471
472
473
# File 'lib/roda.rb', line 471

def is_get?
  @env[REQUEST_METHOD] == GET_REQUEST_METHOD
end

#matched_pathObject

The already matched part of the path, including the original SCRIPT_NAME.



511
512
513
514
# File 'lib/roda.rb', line 511

def matched_path
  e = @env
  e[SCRIPT_NAME] + e[PATH_INFO].chomp(@remaining_path)
end

#on(*args, &block) ⇒ Object

Does a match on the path, matching only if the arguments have matched the path. Because this doesn’t fully match the path, this is usually used to setup branches of the routing tree, not for final handling of the request.

r.remaining_path
# => "/foo/bar"

r.on 'foo' do
  # matches, path is /bar after matching
end

r.on 'bar' do
  # does not match
end

Like other routing methods, If it matches, the match block is executed, and when the match block returns, the rack response is returned. However, in general you will call another routing method inside the match block that fully matches the path and does the final handling for the request:

r.on 'foo' do
  r.is 'bar' do
    # handle /foo/bar request
  end
end


502
503
504
505
506
507
508
# File 'lib/roda.rb', line 502

def on(*args, &block)
  if args.empty?
    always(&block)
  else
    if_match(args, &block)
  end
end

#pathObject

This an an optimized version of Rack::Request#path.

r.env['SCRIPT_NAME'] = '/foo'
r.env['PATH_INFO'] = '/bar'
r.path
# => '/foo/bar'


522
523
524
525
# File 'lib/roda.rb', line 522

def path
  e = @env
  "#{e[SCRIPT_NAME]}#{e[PATH_INFO]}"
end

#post(*args, &block) ⇒ Object

Match POST requests. If no arguments are provided, matches all POST requests, otherwise, matches only POST requests where the arguments given fully consume the path.



539
540
541
# File 'lib/roda.rb', line 539

def post(*args, &block)
  _verb(args, &block) if post?
end

#real_remaining_pathObject

An alias of remaining_path. If a plugin changes remaining_path then it should override this method to return the untouched original.



532
533
534
# File 'lib/roda.rb', line 532

def real_remaining_path
  remaining_path
end

#redirect(path = default_redirect_path, status = default_redirect_status) ⇒ Object

Immediately redirect to the path using the status code. This ends the processing of the request:

r.redirect '/page1', 301 if r['param'] == 'value1'
r.redirect '/page2' # uses 302 status code
response.status = 404 # not reached

If you do not provide a path, by default it will redirect to the same path if the request is not a GET request. This is designed to make it easy to use where a POST request to a URL changes state, GET returns the current state, and you want to show the current state after changing:

r.is "foo" do
  r.get do
    # show state
  end

  r.post do
    # change state
    r.redirect
  end
end


566
567
568
569
# File 'lib/roda.rb', line 566

def redirect(path=default_redirect_path, status=default_redirect_status)
  response.redirect(path, status)
  throw :halt, response.finish
end

#responseObject

The response related to the current request. See ResponseMethods for instance methods for the response, but in general the most common usage is to override the response status and headers:

response.status = 200
response['Header-Name'] = 'Header value'


577
578
579
# File 'lib/roda.rb', line 577

def response
  @scope.response
end

#roda_classObject

Return the Roda class related to this request.



582
583
584
# File 'lib/roda.rb', line 582

def roda_class
  self.class.roda_class
end

#root(&block) ⇒ Object

Routing matches that only matches GET requests where the current path is /. If it matches, the match block is executed, and when the match block returns, the rack response is returned.

[r.request_method, r.remaining_path]
# => ['GET', '/']

r.root do
  # matches
end

This is usuable inside other match blocks:

[r.request_method, r.remaining_path]
# => ['GET', '/foo/']

r.on 'foo' do
  r.root do
    # matches
  end
end

Note that this does not match non-GET requests:

[r.request_method, r.remaining_path]
# => ['POST', '/']

r.root do
  # does not match
end

Use r.post "" for POST requests where the current path is /.

Nor does it match empty paths:

[r.request_method, r.remaining_path]
# => ['GET', '/foo']

r.on 'foo' do
  r.root do
    # does not match
  end
end

Use r.get true to handle GET requests where the current path is empty.



633
634
635
636
637
# File 'lib/roda.rb', line 633

def root(&block)
  if remaining_path == SLASH && is_get?
    always(&block)
  end
end

#run(app) ⇒ Object

Call the given rack app with the environment and return the response from the rack app as the response for this request. This ends the processing of the request:

r.run(proc{[403, {}, []]}) unless r['letmein'] == '1'
r.run(proc{[404, {}, []]})
response.status = 404 # not reached

This updates SCRIPT_NAME/PATH_INFO based on the current remaining_path before dispatching to another rack app, so the app still works as a URL mapper.



650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
# File 'lib/roda.rb', line 650

def run(app)
  e = @env
  path = real_remaining_path
  sn = SCRIPT_NAME
  pi = PATH_INFO
  script_name = e[sn]
  path_info = e[pi]
  begin
    e[sn] += path_info.chomp(path)
    e[pi] = path
    throw :halt, app.call(e)
  ensure
    e[sn] = script_name
    e[pi] = path_info
  end
end

#sessionObject

The session for the current request. Raises a RodaError if a session handler has not been loaded.



669
670
671
# File 'lib/roda.rb', line 669

def session
  @env[SESSION_KEY] || raise(RodaError, "You're missing a session handler. You can get started by adding use Rack::Session::Cookie")
end