Class: Grape::Endpoint
- Inherits:
-
Object
- Object
- Grape::Endpoint
- Defined in:
- lib/grape/endpoint.rb
Overview
An Endpoint is the proxy scope in which all routing
blocks are executed. In other words, any methods
on the instance level of this class may be called
from inside a get
, post
, etc.
Instance Attribute Summary collapse
-
#block ⇒ Object
Returns the value of attribute block.
-
#env ⇒ Object
readonly
Returns the value of attribute env.
-
#headers ⇒ Object
readonly
Returns the value of attribute headers.
-
#options ⇒ Object
Returns the value of attribute options.
-
#params ⇒ Object
readonly
Returns the value of attribute params.
-
#request ⇒ Object
readonly
Returns the value of attribute request.
-
#settings ⇒ Object
Returns the value of attribute settings.
-
#source ⇒ Object
Returns the value of attribute source.
Class Method Summary collapse
- .before_each(new_setup = false, &block) ⇒ Object
-
.generate_api_method(method_name, &block) ⇒ Proc
private
Create an UnboundMethod that is appropriate for executing an endpoint route.
Instance Method Summary collapse
-
#body(value = nil) ⇒ Object
Allows you to define the response body as something other than the return value.
- #call(env) ⇒ Object
- #call!(env) ⇒ Object
- #compile_path(prepared_path, anchor = true, requirements = {}) ⇒ Object
-
#content_type(val) ⇒ Object
Set response content-type.
-
#cookies ⇒ Object
Set or get a cookie.
-
#declared(params, options = {}, declared_params = nil) ⇒ Object
A filtering method that will return a hash consisting only of keys that have been declared by a
params
statement against the current/target endpoint or parent namespaces. -
#endpoints ⇒ Object
Return the collection of endpoints within this endpoint.
-
#error!(message, status = nil, headers = nil) ⇒ Object
End the request and display an error to the end user with the specified message.
-
#header(key = nil, val = nil) ⇒ Object
Set an individual header or retrieve all headers that have been set.
-
#initialize(settings, options = {}, &block) ⇒ Endpoint
constructor
A new instance of Endpoint.
- #method_name ⇒ Object
- #mount_in(route_set) ⇒ Object
- #namespace ⇒ Object
- #prepare_path(path) ⇒ Object
- #prepare_routes ⇒ Object
-
#present(*args) ⇒ Object
Allows you to make use of Grape Entities by setting the response body to the serializable hash of the entity provided in the
:with
option. -
#redirect(url, options = {}) ⇒ Object
Redirect to a new url.
- #require_option(options, key) ⇒ Object
-
#route ⇒ Object
Returns route information for the current request.
- #routes ⇒ Object
-
#status(status = nil) ⇒ Object
Set or retrieve the HTTP status code.
-
#version ⇒ Object
The API version as specified in the URL.
Constructor Details
#initialize(settings, options = {}, &block) ⇒ Endpoint
Returns a new instance of Endpoint.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/grape/endpoint.rb', line 47 def initialize(settings, = {}, &block) require_option(, :path) require_option(, :method) @settings = settings @options = @options[:path] = Array([:path]) @options[:path] << '/' if [:path].empty? @options[:method] = Array([:method]) @options[:route_options] ||= {} if block_given? @source = block @block = self.class.generate_api_method(method_name, &block) end end |
Instance Attribute Details
#block ⇒ Object
Returns the value of attribute block.
7 8 9 |
# File 'lib/grape/endpoint.rb', line 7 def block @block end |
#env ⇒ Object (readonly)
Returns the value of attribute env.
8 9 10 |
# File 'lib/grape/endpoint.rb', line 8 def env @env end |
#headers ⇒ Object (readonly)
Returns the value of attribute headers.
8 9 10 |
# File 'lib/grape/endpoint.rb', line 8 def headers @headers end |
#options ⇒ Object
Returns the value of attribute options.
7 8 9 |
# File 'lib/grape/endpoint.rb', line 7 def @options end |
#params ⇒ Object (readonly)
Returns the value of attribute params.
8 9 10 |
# File 'lib/grape/endpoint.rb', line 8 def params @params end |
#request ⇒ Object (readonly)
Returns the value of attribute request.
8 9 10 |
# File 'lib/grape/endpoint.rb', line 8 def request @request end |
#settings ⇒ Object
Returns the value of attribute settings.
7 8 9 |
# File 'lib/grape/endpoint.rb', line 7 def settings @settings end |
#source ⇒ Object
Returns the value of attribute source.
7 8 9 |
# File 'lib/grape/endpoint.rb', line 7 def source @source end |
Class Method Details
.before_each(new_setup = false, &block) ⇒ Object
11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/grape/endpoint.rb', line 11 def before_each(new_setup = false, &block) if new_setup == false if block_given? @before_each = block else return @before_each end else @before_each = new_setup end end |
.generate_api_method(method_name, &block) ⇒ Proc
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Create an UnboundMethod that is appropriate for executing an endpoint route.
The unbound method allows explicit calls to +return+ without raising a +LocalJumpError+. The method will be removed, but a +Proc+ reference to it will be returned. The returned +Proc+ expects a single argument: the instance of +Endpoint+ to bind to the method during the call.
36 37 38 39 40 41 42 43 44 |
# File 'lib/grape/endpoint.rb', line 36 def generate_api_method(method_name, &block) if instance_methods.include?(method_name.to_sym) || instance_methods.include?(method_name.to_s) raise NameError.new("method #{method_name.inspect} already exists and cannot be used as an unbound method name") end define_method(method_name, &block) method = instance_method(method_name) remove_method(method_name) proc { |endpoint_instance| method.bind(endpoint_instance).call } end |
Instance Method Details
#body(value = nil) ⇒ Object
Allows you to define the response body as something other than the return value.
306 307 308 309 310 311 312 |
# File 'lib/grape/endpoint.rb', line 306 def body(value = nil) if value @body = value else @body end end |
#call(env) ⇒ Object
155 156 157 |
# File 'lib/grape/endpoint.rb', line 155 def call(env) dup.call!(env) end |
#call!(env) ⇒ Object
159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/grape/endpoint.rb', line 159 def call!(env) extend helpers env['api.endpoint'] = self if [:app] [:app].call(env) else builder = build_middleware builder.run [:app] || lambda { |arg| run(arg) } builder.call(env) end end |
#compile_path(prepared_path, anchor = true, requirements = {}) ⇒ Object
148 149 150 151 152 153 |
# File 'lib/grape/endpoint.rb', line 148 def compile_path(prepared_path, anchor = true, requirements = {}) = {} [:version] = /#{settings[:version].join('|')}/ if settings[:version] .merge!(requirements) Rack::Mount::Strexp.compile(prepared_path, , %w( / . ? ), anchor) end |
#content_type(val) ⇒ Object
Set response content-type
280 281 282 |
# File 'lib/grape/endpoint.rb', line 280 def content_type(val) header('Content-Type', val) end |
#cookies ⇒ Object
Set or get a cookie
292 293 294 |
# File 'lib/grape/endpoint.rb', line 292 def @cookies ||= Cookies.new end |
#declared(params, options = {}, declared_params = nil) ⇒ Object
A filtering method that will return a hash
consisting only of keys that have been declared by a
params
statement against the current/target endpoint or parent
namespaces
options. :include_parent_namespaces
defaults to true, hence must be set to false if
you want only to return params declared against the current/target endpoint
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/grape/endpoint.rb', line 181 def declared(params, = {}, declared_params = nil) [:include_missing] = true unless .key?(:include_missing) [:include_parent_namespaces] = true unless .key?(:include_parent_namespaces) if declared_params.nil? declared_params = ![:include_parent_namespaces] ? settings[:declared_params] : settings.gather(:declared_params) end unless declared_params raise ArgumentError, "Tried to filter for declared parameters but none exist." end if params.is_a? Array params.map do |param| declared(param || {}, , declared_params) end else declared_params.inject({}) do |hash, key| key = { key => nil } unless key.is_a? Hash key.each_pair do |parent, children| output_key = [:stringify] ? parent.to_s : parent.to_sym if params.key?(parent) || [:include_missing] hash[output_key] = if children declared(params[parent] || {}, , Array(children)) else params[parent] end end end hash end end end |
#endpoints ⇒ Object
Return the collection of endpoints within this endpoint. This is the case when an Grape::API mounts another Grape::API.
382 383 384 385 386 387 388 |
# File 'lib/grape/endpoint.rb', line 382 def endpoints if [:app] && [:app].respond_to?(:endpoints) [:app].endpoints else nil end end |
#error!(message, status = nil, headers = nil) ⇒ Object
End the request and display an error to the end user with the specified message.
227 228 229 230 |
# File 'lib/grape/endpoint.rb', line 227 def error!(, status = nil, headers = nil) status = settings[:default_error_status] unless status throw :error, message: , status: status, headers: headers end |
#header(key = nil, val = nil) ⇒ Object
Set an individual header or retrieve all headers that have been set.
271 272 273 274 275 276 277 |
# File 'lib/grape/endpoint.rb', line 271 def header(key = nil, val = nil) if key val ? @header[key.to_s] = val : @header.delete(key.to_s) else @header end end |
#method_name ⇒ Object
70 71 72 73 74 75 76 |
# File 'lib/grape/endpoint.rb', line 70 def method_name [[:method], Namespace.joined_space(settings), settings.gather(:mount_path).join('/'), [:path].join('/') ].join(" ") end |
#mount_in(route_set) ⇒ Object
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/grape/endpoint.rb', line 82 def mount_in(route_set) if endpoints endpoints.each { |e| e.mount_in(route_set) } else routes.each do |route| methods = [route.route_method] if !settings[:do_not_route_head] && route.route_method == "GET" methods << "HEAD" end methods.each do |method| route_set.add_route(self, { path_info: route.route_compiled, request_method: method }, route_info: route) end end end end |
#namespace ⇒ Object
144 145 146 |
# File 'lib/grape/endpoint.rb', line 144 def namespace @namespace ||= Namespace.joined_space_path(settings) end |
#prepare_path(path) ⇒ Object
140 141 142 |
# File 'lib/grape/endpoint.rb', line 140 def prepare_path(path) Path.prepare(path, namespace, settings) end |
#prepare_routes ⇒ Object
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/grape/endpoint.rb', line 101 def prepare_routes routes = [] [:method].each do |method| [:path].each do |path| prepared_path = prepare_path(path) anchor = [:route_options][:anchor] anchor = anchor.nil? ? true : anchor endpoint_requirements = [:route_options][:requirements] || {} all_requirements = (settings.gather(:namespace).map(&:requirements) << endpoint_requirements) requirements = all_requirements.reduce({}) do |base_requirements, single_requirements| base_requirements.merge!(single_requirements) end path = compile_path(prepared_path, anchor && ![:app], requirements) regex = Rack::Mount::RegexpWithNamedGroups.new(path) path_params = {} # named parameters in the api path named_params = regex.named_captures.map { |nc| nc[0] } - %w(version format) named_params.each { |named_param| path_params[named_param] = "" } # route parameters declared via desc or appended to the api declaration route_params = ([:route_options][:params] || {}) path_params.merge!(route_params) request_method = (method.to_s.upcase unless method == :any) routes << Route.new([:route_options].clone.merge( prefix: settings[:root_prefix], version: settings[:version] ? settings[:version].join('|') : nil, namespace: namespace, method: request_method, path: prepared_path, params: path_params, compiled: path )) end end routes end |
#present(*args) ⇒ Object
Allows you to make use of Grape Entities by setting
the response body to the serializable hash of the
entity provided in the :with
option. This has the
added benefit of automatically passing along environment
and version information to the serialization, making it
very easy to do conditional exposures. See Entity docs
for more info.
329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 |
# File 'lib/grape/endpoint.rb', line 329 def present(*args) = args.count > 1 ? args. : {} key, object = if args.count == 2 && args.first.is_a?(Symbol) args else [nil, args.first] end entity_class = .delete(:with) if entity_class.nil? # entity class not explicitely defined, auto-detect from relation#klass or first object in the collection object_class = if object.respond_to?(:klass) object.klass else object.respond_to?(:first) ? object.first.class : object.class end object_class.ancestors.each do |potential| entity_class ||= (settings[:representations] || {})[potential] end entity_class ||= object_class.const_get(:Entity) if object_class.const_defined?(:Entity) && object_class.const_get(:Entity).respond_to?(:represent) end root = .delete(:root) representation = if entity_class = { env: env } [:version] = env['api.version'] if env['api.version'] entity_class.represent(object, .merge()) else object end representation = { root => representation } if root representation = (@body || {}).merge(key => representation) if key body representation end |
#redirect(url, options = {}) ⇒ Object
Redirect to a new url.
237 238 239 240 241 242 243 244 245 246 247 248 249 250 |
# File 'lib/grape/endpoint.rb', line 237 def redirect(url, = {}) = { permanent: false }.merge() if [:permanent] status 301 else if env['HTTP_VERSION'] == 'HTTP/1.1' && request.request_method.to_s.upcase != "GET" status 303 else status 302 end end header "Location", url body "" end |
#require_option(options, key) ⇒ Object
66 67 68 |
# File 'lib/grape/endpoint.rb', line 66 def require_option(, key) raise Grape::Exceptions::MissingOption.new(key) unless .key?(key) end |
#route ⇒ Object
Returns route information for the current request.
376 377 378 |
# File 'lib/grape/endpoint.rb', line 376 def route env["rack.routing_args"][:route_info] end |
#routes ⇒ Object
78 79 80 |
# File 'lib/grape/endpoint.rb', line 78 def routes @routes ||= endpoints ? endpoints.collect(&:routes).flatten : prepare_routes end |
#status(status = nil) ⇒ Object
Set or retrieve the HTTP status code.
255 256 257 258 259 260 261 262 263 264 265 266 267 |
# File 'lib/grape/endpoint.rb', line 255 def status(status = nil) if status @status = status else return @status if @status case request.request_method.to_s.upcase when 'POST' 201 else 200 end end end |
#version ⇒ Object
The API version as specified in the URL.
218 219 220 |
# File 'lib/grape/endpoint.rb', line 218 def version env['api.version'] end |