Class: Blix::Rest::Controller

Inherits:
Object
  • Object
show all
Defined in:
lib/blix/rest/controller.rb

Constant Summary collapse

ESCAPE_HTML =

the following is copied from Rack::Utils

{
  '&' => '&',
  '<' => '&lt;',
  '>' => '&gt;',
  "'" => '&#x27;',
  '"' => '&quot;',
  '/' => '&#x2F;'
}.freeze
JS_ESCAPE_MAP =
{ '\\' => '\\\\', '</' => '<\/', "\r\n" => '\n', "\n" => '\n', "\r" => '\n', '"' => '\\"', "'" => "\\'" }.freeze
ESCAPE_HTML_PATTERN =
Regexp.union(*ESCAPE_HTML.keys)

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.__erb_pathObject

default method .. will be overridden with erb_path method



635
636
637
# File 'lib/blix/rest/controller.rb', line 635

def __erb_path
  nil
end

._after_hooksObject



731
732
733
# File 'lib/blix/rest/controller.rb', line 731

def _after_hooks
  @_after_hooks ||= {}
end

._before_hooksObject



727
728
729
# File 'lib/blix/rest/controller.rb', line 727

def _before_hooks
  @_before_hooks ||= {}
end

._do_after(ctx, *a) ⇒ Object



740
741
742
743
# File 'lib/blix/rest/controller.rb', line 740

def _do_after(ctx, *a)
  _after_hooks.each_value{ |h| ctx.instance_eval(&h) }
  superclass._do_after(ctx, *a) if superclass.respond_to? :_do_after
end

._do_before(ctx, *a) ⇒ Object



735
736
737
738
# File 'lib/blix/rest/controller.rb', line 735

def _do_before(ctx, *a)
  superclass._do_before(ctx, *a) if superclass.respond_to? :_do_before
  _before_hooks.each_value{ |h| ctx.instance_eval(&h) }
end

._do_route_hook(route) ⇒ Object



654
655
656
657
658
659
# File 'lib/blix/rest/controller.rb', line 654

def _do_route_hook(route)
  if @_route_hook
    superclass._do_route_hook(route) if superclass.respond_to? :_do_route_hook
    @_route_hook.call(route)
  end
end

.after(&block) ⇒ Object

define an after hook for a controller. only one hook can be defined per controller in a single source file.



757
758
759
760
761
762
763
# File 'lib/blix/rest/controller.rb', line 757

def after(&block)
  if block
    file = block.source_location[0]
    warn("warning: after hook already defined in #{file}") if _after_hooks[file]
    _after_hooks[file] = block
  end
end

.all(*a, &b) ⇒ Object



714
715
716
# File 'lib/blix/rest/controller.rb', line 714

def all(*a, &b)
  route 'ALL', *a, &b
end

.allow_methods(*methods) ⇒ Object



765
766
767
768
769
770
771
772
773
774
# File 'lib/blix/rest/controller.rb', line 765

def allow_methods(*methods)
  out = String.new
  methods.each do |method|
    method = method.to_s.upcase
    next if (HTTP_VERBS + ['ALL']).include?(method)
    out << "def #{method.downcase}(*a, &b);route '#{method}', *a, &b;end\n"
  end
  puts out if $DEBUG || $VERBOSE
  eval out unless out.empty?
end

.before(&block) ⇒ Object

define a before hook for a controller. only one hook can be defined per controller in a single source file.



747
748
749
750
751
752
753
# File 'lib/blix/rest/controller.rb', line 747

def before(&block)
  if block
    file = block.source_location[0]
    warn("warning: before hook already defined in #{file}") if _before_hooks[file]
    _before_hooks[file] = block
  end
end

.before_route(&b) ⇒ Object



722
723
724
# File 'lib/blix/rest/controller.rb', line 722

def before_route(&b)
  @_route_hook = b if b
end

.check_format(accept, format) ⇒ Object

Raises:



645
646
647
648
649
650
651
652
# File 'lib/blix/rest/controller.rb', line 645

def check_format(accept, format)
  return if (format == :json) && accept.nil?  # the majority of cases
  return if (format == :_) && accept.nil?     # assume json by default.

  accept ||= :json
  accept = [accept].flatten
  raise ServiceError, 'invalid format for this request' unless accept.index format
end

.delete(*a, &b) ⇒ Object



710
711
712
# File 'lib/blix/rest/controller.rb', line 710

def delete(*a, &b)
  route 'DELETE', *a, &b
end

.erb_dir(val) ⇒ Object

redefine the __erb_path method for this and derived classes



640
641
642
643
# File 'lib/blix/rest/controller.rb', line 640

def erb_dir(val)
  str = "def self.__erb_path;\"#{val}\";end"
  class_eval str
end

.erb_rootObject



566
567
568
569
570
571
572
573
# File 'lib/blix/rest/controller.rb', line 566

def self.erb_root
  @_erb_root ||= begin
    root = File.join(Dir.pwd, 'app', 'views')
    raise('use set_erb_root() to specify the location of your views') unless Dir.exist?(root)

    root
  end
end

.erb_templatesObject

cache templates here



558
559
560
# File 'lib/blix/rest/controller.rb', line 558

def self.erb_templates
  @_erb ||= {}
end

.get(*a, &b) ⇒ Object



690
691
692
# File 'lib/blix/rest/controller.rb', line 690

def get(*a, &b)
  route 'GET', *a, &b
end

.head(*a, &b) ⇒ Object



694
695
696
# File 'lib/blix/rest/controller.rb', line 694

def head(*a, &b)
  route 'HEAD', *a, &b
end

.no_template_cacheObject

do not cache templates in development mode



548
549
550
551
# File 'lib/blix/rest/controller.rb', line 548

def self.no_template_cache
  @_no_template_cache = (Blix::Rest.environment != 'production') if @_no_template_cache.nil?
  @_no_template_cache
end

.no_template_cache=(val) ⇒ Object



553
554
555
# File 'lib/blix/rest/controller.rb', line 553

def self.no_template_cache=(val)
  @_no_template_cache = val
end

.options(*a, &b) ⇒ Object



718
719
720
# File 'lib/blix/rest/controller.rb', line 718

def options(*a, &b)
  route 'OPTIONS', *a, &b
end

.patch(*a, &b) ⇒ Object



706
707
708
# File 'lib/blix/rest/controller.rb', line 706

def patch(*a, &b)
  route 'PATCH', *a, &b
end

.post(*a, &b) ⇒ Object



698
699
700
# File 'lib/blix/rest/controller.rb', line 698

def post(*a, &b)
  route 'POST', *a, &b
end

.put(*a, &b) ⇒ Object



702
703
704
# File 'lib/blix/rest/controller.rb', line 702

def put(*a, &b)
  route 'PUT', *a, &b
end

.render(text, context, opts = {}) ⇒ Object

render a string within a layout.



578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
# File 'lib/blix/rest/controller.rb', line 578

def render(text, context, opts = {})
  layout_name = opts[:layout]
  path        = opts[:path] || __erb_path || Controller.erb_root

  layout = layout_name && if no_template_cache
                            ERB.new(File.read(File.join(path, layout_name + '.html.erb')),:trim_mode=>'-')
                          else
                            erb_templates[layout_name] ||= ERB.new(File.read(File.join(path, layout_name + '.html.erb')),:trim_mode=>'-')
  end

  begin
    if layout
      layout.result(context._get_binding { |*_args| text })
    else
      text
    end
  rescue Exception
    ::Blix::Rest.logger <<  $!
    ::Blix::Rest.logger <<  $@
    '*** TEMPLATE ERROR ***'
  end
end

.render_erb(name, context, opts = {}) ⇒ Object



601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
# File 'lib/blix/rest/controller.rb', line 601

def render_erb(name, context, opts = {})
  name        = name.to_s
  layout_name = opts[:layout] && opts[:layout].to_s
  locals      = opts[:locals]
  path        = opts[:erb_dir] || __erb_path || Controller.erb_root

  layout = layout_name && if no_template_cache
                            ERB.new(File.read(File.join(path, layout_name + '.html.erb')),:trim_mode=>'-')
                          else
                            erb_templates[layout_name] ||= ERB.new(File.read(File.join(path, layout_name + '.html.erb')),:trim_mode=>'-')
  end

  erb = if no_template_cache
          ERB.new(File.read(File.join(path, name + '.html.erb')),:trim_mode=>'-')
        else
          erb_templates[name] ||= ERB.new(File.read(File.join(path, name + '.html.erb')),:trim_mode=>'-')
  end

  begin
    bind = context._get_binding
    locals&.each { |k, v| bind.local_variable_set(k, v) } # works from ruby 2.1
    if layout
      layout.result(context._get_binding { |*_args| erb.result(bind) })
    else
      erb.result(bind)
    end
  rescue Exception
    ::Blix::Rest.logger <<  $!
    ::Blix::Rest.logger <<  $@
    '*** TEMPLATE ERROR ***'
  end
end

.route(verb, path, opts = {}, &blk) ⇒ Object



661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
# File 'lib/blix/rest/controller.rb', line 661

def route(verb, path, opts = {}, &blk)
  path = '/' + path unless path[0] == '/'
  path = String.new(path)  # in case frozen.
  route = Route.new(verb, path, opts)
  _do_route_hook(route)
  proc = lambda do |context|
    unless opts[:force] && (opts[:accept] == :*)
      check_format(opts[:accept], context.format)
    end
    app = new
    app._setup(context, verb, path, opts)
    begin
      app.session_before(opts)
      app.before(opts)
      app.__before
      context.response = app.instance_eval( &blk )
    rescue
      raise
    ensure
      app.__after
      app.after(opts, context.response)
      app.session_after
      context.response
    end
  end

  RequestMapper.add_path(verb.to_s.upcase, path, opts, &proc)
end

.set_erb_root(dir) ⇒ Object



562
563
564
# File 'lib/blix/rest/controller.rb', line 562

def self.set_erb_root(dir)
  @_erb_root = dir
end

Instance Method Details

#__after(*a) ⇒ Object

perform the after hooks



503
504
505
# File 'lib/blix/rest/controller.rb', line 503

def __after(*a)
  self.class._do_after(self, *a)
end

#__before(*a) ⇒ Object

perform the before hooks.



498
499
500
# File 'lib/blix/rest/controller.rb', line 498

def __before(*a)
  self.class._do_before(self, *a)
end

#_get_bindingObject



229
230
231
# File 'lib/blix/rest/controller.rb', line 229

def _get_binding
  binding
end

#_opt(opts, key) ⇒ Object



484
485
486
487
488
489
490
# File 'lib/blix/rest/controller.rb', line 484

def  _opt(opts,key)
  if opts.key?(key.to_sym)
    opts[key.to_sym]
  else
    opts[key.to_s]
  end
end

#_opt?(opts, key) ⇒ Boolean

Returns:

  • (Boolean)


480
481
482
# File 'lib/blix/rest/controller.rb', line 480

def _opt?(opts,key)
  opts.key?(key.to_sym) || opts.key?(key.to_s)
end

#_setup(context, _verb, _path, _parameters) ⇒ Object




524
525
526
527
528
529
530
531
532
533
534
535
536
537
# File 'lib/blix/rest/controller.rb', line 524

def _setup(context, _verb, _path, _parameters)
  @_context        = context
  @_req            = context.req
  @_env            = req.env
  @_query_params = StringHash.new(req.GET)
  @_path_params  = StringHash.new(context.path_params)
  @_format         = context.format
  @_verb           = _verb
  @_response       = context.response
  @_server_options = context.server._options
  @_parameters     = _parameters
  @_server_cache   = context.server._cache
  @_method         = context.method
end

#add_headers(headers) ⇒ Object



312
313
314
# File 'lib/blix/rest/controller.rb', line 312

def add_headers(headers)
  @_response.headers.merge!(headers.map{|k,v| [k.to_s.downcase,v]}.to_h)
end

#after(_opts, response) ⇒ Object

a hook used to insert processing for after the method call. return a hash containing the response.



515
516
517
# File 'lib/blix/rest/controller.rb', line 515

def after(_opts, response)
  response
end

#auth_error(*params) ⇒ Object

Raises:



362
363
364
365
366
367
368
369
370
371
# File 'lib/blix/rest/controller.rb', line 362

def auth_error(*params)
  if params[0].kind_of?(String)
      message = params[0]
      opts = params[1] || {}
  else
      message = nil
      opts = params[-1] || {}
  end
  raise AuthorizationError.new(message,opts[:realm], opts[:type])
end

#before(opts) ⇒ Object

a hook used to insert processing for before the method call



511
# File 'lib/blix/rest/controller.rb', line 511

def before(opts); end

#bodyObject



79
80
81
82
83
84
85
86
87
# File 'lib/blix/rest/controller.rb', line 79

def body
  @_body ||= begin
    if env['rack.input']
      env['rack.input'].read
    else
      ''
    end
  end
end

#body_hashObject



108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/blix/rest/controller.rb', line 108

def body_hash
  @_body_hash ||= if body.empty?
                    {}
                  else
                    # should we check the content type here?
                    begin
                      StringHash.new(MultiJson.load(body))
                    rescue StandardError
                      raise ServiceError, "error in data json format/#{body}/"
                    end
  end
end

#envObject


convenience methods




42
43
44
# File 'lib/blix/rest/controller.rb', line 42

def env
  @_env
end

#escape_javascript(javascript) ⇒ Object

escape javascript



336
337
338
339
340
341
342
# File 'lib/blix/rest/controller.rb', line 336

def escape_javascript(javascript)
  if javascript
    javascript.gsub(%r{(\|</|\r\n|\342\200\250|\342\200\251|[\n\r"'])}u) { |match| JS_ESCAPE_MAP[match] }
  else
    ''
  end
end

#form_hashObject



104
105
106
# File 'lib/blix/rest/controller.rb', line 104

def form_hash
  StringHash.new(req.POST)
end

#formatObject



125
126
127
# File 'lib/blix/rest/controller.rb', line 125

def format
  @_format
end

#full_path(path) ⇒ Object

add on the root path



197
198
199
# File 'lib/blix/rest/controller.rb', line 197

def full_path(path)
  RequestMapper.full_path(path)
end

#full_url(_path) ⇒ Object

the full url of this path.



202
203
204
# File 'lib/blix/rest/controller.rb', line 202

def full_url(_path)
  raise 'not yet implemented'
end

#get_basic_auth(realm = nil) ⇒ Object

extract the user and login from the basic authentication

Raises:



234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/blix/rest/controller.rb', line 234

def get_basic_auth(realm=nil)
  data = env['HTTP_AUTHORIZATION']
  raise AuthorizationError.new('authentication missing',realm) unless data

  type = data[0, 5]
  rest = data[6..-1]

  raise  AuthorizationError.new('wrong authentication method',realm) unless type == 'Basic'
  raise  AuthorizationError.new('username:password missing',realm)   unless rest

  auth_parts = Base64.decode64(rest).split(':')
   = auth_parts[0]
  password = auth_parts[1]
  [, password]
end


373
374
375
376
377
378
379
380
381
382
383
384
385
386
# File 'lib/blix/rest/controller.rb', line 373

def get_cookie(name)
  cookie_header = env['HTTP_COOKIE']
  cookie_length = name.length
  parts = cookie_header&.split(';')
  value = nil
  parts&.reverse&.each do |cookie|
    cookie.strip!
    if cookie[0..cookie_length] == name + '='
      value = cookie[cookie_length + 1..-1]
      break
    end
  end
  value
end

#get_data(field) ⇒ Object



121
122
123
# File 'lib/blix/rest/controller.rb', line 121

def get_data(field)
  body_hash['data'] && body_hash['data'][field]
end

#get_session_id(session_name, opts = {}) ⇒ Object

manage session handling ————————————————– setup the session and retrieve the session_id this id can be used to retrieve and data associated with the session_id in eg: a database or a memory hash



469
470
471
472
# File 'lib/blix/rest/controller.rb', line 469

def get_session_id(session_name, opts = {})
  session_id = get_cookie(session_name)
  session_id || refresh_session_id(session_name, opts)
end

#h(string) ⇒ Object

Escape ampersands, brackets and quotes to their HTML/XML entities.



331
332
333
# File 'lib/blix/rest/controller.rb', line 331

def h(string)
  string.to_s.gsub(ESCAPE_HTML_PATTERN) { |c| ESCAPE_HTML[c] }
end

#inspectObject



543
544
545
# File 'lib/blix/rest/controller.rb', line 543

def inspect
  to_s
end

#loggerObject



59
60
61
# File 'lib/blix/rest/controller.rb', line 59

def logger
  Blix::Rest.logger
end

#methodObject



168
169
170
# File 'lib/blix/rest/controller.rb', line 168

def method
  @_method
end

#mode_development?Boolean

Returns:

  • (Boolean)


71
72
73
# File 'lib/blix/rest/controller.rb', line 71

def mode_development?
  rack_env == 'development'
end

#mode_production?Boolean

Returns:

  • (Boolean)


75
76
77
# File 'lib/blix/rest/controller.rb', line 75

def mode_production?
  rack_env == 'production'
end

#mode_test?Boolean

Returns:

  • (Boolean)


67
68
69
# File 'lib/blix/rest/controller.rb', line 67

def mode_test?
  rack_env == 'test'
end

#paramsObject



137
138
139
# File 'lib/blix/rest/controller.rb', line 137

def params
  @_params ||= StringHash.new(@_query_params,@_path_params)
end

#pathObject

override the path method to return the internal path.



90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/blix/rest/controller.rb', line 90

def path
  p = CGI.unescape(req.path)
  p = '/' + p if p[0, 1] != '/' # ensure a leading slash on path
  idx = RequestMapper.path_root_length
  if idx > 0
    p = p[idx..-1] || '/'
    p = '/' + p if p[0, 1] != '/' # ensure a leading slash on path
    p
  else
    p
  end
end

#path_for(path) ⇒ Object



152
153
154
# File 'lib/blix/rest/controller.rb', line 152

def path_for(path)
  File.join(RequestMapper.path_root, path || '')
end

#path_paramsObject



133
134
135
# File 'lib/blix/rest/controller.rb', line 133

def path_params
  @_path_params
end

#post_paramsObject



141
142
143
144
145
146
147
148
149
150
# File 'lib/blix/rest/controller.rb', line 141

def post_params
  @_post_params ||= begin
    type = req.media_type
    if type && Rack::Request::FORM_DATA_MEDIA_TYPES.include?(type)
      form_hash
    else
      body_hash
    end
  end
end

#query_paramsObject



129
130
131
# File 'lib/blix/rest/controller.rb', line 129

def query_params
  @_query_params
end

#rack_envObject



63
64
65
# File 'lib/blix/rest/controller.rb', line 63

def rack_env
  ENV['RACK_ENV']
end

#rate_limit(name, options = {}) ⇒ Object

options:

:prefix    # the prefix to use in the cache
:cache     # a cache object  ( server_cache )
:times     # array of delays in seconds to apply default: [60, 600, 86400]


425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
# File 'lib/blix/rest/controller.rb', line 425

def rate_limit(name, options = {})
  # check that the waiting time has expired
  cache      = options[:cache]  || server_cache()
  prefix     = options[:prefix] || 'rlimit'
  key        = "#{prefix}|#{name}"
  info       = cache.get(key) || {}
  fail_count = info['fc'].to_i
  times      = options[:times] || []
  if fail_count > 2
    now       = Time.now
    fail_time = info['ft']
    delta     = times[0] || 60                               # one minute
    delta     = times[1] || 60 * 10      if fail_count > 10  # 10 minutes
    delta     = times[2] || 60 * 60 * 24 if fail_count > 100 # one day
    ltime     = fail_time + delta
    if ltime > now
      raise RateError, ltime.to_s
    end
  end
  exception = nil
  result = begin
            yield(key)
           rescue Exception => e
             exception = e
             nil
          end
  if exception
    # auth failure - increment error count / set error time
    info['fc'] = fail_count + 1
    info['ft']  = Time.now
    cache.set(key, info)
    raise exception
  else
    # auth success - set error count to 0
    info['fc'] = 0
    cache.set(key, info)
    result
  end
end

#rawjson(str) ⇒ Object



225
226
227
# File 'lib/blix/rest/controller.rb', line 225

def rawjson(str)
  RawJsonString.new(str)
end

#redirect(path, status = 302) ⇒ Object Also known as: redirect_to

Raises:



206
207
208
# File 'lib/blix/rest/controller.rb', line 206

def redirect(path, status = 302)
  raise ServiceError.new(nil, status, 'location' => RequestMapper.ensure_full_path(path))
end

#refresh_session_id(session_name, opts = {}) ⇒ Object

generate an new session_id for the current session



475
476
477
478
# File 'lib/blix/rest/controller.rb', line 475

def refresh_session_id(session_name, opts = {})
  session_id = SecureRandom.hex(32)
  store_session_id(session_name, session_id, opts)
end

#render(text, opts = {}) ⇒ Object



221
222
223
# File 'lib/blix/rest/controller.rb', line 221

def render(text, opts = {})
  self.class.render_erb(text, self, opts)
end

#render_erb(template_name, opts = {}) ⇒ Object

render an erb template with the variables in the controller



217
218
219
# File 'lib/blix/rest/controller.rb', line 217

def render_erb(template_name, opts = {})
  self.class.render_erb(template_name, self, opts)
end

#reqObject



160
161
162
# File 'lib/blix/rest/controller.rb', line 160

def req
  @_req
end

#request_ipObject



212
213
214
# File 'lib/blix/rest/controller.rb', line 212

def request_ip
  req.ip
end

#responseObject



184
185
186
# File 'lib/blix/rest/controller.rb', line 184

def response
  @_response
end

#route_optionsObject



180
181
182
# File 'lib/blix/rest/controller.rb', line 180

def route_options
  @_parameters
end

#route_parametersObject



172
173
174
# File 'lib/blix/rest/controller.rb', line 172

def route_parameters
  @_parameters
end

#route_paramsObject



176
177
178
# File 'lib/blix/rest/controller.rb', line 176

def route_params
  @_parameters
end

#send_data(data, opts = {}) ⇒ Object

send data to browser as attachment

Raises:



350
351
352
353
354
355
356
357
358
359
360
# File 'lib/blix/rest/controller.rb', line 350

def send_data(data, opts = {})
  add_headers 'content-type'=> opts[:type] || 'application/octet-stream'
  if opts[:filename]
    add_headers 'content-disposition'=>'attachment;filename='+ opts[:filename]
  elsif opts[:disposition] == 'attachment'
    add_headers 'content-disposition'=>'attachment'
  elsif opts[:disposition] == 'inline'
    add_headers 'content-disposition'=>'inline'
  end
  raise RawResponse.new(data, opts[:status] || 200)
end

#send_error(message, status = nil, headers = nil) ⇒ Object

send a (default) error

Raises:



345
346
347
# File 'lib/blix/rest/controller.rb', line 345

def send_error(message, status = nil, headers = nil)
  raise ServiceError.new(message, status, headers)
end

#server_cacheObject



51
52
53
# File 'lib/blix/rest/controller.rb', line 51

def server_cache
  @_server_cache
end

#server_cache_get(key) ⇒ Object



55
56
57
# File 'lib/blix/rest/controller.rb', line 55

def server_cache_get(key)
  server_cache[key] ||= yield if block_given?
end

#server_optionsObject

options that were passed to the server at create time.



47
48
49
# File 'lib/blix/rest/controller.rb', line 47

def server_options
  @_server_options
end

#sessionObject



192
193
194
# File 'lib/blix/rest/controller.rb', line 192

def session
  req.session
end

#session_afterObject

empty session after hook



520
# File 'lib/blix/rest/controller.rb', line 520

def session_after; end

#session_before(opts) ⇒ Object

empty session before hooh



519
# File 'lib/blix/rest/controller.rb', line 519

def session_before(opts); end

#set_accept_cors(opts = {}) ⇒ Object

set the cors headers



280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/blix/rest/controller.rb', line 280

def set_accept_cors(opts={})
  origin  = opts[:origin] || env['HTTP_ORIGIN'] || '*'
  origin  = origin.to_s
  if method=='options'
    methods = [opts[:methods] || []].to_a.flatten
    max_age = opts[:max_age] || 86400
    headers = [opts[:headers] || []].to_a.flatten
    credentials = opts.key?(:credentials) ? !!opts[:credentials] : true
    methods = [:get] if methods.empty?
    methods = methods.map{|m| m.to_s.upcase}
    headers = ['Content-Type'] if headers.empty?
    max_age = max_age.to_i

    add_headers 'Access-Control-Allow-Origin' => origin,
       'Access-Control-Allow-Methods'=>methods.join(', '),
       'Access-Control-Allow-Headers'=>headers,
       'Access-Control-Max-Age'=>max_age, #86400,
       'Access-Control-Allow-Credentials'=>'true'
  else
    add_headers 'Access-Control-Allow-Origin' => origin
  end
end

#set_options(value) ⇒ Object



307
308
309
310
# File 'lib/blix/rest/controller.rb', line 307

def set_options(value)
  @_context.response_options ||= {}
  @_context.response_options.merge!(value)
end

#set_status(value) ⇒ Object



303
304
305
# File 'lib/blix/rest/controller.rb', line 303

def set_status(value)
  @_response.status = value.to_i
end


388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
# File 'lib/blix/rest/controller.rb', line 388

def store_cookie(name, value, opts={})
  cookie_text = String.new("#{name}=#{value}")
  cookie_text << '; Secure'                                  if _opt?(opts,:secure)
  cookie_text << '; HttpOnly'                                if _opt?(opts,:http)
  cookie_text << "; HostOnly=#{_opt(opts,:hostOnly)}"        if _opt?(opts,:hostOnly)
  cookie_text << "; Expires=#{_opt(opts,:expires).httpdate}" if _opt?(opts,:expires)
  cookie_text << "; Max-Age=#{_opt(opts,:max_age)}"          if _opt?(opts,:max_age)
  cookie_text << "; Domain=#{_opt(opts,:domain)}"            if _opt?(opts,:domain)
  cookie_text << "; Path=#{_opt(opts,:path)}"                if _opt?(opts,:path)
  if policy = _opt(opts,:samesite)
    cookie_text << '; SameSite=Strict' if policy.to_s.downcase == 'strict'
    cookie_text << '; SameSite=Lax'    if policy.to_s.downcase == 'lax'
    cookie_text << '; SameSite=None'   if policy.to_s.downcase == 'none'
  end
  @_cookies ||= {}
  @_cookies[name] = cookie_text
  # cookie_header = @_response.headers['Set-Cookie']
  # if cookie_header
  #   cookie_header = cookie_header << "\n" << cookie_text
  # else
  #   cookie_header = cookie_text
  # end
  @_response.headers['set-cookie'] = @_cookies.values.join("\n")
  value
end

#store_session_id(session_name, session_id, opts = {}) ⇒ Object

set the cookie header that stores the session_id on the browser.



493
494
495
# File 'lib/blix/rest/controller.rb', line 493

def store_session_id(session_name, session_id, opts = {})
  store_cookie(session_name, session_id, opts)
end

#throttle_basic_auth(realm = nil, options = {}) ⇒ Object



250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/blix/rest/controller.rb', line 250

def throttle_basic_auth(realm=nil, options={})
  , password = get_basic_auth(realm)
  # check that the waiting time has expired
  info       = self.class.basic_store.get_hash() || {}
  fail_count = info['fail_count'].to_i
  if fail_count > 3
    now       = Time.now
    fail_time = info['fail_time']
    delta     = 60                             # one minute
    delta     = 60*10      if fail_count > 10  # 10 minutes
    delta     = 60*60*24   if fail_count > 100 # one day
    if (fail_time + delta) > now
      raise Blix::Rest::AuthorizationError.new("try again after #{(fail_time + delta)}", realm)
    end
  end
  if yield(,password)
    # auth success - set error count to 0
    info['fail_count'] = 0
    self.class.basic_store.store_hash(, info)
    true
  else
    # auth failure - increment error count / set error time
    info['fail_count'] = fail_count + 1
    info['fail_time']  = Time.now
    self.class.basic_store.store_hash(, info)
    raise Blix::Rest::AuthorizationError.new("invalid login or password", realm)
  end
end

#to_sObject



539
540
541
# File 'lib/blix/rest/controller.rb', line 539

def to_s
  "<#{self.class.to_s}:#{object_id}>"
end

#url_for(path) ⇒ Object



156
157
158
# File 'lib/blix/rest/controller.rb', line 156

def url_for(path)
  req.base_url + path_for(path)
end

#verbObject



164
165
166
# File 'lib/blix/rest/controller.rb', line 164

def verb
  @_verb
end