def error(context, request): """Catch server errors and trace them.""" logger.error(context, exc_info=True) message = '%s %s: %s' % (context.response.status_code, context.response.reason, context.response.text) if context.response.status_code == 400: response = http_error(httpexceptions.HTTPBadRequest(), errno=ERRORS.INVALID_PARAMETERS, message=message) elif context.response.status_code == 401: response = http_error(httpexceptions.HTTPUnauthorized(), errno=ERRORS.INVALID_AUTH_TOKEN, message=message) # Forget the current user credentials. response.headers.extend(forget(request)) elif context.response.status_code == 403: response = http_error(httpexceptions.HTTPForbidden(), errno=ERRORS.FORBIDDEN, message=message) elif context.response.status_code == 404: response = http_error(httpexceptions.HTTPNotFound(), errno=ERRORS.INVALID_RESOURCE_ID, message=message) else: response = service_unavailable(context, request) return reapply_cors(request, response)
def method_not_allowed(context, request): if context.content_type == 'application/json': return context response = http_error(context, errno=ERRORS.METHOD_NOT_ALLOWED, message="Method not allowed on this endpoint.") return reapply_cors(request, response)
def error(context, request): """Catch server errors and trace them.""" if isinstance(context, httpexceptions.Response): return reapply_cors(request, context) if isinstance(context, storage_exceptions.BackendError): logger.critical(context.original, exc_info=True) return service_unavailable(context, request) logger.error(context, exc_info=True) error_msg = "A programmatic error occured, developers have been informed." info = "https://github.com/mozilla-services/cliquet/issues/" response = http_error(httpexceptions.HTTPInternalServerError(), message=error_msg, info=info) return reapply_cors(request, response)
def service_unavailable(response, request): if response.content_type != 'application/json': error_msg = "Service unavailable due to high load, please retry later." response = http_error(response, errno=ERRORS.BACKEND, message=error_msg) retry_after = request.registry.settings['retry_after_seconds'] response.headers["Retry-After"] = encode_header('%s' % retry_after) return reapply_cors(request, response)
def service_unavailable(response, request): if response.content_type != 'application/json': error_msg = ("Service temporary unavailable " "due to overloading or maintenance, please retry later.") response = http_error(response, errno=ERRORS.BACKEND, message=error_msg) retry_after = request.registry.settings['retry_after_seconds'] response.headers["Retry-After"] = encode_header('%s' % retry_after) return reapply_cors(request, response)
def error(context, request): """Catch server errors and trace them.""" if isinstance(context, httpexceptions.Response): return reapply_cors(request, context) if isinstance(context, storage_exceptions.BackendError): logger.critical(context.original, exc_info=True) response = httpexceptions.HTTPServiceUnavailable() return service_unavailable(response, request) logger.error(context, exc_info=True) error_msg = "A programmatic error occured, developers have been informed." info = request.registry.settings['error_info_link'] response = http_error(httpexceptions.HTTPInternalServerError(), message=error_msg, info=info) return reapply_cors(request, response)
def service_unavailable(context, request): error_msg = "Service unavailable due to high load, please retry later." response = http_error(httpexceptions.HTTPServiceUnavailable(), errno=ERRORS.BACKEND, message=error_msg) retry_after = request.registry.settings['cliquet.retry_after_seconds'] response.headers["Retry-After"] = ('%s' % retry_after).encode("utf-8") return reapply_cors(request, response)
def response_error(context, request): """Catch response error from Sync and trace them.""" message = '%s %s: %s' % (context.response.status_code, context.response.reason, context.response.text) # XXX: Make sure these HTTPError exception are coming from SyncClient. statsd_count(request, "syncclient.status_code.%s" % context.response.status_code) if context.response.status_code in (400, 401, 403, 404): # For this code we also want to log the info about the error. logger.info(context, exc_info=True) # For this specific code we do not want to log the error. if context.response.status_code == 304: response = httpexceptions.HTTPNotModified() elif context.response.status_code == 400: response = http_error(httpexceptions.HTTPBadRequest(), errno=ERRORS.INVALID_PARAMETERS, message=message) elif context.response.status_code == 401: response = http_error(httpexceptions.HTTPUnauthorized(), errno=ERRORS.INVALID_AUTH_TOKEN, message=message) # Forget the current user credentials. response.headers.extend(forget(request)) elif context.response.status_code == 403: response = http_error(httpexceptions.HTTPForbidden(), errno=ERRORS.FORBIDDEN, message=message) elif context.response.status_code == 404: response = http_error(httpexceptions.HTTPNotFound(), errno=ERRORS.INVALID_RESOURCE_ID, message=message) elif context.response.status_code == 412: message = 'Resource was modified meanwhile' response = http_error(httpexceptions.HTTPPreconditionFailed(), errno=ERRORS.MODIFIED_MEANWHILE, message=message) else: # For this code we also want to log the error. logger.error(context, exc_info=True) response = service_unavailable( httpexceptions.HTTPServiceUnavailable(), request) request.response = response export_headers(context.response, request) return reapply_cors(request, response)
def default_bucket(request): if request.method.lower() == 'options': path = request.path.replace('default', 'unknown') subrequest = build_request(request, { 'method': 'OPTIONS', 'path': path }) return request.invoke_subrequest(subrequest) if getattr(request, 'prefixed_userid', None) is None: # Pass through the forbidden_view_config raise httpexceptions.HTTPForbidden() settings = request.registry.settings if asbool(settings['readonly']): raise httpexceptions.HTTPMethodNotAllowed() hmac_secret = settings['userid_hmac_secret'] # Build the user unguessable bucket_id UUID from its user_id digest = hmac_digest(hmac_secret, request.prefixed_userid) bucket_id = text_type(UUID(digest[:32])) path = request.path.replace('/buckets/default', '/buckets/%s' % bucket_id) querystring = request.url[(request.url.index(request.path) + len(request.path)):] # Make sure bucket exists create_bucket(request, bucket_id) # Make sure the collection exists create_collection(request, bucket_id) subrequest = build_request(request, { 'method': request.method, 'path': path + querystring, 'body': request.body }) subrequest.bound_data = request.bound_data try: response = request.invoke_subrequest(subrequest) except httpexceptions.HTTPException as error: if error.content_type == 'application/json': response = reapply_cors(subrequest, error) else: # Ask the upper level to format the error. raise error return response
def default_bucket(request): if request.method.lower() == 'options': path = request.path.replace('default', 'unknown') subrequest = build_request(request, { 'method': 'OPTIONS', 'path': path }) return request.invoke_subrequest(subrequest) if Authenticated not in request.effective_principals: # Pass through the forbidden_view_config raise httpexceptions.HTTPForbidden() settings = request.registry.settings if asbool(settings['readonly']): raise httpexceptions.HTTPMethodNotAllowed() bucket_id = request.default_bucket_id path = request.path.replace('/buckets/default', '/buckets/%s' % bucket_id) querystring = request.url[(request.url.index(request.path) + len(request.path)):] # Make sure bucket exists create_bucket(request, bucket_id) # Make sure the collection exists create_collection(request, bucket_id) subrequest = build_request(request, { 'method': request.method, 'path': path + querystring, 'body': request.body }) subrequest.bound_data = request.bound_data try: response = request.invoke_subrequest(subrequest) except httpexceptions.HTTPException as error: is_redirect = error.status_code < 400 if error.content_type == 'application/json' or is_redirect: response = reapply_cors(subrequest, error) else: # Ask the upper level to format the error. raise error return response
def default_bucket(request): if request.method.lower() == 'options': path = request.path.replace('default', 'unknown') subrequest = build_request(request, { 'method': 'OPTIONS', 'path': path }) return request.invoke_subrequest(subrequest) if getattr(request, 'prefixed_userid', None) is None: raise HTTPForbidden() # Pass through the forbidden_view_config settings = request.registry.settings hmac_secret = settings['userid_hmac_secret'] # Build the user unguessable bucket_id UUID from its user_id digest = hmac_digest(hmac_secret, request.prefixed_userid) bucket_id = text_type(UUID(digest[:32])) path = request.path.replace('/buckets/default', '/buckets/%s' % bucket_id) querystring = request.url[(request.url.index(request.path) + len(request.path)):] # Make sure bucket exists create_bucket(request, bucket_id) # Make sure the collection exists create_collection(request, bucket_id) subrequest = build_request(request, { 'method': request.method, 'path': path + querystring, 'body': request.body }) subrequest.bound_data = request.bound_data try: response = request.invoke_subrequest(subrequest) except HTTPException as error: if error.content_type == 'application/json': response = reapply_cors(subrequest, error) else: # Ask the upper level to format the error. raise error return response
def json_error_handler(errors): """Cornice JSON error handler, returning consistant JSON formatted errors from schema validation errors. This is meant to be used is custom services in your applications. .. code-block:: python upload = Service(name="upload", path='/upload', error_handler=errors.json_error_handler) .. warning:: Only the first error of the list is formatted in the response. (c.f. protocol). """ assert len(errors) != 0 sorted_errors = sorted(errors, key=lambda x: six.text_type(x['name'])) error = sorted_errors[0] name = error['name'] description = error['description'] if isinstance(description, six.binary_type): description = error['description'].decode('utf-8') if name is not None: if name in description: message = description else: message = '%(name)s in %(location)s: %(description)s' % error else: message = '%(location)s: %(description)s' % error response = http_error(httpexceptions.HTTPBadRequest(), code=errors.status, errno=ERRORS.INVALID_PARAMETERS.value, error='Invalid parameters', message=message, details=errors) response.status = errors.status response = reapply_cors(errors.request, response) return response
def default_bucket(request): if request.method.lower() == 'options': path = request.path.replace('default', 'unknown') subrequest = build_request(request, { 'method': 'OPTIONS', 'path': path }) return request.invoke_subrequest(subrequest) if getattr(request, 'prefixed_userid', None) is None: raise HTTPForbidden # Pass through the forbidden_view_config settings = request.registry.settings hmac_secret = settings['userid_hmac_secret'] # Build the user unguessable bucket_id UUID from its user_id digest = hmac_digest(hmac_secret, request.prefixed_userid) bucket_id = text_type(UUID(digest[:32])) path = request.path.replace('/buckets/default', '/buckets/%s' % bucket_id) querystring = request.url[(request.url.index(request.path) + len(request.path)):] # Make sure bucket exists create_bucket(request, bucket_id) # Make sure the collection exists create_collection(request, bucket_id) subrequest = build_request(request, { 'method': request.method, 'path': path + querystring, 'body': request.body }) subrequest.bound_data = request.bound_data try: response = request.invoke_subrequest(subrequest) except HTTPException as error: response = reapply_cors(subrequest, error) return response
def wrap_view(request, *args, **kwargs): response = view(request, *args, **kwargs) # We need to re-apply the CORS checks done by Cornice, since we're # recreating the response from scratch. return reapply_cors(request, response)
def method_not_allowed(context, request): response = http_error(httpexceptions.HTTPMethodNotAllowed(), errno=ERRORS.METHOD_NOT_ALLOWED, message="Method not allowed on this endpoint.") return reapply_cors(request, response)