Class: Blix::Rest::Controller
- Inherits:
-
Object
- Object
- Blix::Rest::Controller
- Defined in:
- lib/blix/rest/controller.rb
Overview
base class for controllers. within your block handling a particular route you have access to a number of methods
env : the request environment hash body : the request body as a string body_hash : the request body as a hash constructed from json query_params : a hash of parameters as passed in the url as parameters path_params : a hash of parameters constructed from variable parts of the path params : all the params combined user : the user making this request ( or nil if format : the format the response should be in :json or :html session : the rack session if middleware has been used
to accept requests other thatn json then set :accept=>[:json,:html] as in the route
eg post '/myform' :accept=>[:html] # this will only accept html requests.
Constant Summary collapse
- ESCAPE_HTML =
the following is copied from Rack::Utils
{ '&' => '&', '<' => '<', '>' => '>', "'" => ''', '"' => '"', '/' => '/' }.freeze
- JS_ESCAPE_MAP =
{ '\\' => '\\\\', '</' => '<\/', "\r\n" => '\n', "\n" => '\n', "\r" => '\n', '"' => '\\"', "'" => "\\'" }.freeze
- ESCAPE_HTML_PATTERN =
Regexp.union(*ESCAPE_HTML.keys)
Class Method Summary collapse
-
.__erb_path ⇒ Object
default method ..
- .all(*a, &b) ⇒ Object
- .check_format(accept, format) ⇒ Object
- .delete(*a, &b) ⇒ Object
-
.erb_dir(val) ⇒ Object
redefine the __erb_path method for this and derived classes.
- .erb_root ⇒ Object
-
.erb_templates ⇒ Object
cache templates here.
- .get(*a, &b) ⇒ Object
- .head(*a, &b) ⇒ Object
-
.no_template_cache ⇒ Object
do not cache templates in development mode.
- .no_template_cache=(val) ⇒ Object
- .options(*a, &b) ⇒ Object
- .patch(*a, &b) ⇒ Object
- .post(*a, &b) ⇒ Object
- .put(*a, &b) ⇒ Object
-
.render(text, context, opts = {}) ⇒ Object
render a string within a layout.
- .render_erb(name, context, opts = {}) ⇒ Object
- .route(verb, path, opts = {}, &blk) ⇒ Object
- .set_erb_root(dir) ⇒ Object
Instance Method Summary collapse
- #_get_binding ⇒ Object
- #_opt(opts, key) ⇒ Object
- #_opt?(opts, key) ⇒ Boolean
- #add_headers(headers) ⇒ Object
-
#after(_opts, response) ⇒ Object
a hook used to insert processing for after the method call.
- #auth_error(*params) ⇒ Object
-
#before(opts) ⇒ Object
a hook used to insert processing for before the method call.
- #body ⇒ Object
- #body_hash ⇒ Object
-
#env ⇒ Object
——————————————————————————————————– convenience methods ——————————————————————————————————–.
-
#escape_javascript(javascript) ⇒ Object
escape javascript.
- #form_hash ⇒ Object
- #format ⇒ Object
-
#full_path(path) ⇒ Object
add on the root path.
-
#full_url(_path) ⇒ Object
the full url of this path.
-
#get_basic_auth(realm = nil) ⇒ Object
extract the user and login from the basic authentication.
- #get_cookie(name) ⇒ Object
- #get_data(field) ⇒ Object
-
#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.
-
#h(string) ⇒ Object
Escape ampersands, brackets and quotes to their HTML/XML entities.
-
#initialize(path_params, _params, req, format, verb, response, server_options) ⇒ Controller
constructor
———————————————————————————————————-.
- #logger ⇒ Object
- #method ⇒ Object
- #mode_development? ⇒ Boolean
- #mode_production? ⇒ Boolean
- #mode_test? ⇒ Boolean
- #params ⇒ Object
- #path ⇒ Object
- #path_for(path) ⇒ Object
- #path_params ⇒ Object
- #post_params ⇒ Object
- #query_params ⇒ Object
- #rack_env ⇒ Object
- #rawjson(str) ⇒ Object
- #redirect(path, status = 302) ⇒ Object (also: #redirect_to)
-
#refresh_session_id(session_name, opts = {}) ⇒ Object
generate an new session_id for the current session.
- #render(text, opts = {}) ⇒ Object
-
#render_erb(template_name, opts = {}) ⇒ Object
render an erb template with the variables in the controller.
- #req ⇒ Object
- #request_ip ⇒ Object
-
#send_error(message, status = nil, headers = nil) ⇒ Object
send a (default) error.
-
#server_options ⇒ Object
options that were passed to the server at create time.
- #session ⇒ Object
- #set_status(value) ⇒ Object
- #store_cookie(name, value, opts = {}) ⇒ Object
-
#store_session_id(session_name, session_id, opts = {}) ⇒ Object
set the cookie header that stores the session_id on the browser.
- #url_for(path) ⇒ Object
- #verb ⇒ Object
Constructor Details
#initialize(path_params, _params, req, format, verb, response, server_options) ⇒ Controller
332 333 334 335 336 337 338 339 340 341 |
# File 'lib/blix/rest/controller.rb', line 332 def initialize(path_params, _params, req, format, verb, response, ) @_req = req @_env = req.env @_query_params = StringHash.new(req.GET) @_path_params = StringHash.new(path_params) @_format = format @_verb = verb @_response = response = end |
Class Method Details
.__erb_path ⇒ Object
default method .. will be overridden with erb_path method
431 432 433 |
# File 'lib/blix/rest/controller.rb', line 431 def __erb_path nil end |
.all(*a, &b) ⇒ Object
493 494 495 |
# File 'lib/blix/rest/controller.rb', line 493 def all(*a, &b) route 'ALL', *a, &b end |
.check_format(accept, format) ⇒ Object
441 442 443 444 445 446 447 448 |
# File 'lib/blix/rest/controller.rb', line 441 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
489 490 491 |
# File 'lib/blix/rest/controller.rb', line 489 def delete(*a, &b) route 'DELETE', *a, &b end |
.erb_dir(val) ⇒ Object
redefine the __erb_path method for this and derived classes
436 437 438 439 |
# File 'lib/blix/rest/controller.rb', line 436 def erb_dir(val) str = "def self.__erb_path;\"#{val}\";end" class_eval str end |
.erb_root ⇒ Object
362 363 364 365 366 367 368 369 |
# File 'lib/blix/rest/controller.rb', line 362 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_templates ⇒ Object
cache templates here
354 355 356 |
# File 'lib/blix/rest/controller.rb', line 354 def self.erb_templates @_erb ||= {} end |
.get(*a, &b) ⇒ Object
469 470 471 |
# File 'lib/blix/rest/controller.rb', line 469 def get(*a, &b) route 'GET', *a, &b end |
.head(*a, &b) ⇒ Object
473 474 475 |
# File 'lib/blix/rest/controller.rb', line 473 def head(*a, &b) route 'HEAD', *a, &b end |
.no_template_cache ⇒ Object
do not cache templates in development mode
344 345 346 347 |
# File 'lib/blix/rest/controller.rb', line 344 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
349 350 351 |
# File 'lib/blix/rest/controller.rb', line 349 def self.no_template_cache=(val) @_no_template_cache = val end |
.options(*a, &b) ⇒ Object
497 498 499 |
# File 'lib/blix/rest/controller.rb', line 497 def (*a, &b) route 'OPTIONS', *a, &b end |
.patch(*a, &b) ⇒ Object
485 486 487 |
# File 'lib/blix/rest/controller.rb', line 485 def patch(*a, &b) route 'PATCH', *a, &b end |
.post(*a, &b) ⇒ Object
477 478 479 |
# File 'lib/blix/rest/controller.rb', line 477 def post(*a, &b) route 'POST', *a, &b end |
.put(*a, &b) ⇒ Object
481 482 483 |
# File 'lib/blix/rest/controller.rb', line 481 def put(*a, &b) route 'PUT', *a, &b end |
.render(text, context, opts = {}) ⇒ Object
render a string within a layout.
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 |
# File 'lib/blix/rest/controller.rb', line 374 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')),nil,'-') else erb_templates[layout_name] ||= ERB.new(File.read(File.join(path, layout_name + '.html.erb')),nil,'-') end begin if layout layout.result(context._get_binding { |*_args| text }) else text end rescue Exception puts $! puts $@ '*** TEMPLATE ERROR ***' end end |
.render_erb(name, context, opts = {}) ⇒ Object
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 |
# File 'lib/blix/rest/controller.rb', line 397 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')),nil,'-') else erb_templates[layout_name] ||= ERB.new(File.read(File.join(path, layout_name + '.html.erb')),nil,'-') end erb = if no_template_cache ERB.new(File.read(File.join(path, name + '.html.erb')),nil,'-') else erb_templates[name] ||= ERB.new(File.read(File.join(path, name + '.html.erb')),nil,'-') 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 puts $! puts $@ '*** TEMPLATE ERROR ***' end end |
.route(verb, path, opts = {}, &blk) ⇒ Object
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 |
# File 'lib/blix/rest/controller.rb', line 450 def route(verb, path, opts = {}, &blk) proc = lambda do |_path_params, _params, _req, _format, _response, | unless opts[:force] && (opts[:accept] == :*) check_format(opts[:accept], _format) end app = new(_path_params, _params, _req, _format, verb, _response, ) begin app.before(opts) response = app.instance_eval( &blk ) rescue raise ensure app.after(opts, response) end end RequestMapper.add_path(verb.to_s.upcase, path, opts, &proc) end |
.set_erb_root(dir) ⇒ Object
358 359 360 |
# File 'lib/blix/rest/controller.rb', line 358 def self.set_erb_root(dir) @_erb_root = dir end |
Instance Method Details
#_get_binding ⇒ Object
172 173 174 |
# File 'lib/blix/rest/controller.rb', line 172 def _get_binding binding end |
#_opt(opts, key) ⇒ Object
305 306 307 308 309 310 311 |
# File 'lib/blix/rest/controller.rb', line 305 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
301 302 303 |
# File 'lib/blix/rest/controller.rb', line 301 def _opt?(opts,key) opts.key?(key.to_sym) || opts.key?(key.to_s) end |
#add_headers(headers) ⇒ Object
197 198 199 |
# File 'lib/blix/rest/controller.rb', line 197 def add_headers(headers) @_response.headers.merge!(headers) end |
#after(_opts, response) ⇒ Object
a hook used to insert processing for after the method call. return a hash containing the response.
326 327 328 |
# File 'lib/blix/rest/controller.rb', line 326 def after(_opts, response) response end |
#auth_error(*params) ⇒ Object
234 235 236 237 238 239 240 241 242 243 |
# File 'lib/blix/rest/controller.rb', line 234 def auth_error(*params) if params[0].kind_of?(String) = params[0] opts = params[1] || {} else = nil opts = params[-1] || {} end raise AuthorizationError.new(,opts[:realm], opts[:type]) end |
#before(opts) ⇒ Object
a hook used to insert processing for before the method call
322 |
# File 'lib/blix/rest/controller.rb', line 322 def before(opts); end |
#body ⇒ Object
58 59 60 61 |
# File 'lib/blix/rest/controller.rb', line 58 def body @_body ||= env['rack.input'].read # env['rack.input'].rewindreq.POST #env["body"] end |
#body_hash ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/blix/rest/controller.rb', line 71 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 |
#env ⇒ Object
convenience methods
29 30 31 |
# File 'lib/blix/rest/controller.rb', line 29 def env @_env end |
#escape_javascript(javascript) ⇒ Object
escape javascript
221 222 223 224 225 226 227 |
# File 'lib/blix/rest/controller.rb', line 221 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_hash ⇒ Object
67 68 69 |
# File 'lib/blix/rest/controller.rb', line 67 def form_hash StringHash.new(req.POST) end |
#format ⇒ Object
88 89 90 |
# File 'lib/blix/rest/controller.rb', line 88 def format @_format end |
#full_path(path) ⇒ Object
add on the root path
140 141 142 |
# File 'lib/blix/rest/controller.rb', line 140 def full_path(path) RequestMapper.full_path(path) end |
#full_url(_path) ⇒ Object
the full url of this path.
145 146 147 |
# File 'lib/blix/rest/controller.rb', line 145 def full_url(_path) raise 'not yet implemented' end |
#get_basic_auth(realm = nil) ⇒ Object
extract the user and login from the basic authentication
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 |
# File 'lib/blix/rest/controller.rb', line 177 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(':') login = auth_parts[0] password = auth_parts[1] [login, password] end |
#get_cookie(name) ⇒ Object
245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
# File 'lib/blix/rest/controller.rb', line 245 def (name) = env['HTTP_COOKIE'] = name.length parts = &.split(';') value = nil parts&.reverse&.each do || .strip! if [0..] == name + '=' value = [ + 1..-1] break end end value end |
#get_data(field) ⇒ Object
84 85 86 |
# File 'lib/blix/rest/controller.rb', line 84 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
290 291 292 293 |
# File 'lib/blix/rest/controller.rb', line 290 def get_session_id(session_name, opts = {}) session_id = (session_name) session_id || refresh_session_id(session_name, opts) end |
#h(string) ⇒ Object
Escape ampersands, brackets and quotes to their HTML/XML entities.
216 217 218 |
# File 'lib/blix/rest/controller.rb', line 216 def h(string) string.to_s.gsub(ESCAPE_HTML_PATTERN) { |c| ESCAPE_HTML[c] } end |
#logger ⇒ Object
38 39 40 |
# File 'lib/blix/rest/controller.rb', line 38 def logger Blix::Rest.logger end |
#method ⇒ Object
131 132 133 |
# File 'lib/blix/rest/controller.rb', line 131 def method env['REQUEST_METHOD'].downcase end |
#mode_development? ⇒ Boolean
50 51 52 |
# File 'lib/blix/rest/controller.rb', line 50 def mode_development? rack_env == 'development' end |
#mode_production? ⇒ Boolean
54 55 56 |
# File 'lib/blix/rest/controller.rb', line 54 def mode_production? rack_env == 'production' end |
#mode_test? ⇒ Boolean
46 47 48 |
# File 'lib/blix/rest/controller.rb', line 46 def mode_test? rack_env == 'test' end |
#params ⇒ Object
100 101 102 |
# File 'lib/blix/rest/controller.rb', line 100 def params @_params ||= StringHash.new(@_query_params,@_path_params) end |
#path ⇒ Object
63 64 65 |
# File 'lib/blix/rest/controller.rb', line 63 def path req.path end |
#path_for(path) ⇒ Object
115 116 117 |
# File 'lib/blix/rest/controller.rb', line 115 def path_for(path) File.join(RequestMapper.path_root, path) end |
#path_params ⇒ Object
96 97 98 |
# File 'lib/blix/rest/controller.rb', line 96 def path_params @_path_params end |
#post_params ⇒ Object
104 105 106 107 108 109 110 111 112 113 |
# File 'lib/blix/rest/controller.rb', line 104 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_params ⇒ Object
92 93 94 |
# File 'lib/blix/rest/controller.rb', line 92 def query_params @_query_params end |
#rack_env ⇒ Object
42 43 44 |
# File 'lib/blix/rest/controller.rb', line 42 def rack_env ENV['RACK_ENV'] end |
#rawjson(str) ⇒ Object
168 169 170 |
# File 'lib/blix/rest/controller.rb', line 168 def rawjson(str) RawJsonString.new(str) end |
#redirect(path, status = 302) ⇒ Object Also known as: redirect_to
149 150 151 |
# File 'lib/blix/rest/controller.rb', line 149 def redirect(path, status = 302) raise ServiceError.new(nil, status, 'Location' => path) end |
#refresh_session_id(session_name, opts = {}) ⇒ Object
generate an new session_id for the current session
296 297 298 299 |
# File 'lib/blix/rest/controller.rb', line 296 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
164 165 166 |
# File 'lib/blix/rest/controller.rb', line 164 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
160 161 162 |
# File 'lib/blix/rest/controller.rb', line 160 def render_erb(template_name, opts = {}) self.class.render_erb(template_name, self, opts) end |
#req ⇒ Object
123 124 125 |
# File 'lib/blix/rest/controller.rb', line 123 def req @_req end |
#request_ip ⇒ Object
155 156 157 |
# File 'lib/blix/rest/controller.rb', line 155 def request_ip req.ip end |
#send_error(message, status = nil, headers = nil) ⇒ Object
send a (default) error
230 231 232 |
# File 'lib/blix/rest/controller.rb', line 230 def send_error(, status = nil, headers = nil) raise ServiceError.new(, status, headers) end |
#server_options ⇒ Object
options that were passed to the server at create time.
34 35 36 |
# File 'lib/blix/rest/controller.rb', line 34 def end |
#session ⇒ Object
135 136 137 |
# File 'lib/blix/rest/controller.rb', line 135 def session req.session end |
#set_status(value) ⇒ Object
193 194 195 |
# File 'lib/blix/rest/controller.rb', line 193 def set_status(value) @_response.status = value end |
#store_cookie(name, value, opts = {}) ⇒ Object
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
# File 'lib/blix/rest/controller.rb', line 260 def (name, value, opts={}) = String.new("#{name}=#{value}") << '; Secure' if _opt?(opts,:secure) << '; HttpOnly' if _opt?(opts,:http) << "; HostOnly=#{_opt(opts,:hostOnly)}" if _opt?(opts,:hostOnly) << "; Expires=#{_opt(opts,:expires).httpdate}" if _opt?(opts,:expires) << "; Max-Age=#{_opt(opts,:max_age)}" if _opt?(opts,:max_age) << "; Domain=#{_opt(opts,:domain)}" if _opt?(opts,:domain) << "; Path=#{_opt(opts,:path)}" if _opt?(opts,:path) if policy = _opt(opts,:samesite) << '; SameSite=Strict' if policy.to_s.downcase == 'strict' << '; SameSite=Lax' if policy.to_s.downcase == 'lax' << '; SameSite=None' if policy.to_s.downcase == 'none' end ||= {} [name] = # 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'] = .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.
314 315 316 |
# File 'lib/blix/rest/controller.rb', line 314 def store_session_id(session_name, session_id, opts = {}) (session_name, session_id, opts) end |
#url_for(path) ⇒ Object
119 120 121 |
# File 'lib/blix/rest/controller.rb', line 119 def url_for(path) req.base_url + path_for(path) end |
#verb ⇒ Object
127 128 129 |
# File 'lib/blix/rest/controller.rb', line 127 def verb @_verb end |