Class: PrestoHTTP::InstanceAPI

Inherits:
Rack::Request
  • Object
show all
Includes:
API
Defined in:
lib/presto/http.rb,
lib/presto/http/instance-api/api.rb,
lib/presto/http/instance-api/auth.rb,
lib/presto/http/instance-api/file.rb,
lib/presto/http/instance-api/pass.rb,
lib/presto/http/instance-api/halt.rb,
lib/presto/http/instance-api/params.rb,
lib/presto/http/instance-api/cookies.rb,
lib/presto/http/instance-api/sandbox.rb,
lib/presto/http/instance-api/session.rb,
lib/presto/http/instance-api/redirect.rb

Defined Under Namespace

Classes: CookiesProxy, SessionProxy

Constant Summary

Constant Summary

Constants included from PrestoCore::Utils

PrestoCore::Utils::PATH_MODIFIERS, PrestoCore::Utils::STATUS__NOT_FOUND, PrestoCore::Utils::STATUS__OK, PrestoCore::Utils::STATUS__PERMANENT_REDIRECT, PrestoCore::Utils::STATUS__REDIRECT, PrestoCore::Utils::STATUS__RESTRICTED, PrestoCore::Utils::STATUS__SERVER_ERROR

Instance Attribute Summary (collapse)

Instance Method Summary (collapse)

Methods included from API

#authorization_form, #build_path, #get, #mime_type, #normalize_path, #post, #route, #xhr_get, #xhr_post

Methods included from PrestoCore::Utils

build_path, #extract_controllers, is_controller?, normalize_path, rootify_url

Constructor Details

- (InstanceAPI) initialize(controller_instance, action, env, user = nil)

initializing the HTTP API to be used by controller instance



10
11
12
13
14
15
# File 'lib/presto/http/instance-api/api.rb', line 10

def initialize controller_instance, action, env, user = nil
  @controller, @controller_instance = controller_instance.class, controller_instance
  @action, @action_route = action, @controller.ctrl[action]
  @env, @request, @response = env, ::Rack::Request.new(env), ::Rack::Response.new
  @user = user
end

Instance Attribute Details

- (Object) action (readonly)

Returns the value of attribute action



6
7
8
# File 'lib/presto/http/instance-api/api.rb', line 6

def action
  @action
end

- (Object) action_route (readonly)

Returns the value of attribute action_route



6
7
8
# File 'lib/presto/http/instance-api/api.rb', line 6

def action_route
  @action_route
end

- (Object) env (readonly)

Returns the value of attribute env



6
7
8
# File 'lib/presto/http/instance-api/api.rb', line 6

def env
  @env
end

- (Object) sandbox_capabilities (readonly)

Returns the value of attribute sandbox_capabilities



7
8
9
# File 'lib/presto/http/instance-api/api.rb', line 7

def sandbox_capabilities
  @sandbox_capabilities
end

- (Object) user (readonly) Also known as: user?

Returns the value of attribute user



7
8
9
# File 'lib/presto/http/instance-api/api.rb', line 7

def user
  @user
end

Instance Method Details

- (Object) [](action_or_url)



55
56
57
# File 'lib/presto/http/instance-api/api.rb', line 55

def [] action_or_url
  @controller.ctrl[action_or_url]
end

- (Object) accept



47
48
49
# File 'lib/presto/http/instance-api/api.rb', line 47

def accept
  @env['HTTP_ACCEPT']
end

- (Object) action_map



51
52
53
# File 'lib/presto/http/instance-api/api.rb', line 51

def action_map
  @controller.ctrl.action_map
end

- (Object) attachment(path, opts = {})



36
37
38
# File 'lib/presto/http/instance-api/file.rb', line 36

def attachment path, opts = {}
  send_file path, opts.merge(attachment: true)
end

- (Object) auth(action = nil)



11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/presto/http/instance-api/auth.rb', line 11

def auth action = nil
  if action
    # checking either given action can be authenticated using current credentials
    if (route = @controller.ctrl.action_map[action]) &&
        (restriction = @controller.http.auth(action))
      type = '' << (restriction[:type] || 'Basic').to_s << 'Auth'
      env = env().dup.update('SCRIPT_NAME' => route)
      return ::PrestoHTTP::const_get(type).new @controller_instance, env, restriction
    end
  else
    @auth
  end
end

- (Object) body(body = nil)

set/get response body



36
37
38
39
# File 'lib/presto/http/instance-api/api.rb', line 36

def body body = nil
  @response.body = body if body
  @response.body
end

- (Boolean) canonical?

Returns:

  • (Boolean)


17
18
19
# File 'lib/presto/http/instance-api/api.rb', line 17

def canonical?
  path.match ::Regexp.union(*@controller.http.canonical, *@controller.ctrl.slice.canonical)
end

- (Object) confine(*capabilities)

limit access to HTTP API. by default it will allow to read params, host, port etc. however it wont allow reading session/cookies/env neither will allow redirects, forwarding or halt. to allow additional capabilities, add them as arguments.

Examples:

generic sandbox for all actions

http.before do
  http.confine
end

generic sandbox for #render action

http.before :render do
  http.confine
end

sandbox with redirect capability for all actions

http.before do
  http.confine :redirect
end

sandbox with session and cookies capability for #order action

http.before :order do
  http.confine :session, :cookies
end

Parameters:

  • capabilities (Array)


31
32
33
# File 'lib/presto/http/instance-api/sandbox.rb', line 31

def confine *capabilities
  @sandbox_capabilities = capabilities
end

- (Object) content_type(content_type = nil)

set/get content_type



42
43
44
45
# File 'lib/presto/http/instance-api/api.rb', line 42

def content_type content_type = nil
  @response['Content-Type'] = content_type if content_type
  @response['Content-Type']
end

- (Object) cookies

get / set cookies



5
6
7
# File 'lib/presto/http/instance-api/cookies.rb', line 5

def cookies
  @cookies__proxy ||= CookiesProxy.new @request, @response
end

- (Object) delayed_redirect(*args) Also known as: deferred_redirect

ensure the browser will be redirected after action/hook finished.



28
29
30
# File 'lib/presto/http/instance-api/redirect.rb', line 28

def delayed_redirect *args
  trigger_redirect STATUS__REDIRECT, *args
end

- (Object) error(status, body = nil)



43
44
45
46
47
48
# File 'lib/presto/http/instance-api/halt.rb', line 43

def error status, body = nil
  if error_proc = @controller.http.error(status)
    body = @controller_instance.instance_exec(body.to_s, &error_proc)
  end
  halt status.to_i, body
end

- (Object) finish



59
60
61
# File 'lib/presto/http/instance-api/api.rb', line 59

def finish
  @response.finish
end

- (Object) flash

Examples:

http.flash[:alert] = 'Item Deleted'
p http.flash[:alert] #=> "Item Deleted"
p http.flash[:alert] #=> nil


20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/presto/http/instance-api/session.rb', line 20

def flash
  api, uniq = self, '__presto__session__flash__'
  unless @session__flash_proxy
    @session__flash_proxy = Class.new
    @session__flash_proxy.define_singleton_method :[]= do |key, val|
      api.session['%s-%s' % [uniq, key]] = val
    end
    @session__flash_proxy.define_singleton_method :[] do |key|
      return unless val = api.session[key = '%s-%s' % [uniq, key]]
      api.session.delete key
      val
    end
  end
  @session__flash_proxy
end

- (Object) get_params Also known as: GET



8
9
10
# File 'lib/presto/http/instance-api/params.rb', line 8

def get_params
  @get_params ||= indifferent_params(@request.GET)
end

- (Object) halt(*args)

stop executing any action/hook and send response to browser. accepts an arbitrary number of arguments. if arg is an Integer, it will be used as status code. if arg is a Hash, it is treated as headers. if it is an array, it is treated as Rack response and are sent immediately, ignoring other args. any other args are treated as body.

Examples:

returning "Well Done" body with 200 status code

http.halt 'Well Done'

halting quietly, ie, with empty body, with 200 status code

http.halt

returning error with 500 code:

http.halt 500, 'Sorry, some fatal error occurred'

custom content type

http.halt File.read('/path/to/theme.css'), 'Content-Type' => http.mime_type('.css')

sending custom Rack response

http.halt [200, {'Content-Disposition' => "attachment; filename=some-file"}, some_IO_instance]

Parameters:

  • *args (Array)


27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/presto/http/instance-api/halt.rb', line 27

def halt *args
  args.each do |a|
    case
      when a.is_a?(Fixnum)
        @response.status = a
      when a.is_a?(Array)
        throw :__presto_catch_response__, a
      when a.is_a?(Hash)
        a.each_pair { |k, v| @response[k] = v }
      else
        @response.body = [a.to_s]
    end
  end
  throw :__presto_catch_response__, @response.finish
end

- (Object) header Also known as: headers



21
22
23
# File 'lib/presto/http/instance-api/api.rb', line 21

def header
  @response.header
end

- (Object) initialize_auth



4
5
6
7
8
9
# File 'lib/presto/http/instance-api/auth.rb', line 4

def initialize_auth
  if restriction = @controller.http.auth(@action)
    type = '' << (restriction[:type] || 'Basic').to_s << 'Auth'
    @auth = ::PrestoHTTP::const_get(type).new @controller_instance, env, restriction
  end
end

- (Object) params



4
5
6
# File 'lib/presto/http/instance-api/params.rb', line 4

def params
  @params ||= indifferent_params(@request.params)
end

- (Object) pass(*args, &proc)

simply pass control to another action.

by default, it will pass control to an action on current controller. if first argument is a controller, control will be passed to that controller.

by default, it will pass with given path parameters, i.e. PATH_INFO if you pass some arguments beside action, they will be passed to destination action.

if proc given, it will be executed just before leaving current scope.

Examples:

pass control to #control_panel if user authorized

def index
  http.pass :control_panel if http.user
end

passing with modified arguments

def index id, action
  http.pass action, id
end

passing with modified arguments and custom HTTP params

def index id, action
  http.pass action, id, :foo => :bar
end

passing to inner controller

def index id, action
  http.pass Articles, :news, action, id
end

execute a callback before leaving current scope

http.before do |*args|
  if args.size > 0
    http.pass :catchall do
      puts 'control passed to #catchall with args: %s' % args
    end
  end
end

Parameters:

  • *args (Class)


44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/presto/http/instance-api/pass.rb', line 44

def pass *args, &proc

  if args.size == 0
    puts 'http.path expects an action(or an controller and action) to be provided'
    raise ArgumentError
  end

  controller = ::PrestoCore::Utils.is_controller?(args.first) ?
      args.shift :
      @controller

  if args.size == 0
    puts 'Beside controller, http.path also expects an action to be provided'
    raise ArgumentError
  end

  @controller_instance.instance_exec(&proc) if proc

  action = args.shift.to_sym
  route = controller.ctrl[action]
  @request.env.update('SCRIPT_NAME' => route)

  if args.size > 0
    path, params = '/', {}
    args.each { |a| a.is_a?(Hash) ? params.update(a) : path << a.to_s << '/' }
    @request.env.update('PATH_INFO' => path)
    params.size > 0 &&
        @request.env.update('QUERY_STRING' => ::Rack::Utils.build_nested_query(params))
  end
  throw :__presto_catch_response__, Response.new(controller, route).call(@request.env)
end

- (Object) path_params



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/presto/http/instance-api/params.rb', line 21

def path_params
  unless @path_params
    path_params = {}
    given_params = env['PATH_INFO'].to_s.split('/').map { |s| s if s.size > 0 }.compact
    method_params = @controller_instance.method(action).parameters
    1.upto(method_params.size).each do
      type, name = method_params.first
      if type == :rest
        path_params[name] = []
        until given_params.size < method_params.size
          path_params[name] << given_params.shift
        end
      else
        path_params[name] = given_params.shift
      end
      method_params.shift
    end
    @path_params = indifferent_params path_params
  end
  @path_params
end

- (Object) permanent_redirect(*args)



19
20
21
22
# File 'lib/presto/http/instance-api/redirect.rb', line 19

def permanent_redirect *args
  trigger_redirect STATUS__PERMANENT_REDIRECT, *args
  halt
end

- (Object) post_params Also known as: POST



14
15
16
# File 'lib/presto/http/instance-api/params.rb', line 14

def post_params
  @post_params ||= indifferent_params(@request.POST)
end

- (Object) redirect(*args)

stop any action/hook and redirect right away. path is built by passing given args to http.route



14
15
16
17
# File 'lib/presto/http/instance-api/redirect.rb', line 14

def redirect *args
  trigger_redirect STATUS__REDIRECT, *args
  halt
end

- (Object) reload(params = nil)

simply reload the page, using current GET params. to use custom GET params, pass a hash as first argument.

Parameters:

  • params (Hash, nil) (defaults to: nil)


8
9
10
# File 'lib/presto/http/instance-api/redirect.rb', line 8

def reload params = nil
  redirect @request.path, params || get_params
end

- (Object) reset_auth



25
26
27
# File 'lib/presto/http/instance-api/auth.rb', line 25

def reset_auth
  @auth && @auth.reset
end

- (Object) sandbox(*capabilities)

creating a sandbox.

Examples:

using a confined api to render an untrusted view

def content
  api = http.sandbox
  view.render_view '/path/to/file', http: api
end

Parameters:

  • capabilities (Array)


44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/presto/http/instance-api/sandbox.rb', line 44

def sandbox *capabilities
  [
      :flash,
      :user,
      :params,
      :scheme,
      :host,
      :host_with_port,
      :port,
      :path_info,
      :request_method,
      :query_string,
      :body,
      :content_length,
      :content_type,
      :media_type,
      :content_charset,
      :get?,
      :head?,
      :options?,
      :post?,
      :put?,
      :xhr?,
      :trace?,
      :form_data?,
      :parseable_data?,
      :referer,
      :referrer,
      :user_agent,
      :url,
      :path,
      :fullpath,
      :accept_encoding,
      :ip,
  ].each do |capability|
    capabilities << capability
  end
  api, sandbox = self, Class.new
  capabilities.uniq.each do |capability|
    sandbox.define_singleton_method capability do |*args|
      api.send capability, *args
    end
  end
  sandbox
end

- (Object) send_file(path, opts = {})

Serving static files. Note that this blocks app while file readed/transmitted(on WEBrick and Thin, as minimum). To avoid app locking, setup your Nginx/Lighttpd server to set proper X-Sendfile header and use Rack::Sendfile middleware in your app.

Parameters:

  • path (String)

    full path to file

  • opts (Hash) (defaults to: {})

Options Hash (opts):

  • filename (String)

    the name of file displayed in browser's save dialog

  • content_type (String)

    custom content_type

  • last_modified (String)
  • cache_control (String)
  • attachment (Boolean)

    if set to true, browser will prompt user to save file



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/presto/http/instance-api/file.rb', line 16

def send_file path, opts = {}

  file = Rack::File.new nil
  file.path = path
  (cache_control = opts[:cache_control]) && file.cache_control = cache_control
  response = file.serving env

  response[1]['Content-Disposition'] = opts[:attachment] ?
      'attachment; filename="%s"' % (opts[:filename] || File.basename(path)) :
      'inline'

  (content_type = opts[:content_type]) &&
      response[1]['Content-Type'] = content_type

  (last_modified = opts[:last_modified]) &&
      response[1]['Last-Modified'] = last_modified

  halt response
end

- (Object) session

read / write sessions

Examples:

set session

http.session[:page] = 1

get session

http.session[:page]

delete session

http.session.delete :page


12
13
14
# File 'lib/presto/http/instance-api/session.rb', line 12

def session
  @session__proxy ||= SessionProxy.new @controller_instance, @request, @response
end

- (Object) status_code(status = nil) Also known as: status

set/get response status



28
29
30
31
# File 'lib/presto/http/instance-api/api.rb', line 28

def status_code status = nil
  @response.status = status if status
  @response.status
end