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
-
.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.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/grape/endpoint.rb', line 35 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
.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.
24 25 26 27 28 29 30 31 32 |
# File 'lib/grape/endpoint.rb', line 24 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.
295 296 297 298 299 300 301 |
# File 'lib/grape/endpoint.rb', line 295 def body(value = nil) if value @body = value else @body end end |
#call(env) ⇒ Object
144 145 146 |
# File 'lib/grape/endpoint.rb', line 144 def call(env) dup.call!(env) end |
#call!(env) ⇒ Object
148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/grape/endpoint.rb', line 148 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
137 138 139 140 141 142 |
# File 'lib/grape/endpoint.rb', line 137 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
269 270 271 |
# File 'lib/grape/endpoint.rb', line 269 def content_type(val) header('Content-Type', val) end |
#cookies ⇒ Object
Set or get a cookie
281 282 283 |
# File 'lib/grape/endpoint.rb', line 281 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
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/grape/endpoint.rb', line 170 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.
367 368 369 370 371 372 373 |
# File 'lib/grape/endpoint.rb', line 367 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.
216 217 218 219 |
# File 'lib/grape/endpoint.rb', line 216 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.
260 261 262 263 264 265 266 |
# File 'lib/grape/endpoint.rb', line 260 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
58 59 60 61 62 63 64 |
# File 'lib/grape/endpoint.rb', line 58 def method_name [[:method], Namespace.joined_space(settings), settings.gather(:mount_path).join('/'), [:path].join('/') ].join(" ") end |
#mount_in(route_set) ⇒ Object
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/grape/endpoint.rb', line 70 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
133 134 135 |
# File 'lib/grape/endpoint.rb', line 133 def namespace @namespace ||= Namespace.joined_space_path(settings) end |
#prepare_path(path) ⇒ Object
129 130 131 |
# File 'lib/grape/endpoint.rb', line 129 def prepare_path(path) Path.prepare(path, namespace, settings) end |
#prepare_routes ⇒ Object
89 90 91 92 93 94 95 96 97 98 99 100 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 |
# File 'lib/grape/endpoint.rb', line 89 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.
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 |
# File 'lib/grape/endpoint.rb', line 318 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 first object in the collection object_instance = object.respond_to?(:first) ? object.first : object object_instance.class.ancestors.each do |potential| entity_class ||= (settings[:representations] || {})[potential] end entity_class ||= object_instance.class.const_get(:Entity) if object_instance.class.const_defined?(:Entity) && object_instance.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.
226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/grape/endpoint.rb', line 226 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
54 55 56 |
# File 'lib/grape/endpoint.rb', line 54 def require_option(, key) raise Grape::Exceptions::MissingOption.new(key) unless .has_key?(key) end |
#route ⇒ Object
Returns route information for the current request.
361 362 363 |
# File 'lib/grape/endpoint.rb', line 361 def route env["rack.routing_args"][:route_info] end |
#routes ⇒ Object
66 67 68 |
# File 'lib/grape/endpoint.rb', line 66 def routes @routes ||= endpoints ? endpoints.collect(&:routes).flatten : prepare_routes end |
#status(status = nil) ⇒ Object
Set or retrieve the HTTP status code.
244 245 246 247 248 249 250 251 252 253 254 255 256 |
# File 'lib/grape/endpoint.rb', line 244 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.
207 208 209 |
# File 'lib/grape/endpoint.rb', line 207 def version env['api.version'] end |