forked from ruby-grape/grape
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrequest_response.rb
171 lines (143 loc) · 6.56 KB
/
request_response.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# frozen_string_literal: true
module Grape
module DSL
module RequestResponse
extend ActiveSupport::Concern
include Grape::DSL::Configuration
module ClassMethods
# Specify the default format for the API's serializers.
# May be `:json` or `:txt` (default).
def default_format(new_format = nil)
namespace_inheritable(:default_format, new_format.nil? ? nil : new_format.to_sym)
end
# Specify the format for the API's serializers.
# May be `:json`, `:xml`, `:txt`, etc.
def format(new_format = nil)
return namespace_inheritable(:format) unless new_format
symbolic_new_format = new_format.to_sym
namespace_inheritable(:format, symbolic_new_format)
namespace_inheritable(:default_error_formatter, Grape::ErrorFormatter.formatter_for(symbolic_new_format))
content_type = content_types[symbolic_new_format]
raise Grape::Exceptions::MissingMimeType.new(new_format) unless content_type
namespace_stackable(:content_types, symbolic_new_format => content_type)
end
# Specify a custom formatter for a content-type.
def formatter(content_type, new_formatter)
namespace_stackable(:formatters, content_type.to_sym => new_formatter)
end
# Specify a custom parser for a content-type.
def parser(content_type, new_parser)
namespace_stackable(:parsers, content_type.to_sym => new_parser)
end
# Specify a default error formatter.
def default_error_formatter(new_formatter_name = nil)
return namespace_inheritable(:default_error_formatter) unless new_formatter_name
new_formatter = Grape::ErrorFormatter.formatter_for(new_formatter_name)
namespace_inheritable(:default_error_formatter, new_formatter)
end
def error_formatter(format, options)
formatter = if options.is_a?(Hash) && options.key?(:with)
options[:with]
else
options
end
namespace_stackable(:error_formatters, format.to_sym => formatter)
end
# Specify additional content-types, e.g.:
# content_type :xls, 'application/vnd.ms-excel'
def content_type(key, val)
namespace_stackable(:content_types, key.to_sym => val)
end
# All available content types.
def content_types
c_types = namespace_stackable_with_hash(:content_types)
Grape::ContentTypes.content_types_for c_types
end
# Specify the default status code for errors.
def default_error_status(new_status = nil)
namespace_inheritable(:default_error_status, new_status)
end
# Allows you to rescue certain exceptions that occur to return
# a grape error rather than raising all the way to the
# server level.
#
# @example Rescue from custom exceptions
# class ExampleAPI < Grape::API
# class CustomError < StandardError; end
#
# rescue_from CustomError
# end
#
# @overload rescue_from(*exception_classes, **options)
# @param [Array] exception_classes A list of classes that you want to rescue, or
# the symbol :all to rescue from all exceptions.
# @param [Block] block Execution block to handle the given exception.
# @param [Hash] options Options for the rescue usage.
# @option options [Boolean] :backtrace Include a backtrace in the rescue response.
# @option options [Boolean] :rescue_subclasses Also rescue subclasses of exception classes
# @param [Proc] handler Execution proc to handle the given exception as an
# alternative to passing a block.
def rescue_from(*args, &block)
if args.last.is_a?(Proc)
handler = args.pop
elsif block
handler = block
end
options = args.extract_options!
raise ArgumentError, 'both :with option and block cannot be passed' if block && options.key?(:with)
handler ||= extract_with(options)
if args.include?(:all)
namespace_inheritable(:rescue_all, true)
namespace_inheritable(:all_rescue_handler, handler)
elsif args.include?(:grape_exceptions)
namespace_inheritable(:rescue_all, true)
namespace_inheritable(:rescue_grape_exceptions, true)
namespace_inheritable(:grape_exceptions_rescue_handler, handler)
else
handler_type =
case options[:rescue_subclasses]
when nil, true
:rescue_handlers
else
:base_only_rescue_handlers
end
namespace_reverse_stackable(handler_type, args.to_h { |arg| [arg, handler] })
end
namespace_stackable(:rescue_options, options)
end
# Allows you to specify a default representation entity for a
# class. This allows you to map your models to their respective
# entities once and then simply call `present` with the model.
#
# @example
# class ExampleAPI < Grape::API
# represent User, with: Entity::User
#
# get '/me' do
# present current_user # with: Entity::User is assumed
# end
# end
#
# Note that Grape will automatically go up the class ancestry to
# try to find a representing entity, so if you, for example, define
# an entity to represent `Object` then all presented objects will
# bubble up and utilize the entity provided on that `represent` call.
#
# @param model_class [Class] The model class that will be represented.
# @option options [Class] :with The entity class that will represent the model.
def represent(model_class, options)
raise Grape::Exceptions::InvalidWithOptionForRepresent.new unless options[:with].is_a?(Class)
namespace_stackable(:representations, model_class => options[:with])
end
private
def extract_with(options)
return unless options.key?(:with)
with_option = options.delete(:with)
return with_option if with_option.instance_of?(Proc)
return with_option.to_sym if with_option.instance_of?(Symbol) || with_option.instance_of?(String)
raise ArgumentError, "with: #{with_option.class}, expected Symbol, String or Proc"
end
end
end
end
end