diff --git a/packages/pytest-simcore/src/pytest_simcore/helpers/assert_checks.py b/packages/pytest-simcore/src/pytest_simcore/helpers/assert_checks.py index e4df1c1bf80..2f71de33e25 100644 --- a/packages/pytest-simcore/src/pytest_simcore/helpers/assert_checks.py +++ b/packages/pytest-simcore/src/pytest_simcore/helpers/assert_checks.py @@ -7,7 +7,7 @@ from aiohttp import ClientResponse from servicelib.aiohttp import status from servicelib.aiohttp.rest_responses import unwrap_envelope -from servicelib.status_utils import get_code_display_name, is_error +from servicelib.status_codes_utils import get_code_display_name, is_error async def assert_status( @@ -15,6 +15,7 @@ async def assert_status( expected_status_code: int, expected_msg: str | None = None, expected_error_code: str | None = None, + *, include_meta: bool | None = False, include_links: bool | None = False, ) -> tuple[dict, ...]: diff --git a/packages/pytest-simcore/src/pytest_simcore/helpers/webserver_parametrizations.py b/packages/pytest-simcore/src/pytest_simcore/helpers/webserver_parametrizations.py index 747d1a1193f..6422122f4f4 100644 --- a/packages/pytest-simcore/src/pytest_simcore/helpers/webserver_parametrizations.py +++ b/packages/pytest-simcore/src/pytest_simcore/helpers/webserver_parametrizations.py @@ -2,7 +2,7 @@ from unittest import mock from servicelib.aiohttp import status -from servicelib.status_utils import get_code_display_name +from servicelib.status_codes_utils import get_code_display_name from simcore_postgres_database.models.users import UserRole diff --git a/packages/service-library/src/servicelib/aiohttp/long_running_tasks/_routes.py b/packages/service-library/src/servicelib/aiohttp/long_running_tasks/_routes.py index 8aad57ba6ce..d2e2dda98bf 100644 --- a/packages/service-library/src/servicelib/aiohttp/long_running_tasks/_routes.py +++ b/packages/service-library/src/servicelib/aiohttp/long_running_tasks/_routes.py @@ -4,11 +4,11 @@ from aiohttp import web from models_library.utils.json_serialization import json_dumps from pydantic import BaseModel +from servicelib.aiohttp import status from ...long_running_tasks._errors import TaskNotCompletedError, TaskNotFoundError from ...long_running_tasks._models import TaskGet, TaskId, TaskStatus from ...long_running_tasks._task import TrackedTask -from ...mimetype_constants import MIMETYPE_APPLICATION_JSON from ..requests_validation import parse_request_path_parameters_as from ._dependencies import get_task_context, get_tasks_manager @@ -89,7 +89,7 @@ async def cancel_and_delete_task(request: web.Request) -> web.Response: tasks_manager = get_tasks_manager(request.app) task_context = get_task_context(request) await tasks_manager.remove_task(path_params.task_id, with_task_context=task_context) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) __all__: tuple[str, ...] = ( diff --git a/packages/service-library/src/servicelib/aiohttp/rest_responses.py b/packages/service-library/src/servicelib/aiohttp/rest_responses.py index dda73210865..52aa87497d8 100644 --- a/packages/service-library/src/servicelib/aiohttp/rest_responses.py +++ b/packages/service-library/src/servicelib/aiohttp/rest_responses.py @@ -13,7 +13,7 @@ from servicelib.aiohttp.status import HTTP_200_OK from ..mimetype_constants import MIMETYPE_APPLICATION_JSON -from ..status_utils import get_code_description +from ..status_codes_utils import get_code_description from .rest_models import ErrorItemType, ErrorType _ENVELOPE_KEYS = ("data", "error") @@ -151,16 +151,3 @@ def _pred(obj) -> bool: assert len(http_statuses) == len(found), "No duplicates" # nosec return http_statuses - - -_STATUS_CODE_TO_HTTP_ERRORS: dict[int, type[HTTPError]] = _collect_http_exceptions( - HTTPError -) - - -def get_http_error(status_code: int) -> type[HTTPError] | None: - """Returns aiohttp error class corresponding to a 4XX or 5XX status code - - NOTICE that any non-error code (i.e. 2XX, 3XX and 4XX) will return None - """ - return _STATUS_CODE_TO_HTTP_ERRORS.get(status_code) diff --git a/packages/service-library/src/servicelib/aiohttp/web_exceptions_extension.py b/packages/service-library/src/servicelib/aiohttp/web_exceptions_extension.py index 47bfa594171..eaf0cfc42a3 100644 --- a/packages/service-library/src/servicelib/aiohttp/web_exceptions_extension.py +++ b/packages/service-library/src/servicelib/aiohttp/web_exceptions_extension.py @@ -1,8 +1,85 @@ -from aiohttp.web_exceptions import HTTPClientError +""" Extends `aiohttp.web_exceptions` classes to match `status` codes + and adds helper functions. +""" + +import inspect +from typing import Any, TypeVar + +from aiohttp import web_exceptions +from aiohttp.web_exceptions import ( + HTTPClientError, + HTTPError, + HTTPException, + HTTPServerError, +) from . import status +assert issubclass(HTTPError, HTTPException) # nsoec + +# NOTE: these are the status codes that DO NOT have an aiohttp.HTTPException associated +STATUS_CODES_WITHOUT_AIOHTTP_EXCEPTION_CLASS = ( + status.HTTP_100_CONTINUE, + status.HTTP_101_SWITCHING_PROTOCOLS, + status.HTTP_102_PROCESSING, + status.HTTP_103_EARLY_HINTS, + status.HTTP_207_MULTI_STATUS, + status.HTTP_208_ALREADY_REPORTED, + status.HTTP_226_IM_USED, + status.HTTP_306_RESERVED, + status.HTTP_418_IM_A_TEAPOT, + status.HTTP_425_TOO_EARLY, +) + class HTTPLockedError(HTTPClientError): # pylint: disable=too-many-ancestors status_code = status.HTTP_423_LOCKED + + +class HTTPLoopDetectedError(HTTPServerError): + # pylint: disable=too-many-ancestors + status_code = status.HTTP_508_LOOP_DETECTED + + +E = TypeVar("E", bound="HTTPException") + + +def get_all_aiohttp_http_exceptions( + base_http_exception_cls: type[E], +) -> dict[int, type[E]]: + # Inverse map from code to HTTPException classes + + def _pred(obj) -> bool: + return ( + inspect.isclass(obj) + and issubclass(obj, base_http_exception_cls) + and getattr(obj, "status_code", 0) > 0 + ) + + found: list[tuple[str, Any]] = inspect.getmembers(web_exceptions, _pred) + assert found # nosec + + status_to_http_exception_map = {cls.status_code: cls for _, cls in found} + assert len(status_to_http_exception_map) == len(found), "No duplicates" # nosec + + for cls in ( + HTTPLockedError, + HTTPLoopDetectedError, + ): + status_to_http_exception_map[cls.status_code] = cls + + return status_to_http_exception_map + + +_STATUS_CODE_TO_HTTP_ERRORS: dict[ + int, type[HTTPError] +] = get_all_aiohttp_http_exceptions(HTTPError) + + +def get_http_error_class_or_none(status_code: int) -> type[HTTPError] | None: + """Returns aiohttp error class corresponding to a 4XX or 5XX status code + + NOTE: any non-error code (i.e. 2XX, 3XX and 4XX) will return None + """ + return _STATUS_CODE_TO_HTTP_ERRORS.get(status_code) diff --git a/packages/service-library/src/servicelib/status_utils.py b/packages/service-library/src/servicelib/status_codes_utils.py similarity index 87% rename from packages/service-library/src/servicelib/status_utils.py rename to packages/service-library/src/servicelib/status_codes_utils.py index 2ebbf61d19b..d50ae7ec681 100644 --- a/packages/service-library/src/servicelib/status_utils.py +++ b/packages/service-library/src/servicelib/status_codes_utils.py @@ -2,7 +2,7 @@ - on aiohttp services from servicelib.aiohttp import status - from servicelib.status_utils import is_success + from servicelib.status_codes_utils import is_success assert is_success(status.HTTP_200_OK) @@ -10,7 +10,7 @@ - on fastapi services from fastapi import status - from servicelib.status_utils import is_success + from servicelib.status_codes_utils import is_success assert is_success(status.HTTP_200_OK) @@ -37,6 +37,7 @@ def get_code_display_name(status_code: int) -> str: return f"HTTP_{status_code}_{code.name}" except ValueError: if status_code == 306: # noqa: PLR2004 + # NOTE: HttpStatus does not include 306 return "HTTP_306_RESERVED" return _INVALID_STATUS_CODE_MSG @@ -65,35 +66,35 @@ def get_code_description(status_code: int) -> str: ) -def is_informational(status_code: int) -> bool: +def is_1xx_informational(status_code: int) -> bool: """ Returns `True` for 1xx status codes, `False` otherwise. """ return 100 <= status_code <= 199 # noqa: PLR2004 -def is_success(status_code: int) -> bool: +def is_2xx_success(status_code: int) -> bool: """ Returns `True` for 2xx status codes, `False` otherwise. """ return 200 <= status_code <= 299 # noqa: PLR2004 -def is_redirect(status_code: int) -> bool: +def is_3xx_redirect(status_code: int) -> bool: """ Returns `True` for 3xx status codes, `False` otherwise. """ return 300 <= status_code <= 399 # noqa: PLR2004 -def is_client_error(status_code: int) -> bool: +def is_4xx_client_error(status_code: int) -> bool: """ Returns `True` for 4xx status codes, `False` otherwise. """ return 400 <= status_code <= 499 # noqa: PLR2004 -def is_server_error(status_code: int) -> bool: +def is_5xx_server_error(status_code: int) -> bool: """ Returns `True` for 5xx status codes, `False` otherwise. """ diff --git a/packages/service-library/tests/aiohttp/test_rest_responses.py b/packages/service-library/tests/aiohttp/test_rest_responses.py index 7077a93cb0f..d1b28d1e9fe 100644 --- a/packages/service-library/tests/aiohttp/test_rest_responses.py +++ b/packages/service-library/tests/aiohttp/test_rest_responses.py @@ -16,16 +16,13 @@ HTTPOk, ) from servicelib.aiohttp import status -from servicelib.aiohttp.rest_responses import ( +from servicelib.aiohttp.rest_responses import create_http_error, exception_to_response +from servicelib.aiohttp.web_exceptions_extension import ( _STATUS_CODE_TO_HTTP_ERRORS, - create_http_error, - exception_to_response, - get_http_error, + get_http_error_class_or_none, ) from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON -# - # SEE https://httpstatuses.com/ # - below 1xx -> invalid BELOW_1XX = (-5, 0, 5, 99) @@ -36,17 +33,17 @@ @pytest.mark.parametrize( - "http_exc", (HTTPBadRequest, HTTPGone, HTTPInternalServerError) + "http_exc", [HTTPBadRequest, HTTPGone, HTTPInternalServerError] ) def test_get_http_exception_class_from_code(http_exc: HTTPException): - assert get_http_error(http_exc.status_code) == http_exc + assert get_http_error_class_or_none(http_exc.status_code) == http_exc @pytest.mark.parametrize( "status_code", itertools.chain(BELOW_1XX, NONE_ERRORS, ABOVE_599) ) def test_get_none_for_invalid_or_not_errors_code(status_code): - assert get_http_error(status_code) is None + assert get_http_error_class_or_none(status_code) is None @pytest.mark.parametrize( diff --git a/packages/service-library/tests/aiohttp/test_status_utils.py b/packages/service-library/tests/aiohttp/test_status_utils.py index cfddc0294f9..c5a8785a3b1 100644 --- a/packages/service-library/tests/aiohttp/test_status_utils.py +++ b/packages/service-library/tests/aiohttp/test_status_utils.py @@ -1,17 +1,23 @@ from http import HTTPStatus +import pytest from servicelib.aiohttp import status -from servicelib.status_utils import ( +from servicelib.aiohttp.web_exceptions_extension import ( + STATUS_CODES_WITHOUT_AIOHTTP_EXCEPTION_CLASS, + HTTPException, + get_all_aiohttp_http_exceptions, +) +from servicelib.status_codes_utils import ( _INVALID_STATUS_CODE_MSG, get_code_description, get_code_display_name, get_http_status_codes, - is_client_error, + is_1xx_informational, + is_2xx_success, + is_3xx_redirect, + is_4xx_client_error, + is_5xx_server_error, is_error, - is_informational, - is_redirect, - is_server_error, - is_success, ) @@ -31,12 +37,12 @@ def test_description(): def test_status_codes_checks(): - assert is_informational(status.HTTP_102_PROCESSING) - assert is_success(status.HTTP_202_ACCEPTED) - assert is_redirect(status.HTTP_301_MOVED_PERMANENTLY) + assert is_1xx_informational(status.HTTP_102_PROCESSING) + assert is_2xx_success(status.HTTP_202_ACCEPTED) + assert is_3xx_redirect(status.HTTP_301_MOVED_PERMANENTLY) - assert is_client_error(status.HTTP_401_UNAUTHORIZED) - assert is_server_error(status.HTTP_503_SERVICE_UNAVAILABLE) + assert is_4xx_client_error(status.HTTP_401_UNAUTHORIZED) + assert is_5xx_server_error(status.HTTP_503_SERVICE_UNAVAILABLE) assert is_error(status.HTTP_401_UNAUTHORIZED) assert is_error(status.HTTP_503_SERVICE_UNAVAILABLE) @@ -45,7 +51,7 @@ def test_status_codes_checks(): def test_predicates_with_status(): # in formational - assert get_http_status_codes(status, is_informational) == [ + assert get_http_status_codes(status, is_1xx_informational) == [ status.HTTP_100_CONTINUE, status.HTTP_101_SWITCHING_PROTOCOLS, status.HTTP_102_PROCESSING, @@ -61,3 +67,17 @@ def test_predicates_with_status(): for c in get_http_status_codes(status) if c != status.HTTP_306_RESERVED ] + + +AIOHTTP_EXCEPTION_CLASSES_MAP: dict[ + int, type[HTTPException] +] = get_all_aiohttp_http_exceptions(HTTPException) + + +@pytest.mark.parametrize("status_code", get_http_status_codes(status)) +def test_how_status_codes_map_to_aiohttp_exception_class(status_code): + aiohttp_exception_cls = AIOHTTP_EXCEPTION_CLASSES_MAP.get(status_code) + if status_code in STATUS_CODES_WITHOUT_AIOHTTP_EXCEPTION_CLASS: + assert aiohttp_exception_cls is None + else: + assert aiohttp_exception_cls is not None diff --git a/services/storage/src/simcore_service_storage/handlers_files.py b/services/storage/src/simcore_service_storage/handlers_files.py index 8cb96d267a2..87cb60d5829 100644 --- a/services/storage/src/simcore_service_storage/handlers_files.py +++ b/services/storage/src/simcore_service_storage/handlers_files.py @@ -1,7 +1,7 @@ import asyncio import logging import urllib.parse -from typing import NoReturn, cast +from typing import cast from aiohttp import web from aiohttp.web import RouteTableDef @@ -25,7 +25,6 @@ parse_request_path_parameters_as, parse_request_query_parameters_as, ) -from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON from ._meta import API_VTAG from .dsm import get_dsm_provider @@ -249,7 +248,7 @@ async def upload_file(request: web.Request) -> web.Response: f"/{API_VTAG}/locations/{{location_id}}/files/{{file_id}}:abort", name="abort_upload_file", ) -async def abort_upload_file(request: web.Request) -> NoReturn: +async def abort_upload_file(request: web.Request) -> web.Response: query_params: StorageQueryParamsBase = parse_request_query_parameters_as( StorageQueryParamsBase, request ) @@ -261,7 +260,7 @@ async def abort_upload_file(request: web.Request) -> NoReturn: dsm = get_dsm_provider(request.app).get(path_params.location_id) await dsm.abort_file_upload(query_params.user_id, path_params.file_id) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) @routes.post( @@ -374,7 +373,7 @@ async def is_completed_upload_file(request: web.Request) -> web.Response: @routes.delete( f"/{API_VTAG}/locations/{{location_id}}/files/{{file_id}}", name="delete_file" ) -async def delete_file(request: web.Request) -> NoReturn: +async def delete_file(request: web.Request) -> web.Response: query_params: StorageQueryParamsBase = parse_request_query_parameters_as( StorageQueryParamsBase, request ) @@ -386,7 +385,7 @@ async def delete_file(request: web.Request) -> NoReturn: dsm = get_dsm_provider(request.app).get(path_params.location_id) await dsm.delete_file(query_params.user_id, path_params.file_id) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) @routes.post(f"/{API_VTAG}/files/{{file_id}}:soft-copy", name="copy_as_soft_link") diff --git a/services/storage/src/simcore_service_storage/handlers_simcore_s3.py b/services/storage/src/simcore_service_storage/handlers_simcore_s3.py index a4fff084329..0f8e52fa7fc 100644 --- a/services/storage/src/simcore_service_storage/handlers_simcore_s3.py +++ b/services/storage/src/simcore_service_storage/handlers_simcore_s3.py @@ -1,5 +1,5 @@ import logging -from typing import NoReturn, cast +from typing import cast from aiohttp import web from aiohttp.web import RouteTableDef @@ -7,6 +7,7 @@ from models_library.projects import ProjectID from models_library.utils.fastapi_encoders import jsonable_encoder from models_library.utils.json_serialization import json_dumps +from servicelib.aiohttp import status from servicelib.aiohttp.long_running_tasks.server import ( TaskProgress, start_long_running_task, @@ -106,7 +107,7 @@ async def copy_folders_from_project(request: web.Request) -> web.Response: @routes.delete( f"/{API_VTAG}/simcore-s3/folders/{{folder_id}}", name="delete_folders_of_project" ) -async def delete_folders_of_project(request: web.Request) -> NoReturn: +async def delete_folders_of_project(request: web.Request) -> web.Response: query_params: DeleteFolderQueryParams = parse_request_query_parameters_as( DeleteFolderQueryParams, request ) @@ -126,7 +127,7 @@ async def delete_folders_of_project(request: web.Request) -> NoReturn: query_params.node_id, ) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) @routes.post(f"/{API_VTAG}/simcore-s3/files/metadata:search", name="search_files") diff --git a/services/web/server/src/simcore_service_webserver/api_keys/_handlers.py b/services/web/server/src/simcore_service_webserver/api_keys/_handlers.py index ce7a7be0943..627d733d9c7 100644 --- a/services/web/server/src/simcore_service_webserver/api_keys/_handlers.py +++ b/services/web/server/src/simcore_service_webserver/api_keys/_handlers.py @@ -5,6 +5,7 @@ from models_library.api_schemas_webserver.auth import ApiKeyCreate from models_library.users import UserID from pydantic import Field +from servicelib.aiohttp import status from servicelib.aiohttp.requests_validation import RequestParams, parse_request_body_as from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON from simcore_postgres_database.errors import DatabaseError @@ -84,4 +85,4 @@ async def delete_api_key(request: web.Request): "Failed to delete API key %s. Ignoring error", name, exc_info=err ) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) diff --git a/services/web/server/src/simcore_service_webserver/director_v2/_handlers.py b/services/web/server/src/simcore_service_webserver/director_v2/_handlers.py index fb80f3aa3fa..f794fa6f148 100644 --- a/services/web/server/src/simcore_service_webserver/director_v2/_handlers.py +++ b/services/web/server/src/simcore_service_webserver/director_v2/_handlers.py @@ -10,16 +10,13 @@ from models_library.utils.json_serialization import json_dumps from pydantic import BaseModel, Field, ValidationError, parse_obj_as from pydantic.types import NonNegativeInt -from servicelib.aiohttp.rest_responses import ( - create_http_error, - exception_to_response, - get_http_error, -) +from servicelib.aiohttp import status +from servicelib.aiohttp.rest_responses import create_http_error, exception_to_response +from servicelib.aiohttp.web_exceptions_extension import get_http_error_class_or_none from servicelib.common_headers import ( UNDEFINED_DEFAULT_SIMCORE_USER_AGENT_VALUE, X_SIMCORE_USER_AGENT, ) -from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON from servicelib.request_keys import RQT_USERID_KEY from simcore_postgres_database.utils_groups_extra_properties import ( GroupExtraPropertiesRepo, @@ -170,7 +167,8 @@ async def start_computation(request: web.Request) -> web.Response: create_http_error( exc, reason=exc.reason, - http_error_cls=get_http_error(exc.status) or web.HTTPServiceUnavailable, + http_error_cls=get_http_error_class_or_none(exc.status) + or web.HTTPServiceUnavailable, ) ) except UserDefaultWalletNotFoundError as exc: @@ -204,19 +202,14 @@ async def stop_computation(request: web.Request) -> web.Response: await asyncio.gather( *[computations.stop(pid, req_ctx.user_id) for pid in project_ids] ) - - # NOTE: our middleware has this issue - # - # if 'return web.HTTPNoContent()' then 'await response.json()' raises ContentTypeError - # if 'raise web.HTTPNoContent()' then 'await response.json() == None' - # - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) except DirectorServiceError as exc: return create_http_error( exc, reason=exc.reason, - http_error_cls=get_http_error(exc.status) or web.HTTPServiceUnavailable, + http_error_cls=get_http_error_class_or_none(exc.status) + or web.HTTPServiceUnavailable, ) @@ -265,7 +258,8 @@ async def get_computation(request: web.Request) -> web.Response: return create_http_error( exc, reason=exc.reason, - http_error_cls=get_http_error(exc.status) or web.HTTPServiceUnavailable, + http_error_cls=get_http_error_class_or_none(exc.status) + or web.HTTPServiceUnavailable, ) except ValidationError as exc: return create_http_error(exc, http_error_cls=web.HTTPInternalServerError) diff --git a/services/web/server/src/simcore_service_webserver/folders/_folders_handlers.py b/services/web/server/src/simcore_service_webserver/folders/_folders_handlers.py index 4b212524079..f331c98da4a 100644 --- a/services/web/server/src/simcore_service_webserver/folders/_folders_handlers.py +++ b/services/web/server/src/simcore_service_webserver/folders/_folders_handlers.py @@ -17,6 +17,7 @@ from models_library.utils.common_validators import null_or_none_str_to_none_validator from models_library.workspaces import WorkspaceID from pydantic import Extra, Field, Json, parse_obj_as, validator +from servicelib.aiohttp import status from servicelib.aiohttp.requests_validation import ( RequestParams, StrictRequestParams, @@ -246,4 +247,4 @@ async def delete_folder_group(request: web.Request): folder_id=path_params.folder_id, product_name=req_ctx.product_name, ) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) diff --git a/services/web/server/src/simcore_service_webserver/groups/_handlers.py b/services/web/server/src/simcore_service_webserver/groups/_handlers.py index 2f0b0411601..b6284bed8bf 100644 --- a/services/web/server/src/simcore_service_webserver/groups/_handlers.py +++ b/services/web/server/src/simcore_service_webserver/groups/_handlers.py @@ -13,6 +13,7 @@ from models_library.users import GroupID, UserID from models_library.utils.json_serialization import json_dumps from pydantic import BaseModel, Extra, Field, parse_obj_as +from servicelib.aiohttp import status from servicelib.aiohttp.requests_validation import ( parse_request_path_parameters_as, parse_request_query_parameters_as, @@ -169,7 +170,7 @@ async def delete_group(request: web.Request): path_params = parse_request_path_parameters_as(_GroupPathParams, request) await api.delete_user_group(request.app, req_ctx.user_id, path_params.gid) - raise web.HTTPNoContent + return web.json_response(status=status.HTTP_204_NO_CONTENT) @routes.get(f"/{API_VTAG}/groups/{{gid}}/users", name="get_group_users") @@ -215,7 +216,7 @@ async def add_group_user(request: web.Request): new_user_id=new_user_id, new_user_email=new_user_email, ) - raise web.HTTPNoContent + return web.json_response(status=status.HTTP_204_NO_CONTENT) class _GroupUserPathParams(BaseModel): @@ -275,7 +276,7 @@ async def delete_group_user(request: web.Request): await api.delete_user_in_group( request.app, req_ctx.user_id, path_params.gid, path_params.uid ) - raise web.HTTPNoContent + return web.json_response(status=status.HTTP_204_NO_CONTENT) # diff --git a/services/web/server/src/simcore_service_webserver/login/_registration_handlers.py b/services/web/server/src/simcore_service_webserver/login/_registration_handlers.py index 2ad608e3c12..869fa7a2973 100644 --- a/services/web/server/src/simcore_service_webserver/login/_registration_handlers.py +++ b/services/web/server/src/simcore_service_webserver/login/_registration_handlers.py @@ -8,6 +8,7 @@ ) from models_library.users import UserID from pydantic import BaseModel, Field +from servicelib.aiohttp import status from servicelib.aiohttp.application_keys import APP_FIRE_AND_FORGET_TASKS_KEY from servicelib.aiohttp.requests_validation import parse_request_body_as from servicelib.logging_utils import get_log_record_extra, log_context @@ -85,7 +86,7 @@ async def request_product_account(request: web.Request): task_suffix_name=f"{__name__}.request_product_account.send_account_request_email_to_support", fire_and_forget_tasks_collection=request.app[APP_FIRE_AND_FORGET_TASKS_KEY], ) - raise web.HTTPNoContent + return web.json_response(status=status.HTTP_204_NO_CONTENT) class _AuthenticatedContext(BaseModel): diff --git a/services/web/server/src/simcore_service_webserver/projects/_comments_handlers.py b/services/web/server/src/simcore_service_webserver/projects/_comments_handlers.py index fff41cd016c..5325f389e9a 100644 --- a/services/web/server/src/simcore_service_webserver/projects/_comments_handlers.py +++ b/services/web/server/src/simcore_service_webserver/projects/_comments_handlers.py @@ -16,6 +16,7 @@ ) from models_library.rest_pagination_utils import paginate_data from pydantic import BaseModel, Extra, Field, NonNegativeInt +from servicelib.aiohttp import status from servicelib.aiohttp.requests_validation import ( parse_request_body_as, parse_request_path_parameters_as, @@ -223,7 +224,7 @@ async def delete_project_comment(request: web.Request): request=request, comment_id=path_params.comment_id, ) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) @routes.get( diff --git a/services/web/server/src/simcore_service_webserver/projects/_crud_handlers.py b/services/web/server/src/simcore_service_webserver/projects/_crud_handlers.py index d2cce731d21..11d1f701b32 100644 --- a/services/web/server/src/simcore_service_webserver/projects/_crud_handlers.py +++ b/services/web/server/src/simcore_service_webserver/projects/_crud_handlers.py @@ -26,6 +26,7 @@ from models_library.utils.fastapi_encoders import jsonable_encoder from models_library.utils.json_serialization import json_dumps from pydantic import parse_obj_as +from servicelib.aiohttp import status from servicelib.aiohttp.long_running_tasks.server import start_long_running_task from servicelib.aiohttp.requests_validation import ( parse_request_body_as, @@ -576,7 +577,7 @@ async def patch_project(request: web.Request): product_name=req_ctx.product_name, ) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) # @@ -661,7 +662,7 @@ async def delete_project(request: web.Request): except ProjectDeleteError as err: raise web.HTTPConflict(reason=f"{err}") from err - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) # diff --git a/services/web/server/src/simcore_service_webserver/projects/_folders_handlers.py b/services/web/server/src/simcore_service_webserver/projects/_folders_handlers.py index 591fecf8a94..0e22c5970b9 100644 --- a/services/web/server/src/simcore_service_webserver/projects/_folders_handlers.py +++ b/services/web/server/src/simcore_service_webserver/projects/_folders_handlers.py @@ -6,9 +6,9 @@ from models_library.projects import ProjectID from models_library.utils.common_validators import null_or_none_str_to_none_validator from pydantic import BaseModel, Extra, validator +from servicelib.aiohttp import status from servicelib.aiohttp.requests_validation import parse_request_path_parameters_as from servicelib.aiohttp.typing_extension import Handler -from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON from .._meta import api_version_prefix as VTAG from ..login.decorators import login_required @@ -69,4 +69,4 @@ async def replace_project_folder(request: web.Request): folder_id=path_params.folder_id, product_name=req_ctx.product_name, ) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) diff --git a/services/web/server/src/simcore_service_webserver/projects/_groups_handlers.py b/services/web/server/src/simcore_service_webserver/projects/_groups_handlers.py index 607dd499df2..85c71d0d62d 100644 --- a/services/web/server/src/simcore_service_webserver/projects/_groups_handlers.py +++ b/services/web/server/src/simcore_service_webserver/projects/_groups_handlers.py @@ -9,12 +9,12 @@ from models_library.projects import ProjectID from models_library.users import GroupID from pydantic import BaseModel, Extra +from servicelib.aiohttp import status from servicelib.aiohttp.requests_validation import ( parse_request_body_as, parse_request_path_parameters_as, ) from servicelib.aiohttp.typing_extension import Handler -from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON from .._meta import api_version_prefix as VTAG from ..login.decorators import login_required @@ -154,4 +154,4 @@ async def delete_project_group(request: web.Request): group_id=path_params.group_id, product_name=req_ctx.product_name, ) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) diff --git a/services/web/server/src/simcore_service_webserver/projects/_nodes_handlers.py b/services/web/server/src/simcore_service_webserver/projects/_nodes_handlers.py index 255260c60ad..fd7a21eaad6 100644 --- a/services/web/server/src/simcore_service_webserver/projects/_nodes_handlers.py +++ b/services/web/server/src/simcore_service_webserver/projects/_nodes_handlers.py @@ -33,6 +33,7 @@ from models_library.utils.fastapi_encoders import jsonable_encoder from models_library.utils.json_serialization import json_dumps from pydantic import BaseModel, Field, parse_obj_as +from servicelib.aiohttp import status from servicelib.aiohttp.long_running_tasks.server import ( TaskProgress, start_long_running_task, @@ -238,7 +239,7 @@ async def patch_project_node(request: web.Request) -> web.Response: node_patch=node_patch, ) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) @routes.delete(f"/{VTAG}/projects/{{project_id}}/nodes/{{node_id}}", name="delete_node") @@ -263,7 +264,7 @@ async def delete_node(request: web.Request) -> web.Response: req_ctx.product_name, ) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) @routes.post( @@ -310,7 +311,7 @@ async def update_node_outputs(request: web.Request) -> web.Response: node_errors=None, ui_changed_keys=ui_changed_keys, ) - return web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) @routes.post( @@ -333,7 +334,7 @@ async def start_node(request: web.Request) -> web.Response: node_id=path_params.node_id, ) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) async def _stop_dynamic_service_task( @@ -347,15 +348,15 @@ async def _stop_dynamic_service_task( await dynamic_scheduler_api.stop_dynamic_service( app, dynamic_service_stop=dynamic_service_stop ) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) - # in case there is an error reply as not found except (RPCServerError, ServiceWaitingForManualInterventionError) as exc: + # in case there is an error reply as not found raise web.HTTPNotFound(reason=f"{exc}") from exc - # in case the service is not found reply as all OK - except ServiceWasNotFoundError as exc: - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) from exc + except ServiceWasNotFoundError: + # in case the service is not found reply as all OK + return web.json_response(status=status.HTTP_204_NO_CONTENT) @routes.post( @@ -413,7 +414,7 @@ async def restart_node(request: web.Request) -> web.Response: await director_v2_api.restart_dynamic_service(request.app, f"{path_params.node_id}") - raise web.HTTPNoContent + return web.json_response(status=status.HTTP_204_NO_CONTENT) # diff --git a/services/web/server/src/simcore_service_webserver/projects/_states_handlers.py b/services/web/server/src/simcore_service_webserver/projects/_states_handlers.py index fe7c62960f0..ca0725b37b9 100644 --- a/services/web/server/src/simcore_service_webserver/projects/_states_handlers.py +++ b/services/web/server/src/simcore_service_webserver/projects/_states_handlers.py @@ -10,6 +10,7 @@ from aiohttp import web from models_library.projects_state import ProjectState from pydantic import BaseModel +from servicelib.aiohttp import status from servicelib.aiohttp.requests_validation import ( parse_request_path_parameters_as, parse_request_query_parameters_as, @@ -20,7 +21,6 @@ UNDEFINED_DEFAULT_SIMCORE_USER_AGENT_VALUE, X_SIMCORE_USER_AGENT, ) -from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON from simcore_postgres_database.models.users import UserRole from simcore_postgres_database.webserver_models import ProjectType @@ -222,7 +222,7 @@ async def close_project(request: web.Request) -> web.Response: ), ) await project_logs.unsubscribe(request.app, path_params.project_id) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) # diff --git a/services/web/server/src/simcore_service_webserver/projects/_workspaces_handlers.py b/services/web/server/src/simcore_service_webserver/projects/_workspaces_handlers.py index e262ce8dc29..6b553a6d3ba 100644 --- a/services/web/server/src/simcore_service_webserver/projects/_workspaces_handlers.py +++ b/services/web/server/src/simcore_service_webserver/projects/_workspaces_handlers.py @@ -6,9 +6,9 @@ from models_library.utils.common_validators import null_or_none_str_to_none_validator from models_library.workspaces import WorkspaceID from pydantic import BaseModel, Extra, validator +from servicelib.aiohttp import status from servicelib.aiohttp.requests_validation import parse_request_path_parameters_as from servicelib.aiohttp.typing_extension import Handler -from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON from .._meta import api_version_prefix as VTAG from ..folders.errors import FolderAccessForbiddenError, FolderNotFoundError @@ -81,4 +81,4 @@ async def replace_project_workspace(request: web.Request): workspace_id=path_params.workspace_id, product_name=req_ctx.product_name, ) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) diff --git a/services/web/server/src/simcore_service_webserver/publications/_handlers.py b/services/web/server/src/simcore_service_webserver/publications/_handlers.py index 3a88ca641c5..2d7feef016f 100644 --- a/services/web/server/src/simcore_service_webserver/publications/_handlers.py +++ b/services/web/server/src/simcore_service_webserver/publications/_handlers.py @@ -3,6 +3,7 @@ from aiohttp import MultipartReader, hdrs, web from json2html import json2html # type: ignore[import-untyped] from models_library.utils.json_serialization import json_dumps +from servicelib.aiohttp import status from servicelib.mimetype_constants import ( MIMETYPE_APPLICATION_JSON, MIMETYPE_APPLICATION_ZIP, @@ -93,4 +94,4 @@ async def service_submission(request: web.Request): _logger.exception("Error while sending the 'new service submission' mail.") raise web.HTTPServiceUnavailable from exc - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) diff --git a/services/web/server/src/simcore_service_webserver/tags/_handlers.py b/services/web/server/src/simcore_service_webserver/tags/_handlers.py index 5492d5e468e..8862f0320c1 100644 --- a/services/web/server/src/simcore_service_webserver/tags/_handlers.py +++ b/services/web/server/src/simcore_service_webserver/tags/_handlers.py @@ -2,6 +2,7 @@ from aiohttp import web from pydantic import parse_obj_as +from servicelib.aiohttp import status from servicelib.aiohttp.requests_validation import ( parse_request_body_as, parse_request_path_parameters_as, @@ -107,7 +108,7 @@ async def delete_tag(request: web.Request): request.app, user_id=req_ctx.user_id, tag_id=path_params.tag_id ) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) # diff --git a/services/web/server/src/simcore_service_webserver/users/_handlers.py b/services/web/server/src/simcore_service_webserver/users/_handlers.py index 3e2018c7d9b..3462602f74b 100644 --- a/services/web/server/src/simcore_service_webserver/users/_handlers.py +++ b/services/web/server/src/simcore_service_webserver/users/_handlers.py @@ -4,13 +4,13 @@ from aiohttp import web from models_library.users import UserID from pydantic import BaseModel, Field +from servicelib.aiohttp import status from servicelib.aiohttp.requests_validation import ( parse_request_body_as, parse_request_query_parameters_as, ) from servicelib.aiohttp.typing_extension import Handler from servicelib.logging_errors import create_troubleshotting_log_kwargs -from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON from servicelib.request_keys import RQT_USERID_KEY from servicelib.rest_constants import RESPONSE_MODEL_POLICY @@ -85,7 +85,7 @@ async def update_my_profile(request: web.Request) -> web.Response: await api.update_user_profile( request.app, req_ctx.user_id, profile_update, as_patch=False ) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) class _SearchQueryParams(BaseModel): diff --git a/services/web/server/src/simcore_service_webserver/users/_notifications_handlers.py b/services/web/server/src/simcore_service_webserver/users/_notifications_handlers.py index b30a435210b..3a9588d39a5 100644 --- a/services/web/server/src/simcore_service_webserver/users/_notifications_handlers.py +++ b/services/web/server/src/simcore_service_webserver/users/_notifications_handlers.py @@ -4,11 +4,11 @@ import redis.asyncio as aioredis from aiohttp import web from pydantic import BaseModel +from servicelib.aiohttp import status from servicelib.aiohttp.requests_validation import ( parse_request_body_as, parse_request_path_parameters_as, ) -from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON from servicelib.redis_utils import handle_redis_returns_union_types from .._meta import API_VTAG @@ -84,7 +84,7 @@ async def create_user_notification(request: web.Request) -> web.Response: pipe.ltrim(key, 0, MAX_NOTIFICATIONS_FOR_USER_TO_KEEP - 1) await pipe.execute() - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) class _NotificationPathParams(BaseModel): @@ -115,9 +115,9 @@ async def mark_notification_as_read(request: web.Request) -> web.Response: await handle_redis_returns_union_types( redis_client.lset(key, k, user_notification.json()) ) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) @routes.get(f"/{API_VTAG}/me/permissions", name="list_user_permissions") diff --git a/services/web/server/src/simcore_service_webserver/users/_preferences_handlers.py b/services/web/server/src/simcore_service_webserver/users/_preferences_handlers.py index 9f5513b904f..0c537278f9c 100644 --- a/services/web/server/src/simcore_service_webserver/users/_preferences_handlers.py +++ b/services/web/server/src/simcore_service_webserver/users/_preferences_handlers.py @@ -8,12 +8,12 @@ from models_library.products import ProductName from models_library.users import UserID from pydantic import BaseModel, Field +from servicelib.aiohttp import status from servicelib.aiohttp.requests_validation import ( parse_request_body_as, parse_request_path_parameters_as, ) from servicelib.aiohttp.typing_extension import Handler -from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON from servicelib.request_keys import RQT_USERID_KEY from simcore_postgres_database.utils_user_preferences import ( CouldNotCreateOrUpdateUserPreferenceError, @@ -66,4 +66,4 @@ async def set_frontend_preference(request: web.Request) -> web.Response: frontend_preference_identifier=req_path_params.preference_id, value=req_body.value, ) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) diff --git a/services/web/server/src/simcore_service_webserver/users/_tokens_handlers.py b/services/web/server/src/simcore_service_webserver/users/_tokens_handlers.py index ddca5a94b2f..40b884c4eb9 100644 --- a/services/web/server/src/simcore_service_webserver/users/_tokens_handlers.py +++ b/services/web/server/src/simcore_service_webserver/users/_tokens_handlers.py @@ -3,12 +3,12 @@ from aiohttp import web from pydantic import BaseModel +from servicelib.aiohttp import status from servicelib.aiohttp.requests_validation import ( parse_request_body_as, parse_request_path_parameters_as, ) from servicelib.aiohttp.typing_extension import Handler -from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON from .._meta import API_VTAG from ..login.decorators import login_required @@ -85,4 +85,4 @@ async def delete_token(request: web.Request) -> web.Response: req_ctx = UsersRequestContext.parse_obj(request) req_path_params = parse_request_path_parameters_as(_TokenPathParams, request) await _tokens.delete_token(request.app, req_ctx.user_id, req_path_params.service) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) diff --git a/services/web/server/src/simcore_service_webserver/wallets/_groups_handlers.py b/services/web/server/src/simcore_service_webserver/wallets/_groups_handlers.py index 6690d6d41e4..1115a239d62 100644 --- a/services/web/server/src/simcore_service_webserver/wallets/_groups_handlers.py +++ b/services/web/server/src/simcore_service_webserver/wallets/_groups_handlers.py @@ -9,12 +9,12 @@ from models_library.users import GroupID, UserID from models_library.wallets import WalletID from pydantic import BaseModel, Extra, Field +from servicelib.aiohttp import status from servicelib.aiohttp.requests_validation import ( parse_request_body_as, parse_request_path_parameters_as, ) from servicelib.aiohttp.typing_extension import Handler -from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON from servicelib.request_keys import RQT_USERID_KEY from .._constants import RQ_PRODUCT_KEY @@ -161,4 +161,4 @@ async def delete_wallet_group(request: web.Request): group_id=path_params.group_id, product_name=req_ctx.product_name, ) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) diff --git a/services/web/server/src/simcore_service_webserver/wallets/_payments_handlers.py b/services/web/server/src/simcore_service_webserver/wallets/_payments_handlers.py index 27060372abd..9a03bc2d2a5 100644 --- a/services/web/server/src/simcore_service_webserver/wallets/_payments_handlers.py +++ b/services/web/server/src/simcore_service_webserver/wallets/_payments_handlers.py @@ -15,6 +15,7 @@ from models_library.products import CreditResultGet from models_library.rest_pagination import Page, PageQueryParameters from models_library.rest_pagination_utils import paginate_data +from servicelib.aiohttp import status from servicelib.aiohttp.application_keys import APP_FIRE_AND_FORGET_TASKS_KEY from servicelib.aiohttp.requests_validation import ( parse_request_body_as, @@ -22,7 +23,6 @@ parse_request_query_parameters_as, ) from servicelib.logging_utils import get_log_record_extra, log_context -from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON from servicelib.utils import fire_and_forget_task from .._meta import API_VTAG as VTAG @@ -185,7 +185,7 @@ async def _cancel_payment(request: web.Request): product_name=req_ctx.product_name, ) - return web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) # @@ -261,7 +261,7 @@ async def _cancel_creation_of_payment_method(request: web.Request): product_name=req_ctx.product_name, ) - return web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) @routes.get( @@ -323,7 +323,7 @@ async def _delete_payment_method(request: web.Request): payment_method_id=path_params.payment_method_id, product_name=req_ctx.product_name, ) - return web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) _TINY_WAIT_TO_TRIGGER_CONTEXT_SWITCH = 0.1 diff --git a/services/web/server/src/simcore_service_webserver/workspaces/_groups_handlers.py b/services/web/server/src/simcore_service_webserver/workspaces/_groups_handlers.py index 0bf7d09eb68..d4ae7c4b74f 100644 --- a/services/web/server/src/simcore_service_webserver/workspaces/_groups_handlers.py +++ b/services/web/server/src/simcore_service_webserver/workspaces/_groups_handlers.py @@ -9,12 +9,12 @@ from models_library.users import GroupID, UserID from models_library.workspaces import WorkspaceID from pydantic import BaseModel, Extra, Field +from servicelib.aiohttp import status from servicelib.aiohttp.requests_validation import ( parse_request_body_as, parse_request_path_parameters_as, ) from servicelib.aiohttp.typing_extension import Handler -from servicelib.mimetype_constants import MIMETYPE_APPLICATION_JSON from servicelib.request_keys import RQT_USERID_KEY from .._constants import RQ_PRODUCT_KEY @@ -162,4 +162,4 @@ async def delete_workspace_group(request: web.Request): group_id=path_params.group_id, product_name=req_ctx.product_name, ) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) diff --git a/services/web/server/src/simcore_service_webserver/workspaces/_workspaces_handlers.py b/services/web/server/src/simcore_service_webserver/workspaces/_workspaces_handlers.py index 5cc49639334..fa9a2e4aa67 100644 --- a/services/web/server/src/simcore_service_webserver/workspaces/_workspaces_handlers.py +++ b/services/web/server/src/simcore_service_webserver/workspaces/_workspaces_handlers.py @@ -15,6 +15,7 @@ from models_library.users import UserID from models_library.workspaces import WorkspaceID from pydantic import Extra, Field, Json, parse_obj_as, validator +from servicelib.aiohttp import status from servicelib.aiohttp.requests_validation import ( RequestParams, StrictRequestParams, @@ -209,4 +210,4 @@ async def delete_workspace(request: web.Request): workspace_id=path_params.workspace_id, product_name=req_ctx.product_name, ) - raise web.HTTPNoContent(content_type=MIMETYPE_APPLICATION_JSON) + return web.json_response(status=status.HTTP_204_NO_CONTENT) diff --git a/services/web/server/tests/integration/02/test_computation.py b/services/web/server/tests/integration/02/test_computation.py index 2aa2da0f3dd..0a73402e68d 100644 --- a/services/web/server/tests/integration/02/test_computation.py +++ b/services/web/server/tests/integration/02/test_computation.py @@ -20,7 +20,7 @@ from pytest_simcore.helpers.assert_checks import assert_status from servicelib.aiohttp import status from servicelib.aiohttp.application import create_safe_application -from servicelib.status_utils import get_code_display_name +from servicelib.status_codes_utils import get_code_display_name from settings_library.rabbit import RabbitSettings from settings_library.redis import RedisSettings from simcore_postgres_database.models.projects import projects diff --git a/services/web/server/tests/unit/isolated/test_security_api.py b/services/web/server/tests/unit/isolated/test_security_api.py index f7e73620435..e60cab4985b 100644 --- a/services/web/server/tests/unit/isolated/test_security_api.py +++ b/services/web/server/tests/unit/isolated/test_security_api.py @@ -156,12 +156,12 @@ async def _init(request: web.Request): # get url and deliver product product_name = expected_product_name await _remember_product_name(request, product_name) - return web.HTTPOk() + return web.json_response(status=status.HTTP_200_OK) @routes.post("/v0/hack/{product_name}") async def _set_other_product(request: web.Request): await _remember_product_name(request, request.match_info["product_name"]) - return web.HTTPOk() + return web.json_response(status=status.HTTP_200_OK) @routes.post("/v0/login") async def _login(request: web.Request): @@ -183,7 +183,7 @@ async def _login(request: web.Request): @routes.post("/v0/public") async def _public(request: web.Request): assert await _get_product_name(request) == expected_product_name - return web.HTTPOk() + return web.json_response(status=status.HTTP_200_OK) @routes.post("/v0/admin") @login_required # NOTE: same as `await check_user_authorized(request)`` @@ -192,7 +192,7 @@ async def _public(request: web.Request): ) async def _admin_only(request: web.Request): assert await _get_product_name(request) == expected_product_name - return web.HTTPOk() + return web.json_response(status=status.HTTP_200_OK) @routes.post("/v0/logout") async def _logout(request: web.Request):