def ows_response_tween(request, handler): """Tween that wraps any API request with appropriate dispatch of error conversion to handle formatting.""" try: result = handler(request) if hasattr(handler, OWS_TWEEN_HANDLED): if isinstance(result, Exception) and not isinstance( result, (HTTPSuccessful, HTTPRedirection)): raise result # let the previous tween handler handle this case return result # NOTE: # Handle exceptions from most explicit definitions to least explicit. # Exceptions in 'weaver.exceptions' sometimes derive from 'OWSException' to provide additional details. # Furthermore, 'OWSException' have extensive details with references to 'HTTPException' and 'pywps.exceptions'. except HTTPException as err: LOGGER.debug("http exception -> ows exception response.") # Use the same json formatter than OWSException raised_error = err raised_error._json_formatter = OWSException.json_formatter return_error = raised_error exc_info_err = False exc_log_lvl = logging.WARNING if err.status_code < 500 else logging.ERROR except OWSException as err: # could be 'WeaverException' with 'OWSException' base LOGGER.debug("direct ows exception response") raised_error = err return_error = err exc_info_err = False exc_log_lvl = logging.WARNING except NotImplementedError as err: LOGGER.debug("not implemented error -> ows exception response") raised_error = err return_error = OWSNotImplemented(str(err)) exc_info_err = sys.exc_info() exc_log_lvl = logging.ERROR except Exception as err: LOGGER.debug("unhandled %s exception -> ows exception response", type(err).__name__) raised_error = err return_error = OWSException(detail=str(err), status=HTTPInternalServerError) exc_info_err = sys.exc_info() exc_log_lvl = logging.ERROR # FIXME: # https://github.com/crim-ca/weaver/issues/215 # convivial generation of this repr format should be directly in common exception class raised_err_code = getattr(raised_error, "code", getattr(raised_error, "status_code", 500)) raised_err_repr = "({}) <{}> {!s}".format( type(raised_error).__name__, raised_err_code, raised_error) if raised_error != return_error: err_msg = "\n Raised: [{}]\n Return: [{!r}]".format( raised_err_repr, return_error) else: err_msg = " [{}]".format(raised_err_repr) LOGGER.log(exc_log_lvl, "Handled request exception:%s", err_msg, exc_info=exc_info_err) LOGGER.debug("Handled request details:\n%s\n%s", raised_err_repr, getattr(raised_error, "text", "")) return return_error
def add_provider(request): """ Add a provider. """ store = get_db(request).get_store(StoreServices) try: new_service = Service(url=request.json["url"], name=get_any_id(request.json)) except KeyError as exc: raise OWSMissingParameterValue( "Missing json parameter '{!s}'.".format(exc), value=exc) if "public" in request.json: new_service["public"] = request.json["public"] if "auth" in request.json: new_service["auth"] = request.json["auth"] try: store.save_service(new_service) except NotImplementedError: raise OWSNotImplemented( sd.NotImplementedPostProviderResponse.description, value=new_service) return HTTPCreated(json=get_capabilities(new_service, request))
def add_provider(request): # type: (PyramidRequest) -> AnyViewResponse """ Register a new service provider. """ schema = sd.CreateProviderRequestBody() schema_ref = get_schema_ref(schema, request) try: body = schema.deserialize(request.json) except colander.Invalid as invalid: data = { "description": f"Invalid schema: [{invalid!s}]", "value": invalid.value } data.update(schema_ref) raise HTTPBadRequest(json=data) store = get_db(request).get_store(StoreServices) prov_id = get_any_id(body) try: store.fetch_by_name(prov_id) except ServiceNotFound: pass else: raise HTTPConflict(f"Provider [{prov_id}] already exists.") try: new_service = Service(url=body["url"], name=prov_id) except KeyError as exc: raise OWSMissingParameterValue(f"Missing JSON parameter '{exc!s}'.", value=exc) if "public" in body: new_service["public"] = body["public"] if "auth" in body: new_service["auth"] = body["auth"] try: # validate that metadata or any pre-fetch operation can be resolved service = new_service.summary(request, fetch=True, ignore=False) if not service: raise colander.Invalid(None, value=body) store.save_service(new_service) except NotImplementedError: # raised when supported service types / conversion raise OWSNotImplemented( sd.NotImplementedPostProviderResponse.description, value=new_service) except ServiceParsingError: # derives from HTTPUnprocessableEntity with relevant error message raise except colander.Invalid as invalid: data = { "description": "Provider properties could not be parsed correctly.", "value": invalid.value } data.update(schema_ref) raise HTTPUnprocessableEntity(json=data) data = get_schema_ref(sd.ProviderSummarySchema, request) data.update(service) return HTTPCreated(json=data)
def remove_provider(request): """ Remove an existing service provider. """ service, store = get_service(request) try: store.delete_service(service.name) except NotImplementedError: raise OWSNotImplemented(sd.NotImplementedDeleteProviderResponse.description) return HTTPNoContent(json={})