Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(210)

Side by Side Diff: third_party/google-endpoints/endpoints/errors.py

Issue 2666783008: Add google-endpoints to third_party/. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2016 Google Inc. All Rights Reserved.
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14
15 """Error handling and exceptions used in the local Cloud Endpoints server."""
16
17 # pylint: disable=g-bad-name
18 import json
19 import logging
20
21 import generated_error_info
22
23
24 __all__ = ['BackendError',
25 'BasicTypeParameterError',
26 'EnumRejectionError',
27 'InvalidParameterError',
28 'RequestError',
29 'RequestRejectionError']
30
31 _INVALID_ENUM_TEMPLATE = 'Invalid string value: %r. Allowed values: %r'
32 _INVALID_BASIC_PARAM_TEMPLATE = 'Invalid %s value: %r.'
33
34
35 class RequestError(Exception):
36 """Base class for errors that happen while processing a request."""
37
38 def status_code(self):
39 """HTTP status code number associated with this error.
40
41 Subclasses must implement this, returning an integer with the status
42 code number for the error.
43
44 Example: 400
45
46 Raises:
47 NotImplementedError: Subclasses must override this function.
48 """
49 raise NotImplementedError
50
51 def message(self):
52 """Text message explaining the error.
53
54 Subclasses must implement this, returning a string that explains the
55 error.
56
57 Raises:
58 NotImplementedError: Subclasses must override this function.
59 """
60 raise NotImplementedError
61
62 def reason(self):
63 """Get the reason for the error.
64
65 Error reason is a custom string in the Cloud Endpoints server. When
66 possible, this should match the reason that the live server will generate,
67 based on the error's status code. If this returns None, the error formatter
68 will attempt to generate a reason from the status code.
69
70 Returns:
71 None, by default. Subclasses can override this if they have a specific
72 error reason.
73 """
74 raise NotImplementedError
75
76 def domain(self):
77 """Get the domain for this error.
78
79 Returns:
80 The string 'global' by default. Subclasses can override this if they have
81 a different domain.
82 """
83 return 'global'
84
85 def extra_fields(self):
86 """Return a dict of extra fields to add to the error response.
87
88 Some errors have additional information. This provides a way for subclasses
89 to provide that information.
90
91 Returns:
92 None, by default. Subclasses can return a dict with values to add
93 to the error response.
94 """
95 return None
96
97 def __format_error(self, error_list_tag):
98 """Format this error into a JSON response.
99
100 Args:
101 error_list_tag: A string specifying the name of the tag to use for the
102 error list.
103
104 Returns:
105 A dict containing the reformatted JSON error response.
106 """
107 error = {'domain': self.domain(),
108 'reason': self.reason(),
109 'message': self.message()}
110 error.update(self.extra_fields() or {})
111 return {'error': {error_list_tag: [error],
112 'code': self.status_code(),
113 'message': self.message()}}
114
115 def rest_error(self):
116 """Format this error into a response to a REST request.
117
118 Returns:
119 A string containing the reformatted error response.
120 """
121 error_json = self.__format_error('errors')
122 return json.dumps(error_json, indent=1, sort_keys=True)
123
124 def rpc_error(self):
125 """Format this error into a response to a JSON RPC request.
126
127
128 Returns:
129 A dict containing the reformatted JSON error response.
130 """
131 return self.__format_error('data')
132
133
134 class RequestRejectionError(RequestError):
135 """Base class for invalid/rejected requests.
136
137 To be raised when parsing the request values and comparing them against the
138 generated discovery document.
139 """
140
141 def status_code(self):
142 return 400
143
144
145 class InvalidParameterError(RequestRejectionError):
146 """Base class for invalid parameter errors.
147
148 Child classes only need to implement the message() function.
149 """
150
151 def __init__(self, parameter_name, value):
152 """Constructor for InvalidParameterError.
153
154 Args:
155 parameter_name: String; the name of the parameter which had a value
156 rejected.
157 value: The actual value passed in for the parameter. Usually string.
158 """
159 super(InvalidParameterError, self).__init__()
160 self.parameter_name = parameter_name
161 self.value = value
162
163 def reason(self):
164 """Returns the server's reason for this error.
165
166 Returns:
167 A string containing a short error reason.
168 """
169 return 'invalidParameter'
170
171 def extra_fields(self):
172 """Returns extra fields to add to the error response.
173
174 Returns:
175 A dict containing extra fields to add to the error response.
176 """
177 return {'locationType': 'parameter',
178 'location': self.parameter_name}
179
180
181 class BasicTypeParameterError(InvalidParameterError):
182 """Request rejection exception for basic types (int, float)."""
183
184 def __init__(self, parameter_name, value, type_name):
185 """Constructor for BasicTypeParameterError.
186
187 Args:
188 parameter_name: String; the name of the parameter which had a value
189 rejected.
190 value: The actual value passed in for the enum. Usually string.
191 type_name: Descriptive name of the data type expected.
192 """
193 super(BasicTypeParameterError, self).__init__(parameter_name, value)
194 self.type_name = type_name
195
196 def message(self):
197 """A descriptive message describing the error."""
198 return _INVALID_BASIC_PARAM_TEMPLATE % (self.type_name, self.value)
199
200
201 class EnumRejectionError(InvalidParameterError):
202 """Custom request rejection exception for enum values."""
203
204 def __init__(self, parameter_name, value, allowed_values):
205 """Constructor for EnumRejectionError.
206
207 Args:
208 parameter_name: String; the name of the enum parameter which had a value
209 rejected.
210 value: The actual value passed in for the enum. Usually string.
211 allowed_values: List of strings allowed for the enum.
212 """
213 super(EnumRejectionError, self).__init__(parameter_name, value)
214 self.allowed_values = allowed_values
215
216 def message(self):
217 """A descriptive message describing the error."""
218 return _INVALID_ENUM_TEMPLATE % (self.value, self.allowed_values)
219
220
221 class BackendError(RequestError):
222 """Exception raised when the backend returns an error code."""
223
224 def __init__(self, body, status):
225 super(BackendError, self).__init__()
226 # Convert backend error status to whatever the live server would return.
227 status_code = self._get_status_code(status)
228 self._error_info = generated_error_info.get_error_info(status_code)
229
230 try:
231 error_json = json.loads(body)
232 self._message = error_json.get('error_message')
233 except TypeError:
234 self._message = body
235
236 def _get_status_code(self, http_status):
237 """Get the HTTP status code from an HTTP status string.
238
239 Args:
240 http_status: A string containing a HTTP status code and reason.
241
242 Returns:
243 An integer with the status code number from http_status.
244 """
245 try:
246 return int(http_status.split(' ', 1)[0])
247 except TypeError:
248 logging.warning('Unable to find status code in HTTP status %r.',
249 http_status)
250 return 500
251
252 def status_code(self):
253 """Return the HTTP status code number for this error.
254
255 Returns:
256 An integer containing the status code for this error.
257 """
258 return self._error_info.http_status
259
260 def message(self):
261 """Return a descriptive message for this error.
262
263 Returns:
264 A string containing a descriptive message for this error.
265 """
266 return self._message
267
268 def reason(self):
269 """Return the short reason for this error.
270
271 Returns:
272 A string with the reason for this error.
273 """
274 return self._error_info.reason
275
276 def domain(self):
277 """Return the remapped domain for this error.
278
279 Returns:
280 A string containing the remapped domain for this error.
281 """
282 return self._error_info.domain
OLDNEW
« no previous file with comments | « third_party/google-endpoints/endpoints/endpointscfg.py ('k') | third_party/google-endpoints/endpoints/generated_error_info.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698