Skip to content

Commit

Permalink
Have disabled endpoint in read-only mode respond 405
Browse files Browse the repository at this point in the history
Instead of 418
  • Loading branch information
candleindark committed Dec 16, 2023
1 parent 6f46720 commit db724cf
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 9 deletions.
8 changes: 3 additions & 5 deletions datalad_registry/blueprints/api/dataset_urls/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@
mark_for_chk,
process_dataset_url,
)
from datalad_registry.utils.flask_tools import (
disable_in_read_only_mode,
json_resp_from_str,
)
from datalad_registry.utils.flask_tools import json_resp_from_str

from .models import (
DatasetURLPage,
Expand All @@ -36,6 +33,7 @@
)
from .. import API_URL_PREFIX, COMMON_API_RESPONSES, HTTPExceptionResp
from ..url_metadata.models import URLMetadataRef
from ..utils import disable_in_read_only_mode

_ORDER_KEY_TO_SQLA_ATTR = {
OrderKey.url: RepoUrl.url,
Expand All @@ -60,7 +58,7 @@
responses={
"201": DatasetURLRespModel,
"202": DatasetURLRespModel,
"418": HTTPExceptionResp, # Occurs only when the server is in read-only mode
"405": HTTPExceptionResp, # Occurs only when the server is in read-only mode
},
)
@disable_in_read_only_mode
Expand Down
37 changes: 33 additions & 4 deletions datalad_registry/blueprints/api/utils.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
from functools import wraps
from http import HTTPStatus

from flask import abort, current_app
from flask import current_app, request

from datalad_registry import OperationMode
from datalad_registry.utils.flask_tools import json_resp_from_str

from . import HTTPExceptionResp


def disable_in_read_only_mode(view_func):
Expand All @@ -20,10 +23,36 @@ def wrapper(*args, **kwargs):
current_app.config["DATALAD_REGISTRY_OPERATION_MODE"]
is OperationMode.READ_ONLY
):
abort(
HTTPStatus.IM_A_TEAPOT,
description="This operation is not available from a read-only server.",

resp_status = HTTPStatus.METHOD_NOT_ALLOWED

# Construct the response body
resp_body = HTTPExceptionResp(
code=resp_status,
name=resp_status.phrase,
description="This method on the requested resource is not available "
"through a read-only server.",
)

# Get remaining supported methods on the endpoint, representing a resource,
# to construct the required `Allow` header for a 405, Method Not Allowed,
# response
remaining_supported_methods: set[str] = set()
for rule in current_app.url_map.iter_rules():
if (
str(rule) == str(request.url_rule)
and rule.endpoint != request.endpoint
):
# `rule` is of the current requested path
# but not of the current endpoint
remaining_supported_methods.update(rule.methods)

return json_resp_from_str(
resp_body.json(exclude_none=True),
status=resp_status,
headers={"Allow": ", ".join(remaining_supported_methods)},
)

else:
return view_func(*args, **kwargs)

Expand Down

0 comments on commit db724cf

Please sign in to comment.