class Blix::Rest::Controller
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 options in the route eg post '/myform' :accept=>[:html] # this will only accept html requests.
Constants
- ESCAPE_HTML
the following is copied from Rack::Utils
- ESCAPE_HTML_PATTERN
- JS_ESCAPE_MAP
Public Class Methods
default method .. will be overridden with erb_path method
# File lib/blix/rest/controller.rb, line 431 def __erb_path nil end
# File lib/blix/rest/controller.rb, line 493 def all(*a, &b) route 'ALL', *a, &b end
# 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
# File lib/blix/rest/controller.rb, line 489 def delete(*a, &b) route 'DELETE', *a, &b end
redefine the __erb_path
method for this and derived classes
# File lib/blix/rest/controller.rb, line 436 def erb_dir(val) str = "def self.__erb_path;\"#{val}\";end" class_eval str end
# 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
cache templates here
# File lib/blix/rest/controller.rb, line 354 def self.erb_templates @_erb ||= {} end
# File lib/blix/rest/controller.rb, line 469 def get(*a, &b) route 'GET', *a, &b end
# File lib/blix/rest/controller.rb, line 473 def head(*a, &b) route 'HEAD', *a, &b end
# File lib/blix/rest/controller.rb, line 332 def initialize(path_params, _params, req, format, verb, response, server_options) @_req = req @_env = req.env @_query_params = StringHash.new(req.GET) @_path_params = StringHash.new(path_params) @_format = format @_verb = verb @_response = response @_server_options = server_options end
do not cache templates in development mode
# 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
# File lib/blix/rest/controller.rb, line 349 def self.no_template_cache=(val) @_no_template_cache = val end
# File lib/blix/rest/controller.rb, line 497 def options(*a, &b) route 'OPTIONS', *a, &b end
# File lib/blix/rest/controller.rb, line 485 def patch(*a, &b) route 'PATCH', *a, &b end
# File lib/blix/rest/controller.rb, line 477 def post(*a, &b) route 'POST', *a, &b end
# File lib/blix/rest/controller.rb, line 481 def put(*a, &b) route 'PUT', *a, &b end
render a string within a layout.
# 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
# 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
# File lib/blix/rest/controller.rb, line 450 def route(verb, path, opts = {}, &blk) proc = lambda do |_path_params, _params, _req, _format, _response, server_options| unless opts[:force] && (opts[:accept] == :*) check_format(opts[:accept], _format) end app = new(_path_params, _params, _req, _format, verb, _response, server_options) 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
# File lib/blix/rest/controller.rb, line 358 def self.set_erb_root(dir) @_erb_root = dir end
Public Instance Methods
# File lib/blix/rest/controller.rb, line 172 def _get_binding binding end
# 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
# File lib/blix/rest/controller.rb, line 301 def _opt?(opts,key) opts.key?(key.to_sym) || opts.key?(key.to_s) end
# File lib/blix/rest/controller.rb, line 197 def add_headers(headers) @_response.headers.merge!(headers) end
a hook used to insert processing for after the method call. return a hash containing the response.
# File lib/blix/rest/controller.rb, line 326 def after(_opts, response) response end
# File lib/blix/rest/controller.rb, line 234 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
a hook used to insert processing for before the method call
# File lib/blix/rest/controller.rb, line 322 def before(opts); end
# File lib/blix/rest/controller.rb, line 58 def body @_body ||= env['rack.input'].read # env['rack.input'].rewindreq.POST #env["body"] end
# 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
# File lib/blix/rest/controller.rb, line 29 def env @_env end
escape javascript
# 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
# File lib/blix/rest/controller.rb, line 67 def form_hash StringHash.new(req.POST) end
# File lib/blix/rest/controller.rb, line 88 def format @_format end
add on the root path
# File lib/blix/rest/controller.rb, line 140 def full_path(path) RequestMapper.full_path(path) end
the full url of this path.
# File lib/blix/rest/controller.rb, line 145 def full_url(_path) raise 'not yet implemented' end
extract the user and login from the basic authentication
# 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
# File lib/blix/rest/controller.rb, line 84 def get_data(field) body_hash['data'] && body_hash['data'][field] end
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
# File lib/blix/rest/controller.rb, line 290 def get_session_id(session_name, opts = {}) session_id = get_cookie(session_name) session_id || refresh_session_id(session_name, opts) end
Escape ampersands, brackets and quotes to their HTML/XML entities.
# File lib/blix/rest/controller.rb, line 216 def h(string) string.to_s.gsub(ESCAPE_HTML_PATTERN) { |c| ESCAPE_HTML[c] } end
# File lib/blix/rest/controller.rb, line 38 def logger Blix::Rest.logger end
# File lib/blix/rest/controller.rb, line 131 def method env['REQUEST_METHOD'].downcase end
# File lib/blix/rest/controller.rb, line 50 def mode_development? rack_env == 'development' end
# File lib/blix/rest/controller.rb, line 54 def mode_production? rack_env == 'production' end
# File lib/blix/rest/controller.rb, line 46 def mode_test? rack_env == 'test' end
# File lib/blix/rest/controller.rb, line 100 def params @_params ||= StringHash.new(@_query_params,@_path_params) end
# File lib/blix/rest/controller.rb, line 63 def path req.path end
# File lib/blix/rest/controller.rb, line 115 def path_for(path) File.join(RequestMapper.path_root, path) end
# File lib/blix/rest/controller.rb, line 96 def path_params @_path_params end
# 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
# File lib/blix/rest/controller.rb, line 92 def query_params @_query_params end
# File lib/blix/rest/controller.rb, line 42 def rack_env ENV['RACK_ENV'] end
# File lib/blix/rest/controller.rb, line 168 def rawjson(str) RawJsonString.new(str) end
# File lib/blix/rest/controller.rb, line 149 def redirect(path, status = 302) raise ServiceError.new(nil, status, 'Location' => path) end
generate an new session_id for the current session
# 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
# File lib/blix/rest/controller.rb, line 164 def render(text, opts = {}) self.class.render_erb(text, self, opts) end
render an erb template with the variables in the controller
# File lib/blix/rest/controller.rb, line 160 def render_erb(template_name, opts = {}) self.class.render_erb(template_name, self, opts) end
# File lib/blix/rest/controller.rb, line 123 def req @_req end
# File lib/blix/rest/controller.rb, line 155 def request_ip req.ip end
send a (default) error
# File lib/blix/rest/controller.rb, line 230 def send_error(message, status = nil, headers = nil) raise ServiceError.new(message, status, headers) end
options that were passed to the server at create time.
# File lib/blix/rest/controller.rb, line 34 def server_options @_server_options end
# File lib/blix/rest/controller.rb, line 135 def session req.session end
# File lib/blix/rest/controller.rb, line 193 def set_status(value) @_response.status = value end
set the cookie header that stores the session_id on the browser.
# File lib/blix/rest/controller.rb, line 314 def store_session_id(session_name, session_id, opts = {}) store_cookie(session_name, session_id, opts) end
# File lib/blix/rest/controller.rb, line 119 def url_for(path) req.base_url + path_for(path) end
# File lib/blix/rest/controller.rb, line 127 def verb @_verb end