Skip to content

Commit

Permalink
added OAI errors, handler
Browse files Browse the repository at this point in the history
  • Loading branch information
kyokukou committed Nov 6, 2024
1 parent a66d6ad commit abd284a
Show file tree
Hide file tree
Showing 9 changed files with 108 additions and 9 deletions.
46 changes: 46 additions & 0 deletions oaipmh/data/oai_errors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@

class OAIException(Exception):
"""General class for all OAI defined errors"""
code: str
description: str
pass

class OAIBadArgument(OAIException):
#dont include attributes
code="badArgument"
description="The request includes illegal arguments, is missing required arguments, includes a repeated argument, or values for arguments have an illegal syntax."

class OAIBadResumptionToken(OAIException):
#TODO consider including params
code="badResumptionToken"
description="The value of the resumptionToken argument is invalid or expired."

class OAIBadVerb(OAIException):
#dont include attributes
code="badVerb"
description="Value of the verb argument is not a legal OAI-PMH verb, the verb argument is missing, or the verb argument is repeated."

class OAIBadFormat(OAIException):
#TODO consider including params
code="cannotDisseminateFormat"
description="The metadata format identified by the value given for the metadataPrefix argument is not supported by the item or by the repository."

class OAINonexistentID(OAIException):
#TODO consider including params
code="idDoesNotExist"
description="The value of the identifier argument is unknown or illegal in this repository."

class OAINoRecordsMatch(OAIException):
#TODO params
code="noRecordsMatch"
description="The combination of the values of the from, until, set and metadataPrefix arguments results in an empty list."

class OAINoMetadataFormats(OAIException):
#TODO consider including params
code="noMetadataFormats"
description="There are no metadata formats available for the specified item."

class OAINoSetHierarchy(OAIException):
#should not be triggered for arXiv implementation
code="noSetHierarchy"
description="The repository does not support sets. This exception should not be true for the arXiv implementation."
19 changes: 18 additions & 1 deletion oaipmh/factory.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import logging
from datetime import datetime, timezone

from flask import Flask
from flask import Flask, render_template
from flask_s3 import FlaskS3
from flask.logging import default_handler
from werkzeug.exceptions import HTTPException

from arxiv.base import Base
from arxiv.db import config_query_timing, configure_db

from oaipmh.data.oai_errors import OAIException
from oaipmh.config import Settings
from oaipmh.requests import routes

Expand All @@ -33,6 +36,20 @@ def create_web_app(**kwargs) -> Flask: # type: ignore
app.register_blueprint(routes.blueprint)
s3.init_app(app)

@app.errorhandler(OAIException)
def handle_oai_error(e):
response=render_template("errors.xml",
response_date=datetime.now(timezone.utc),
error=e)
headers={"Content-Type":"application/xml"}
return response, 200, headers

#TODO make this actually trigger
@app.errorhandler(HTTPException)
def handle_http_error(e):
print("main error handler ran!")
return e.description, e.code, {}

app.jinja_env.trim_blocks = True
app.jinja_env.lstrip_blocks = True
if not app.jinja_env.globals:
Expand Down
4 changes: 2 additions & 2 deletions oaipmh/requests/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
@blueprint.route("/oai", methods=['GET', 'POST'])
def oai() -> Response:

#TODO what happens if duplicate params
params: Dict[str, str] = request.args.to_dict() if request.method == 'GET' else request.form.to_dict()
result=verb_sorter(params)


response_xml=render_template("base.xml",
response_date=datetime.now(timezone.utc),
request_info="request info", #TODO
Expand All @@ -26,4 +26,4 @@ def oai() -> Response:
@blueprint.route('/favicon.ico')
def favicon():
#TODO
return '', 204
return '', 204
4 changes: 2 additions & 2 deletions oaipmh/requests/verb_sorter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from oaipmh.requests.info_queries import identify, list_metadata_formats, list_sets
from oaipmh.requests.data_queries import get_record, list_identifiers, list_records
from oaipmh.serializers.output_formats import InteriorData
from oaipmh.data.oai_errors import OAIBadVerb

def verb_sorter(params: Dict[str, str]) -> InteriorData:
"""
Expand All @@ -26,5 +27,4 @@ def verb_sorter(params: Dict[str, str]) -> InteriorData:
case "ListSets":
return list_sets(params)
case _:
#TODO bad/no verb case error
return InteriorData()
raise OAIBadVerb #dont keep invalid verb
7 changes: 5 additions & 2 deletions oaipmh/templates/base.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
<responseDate>{{ response_date.strftime("%Y-%m-%dT%H:%M:%SZ") }}</responseDate>
{{macros.request_element()}}
{{interior_xml}}
{% block request_element %}
{% endblock %}

{% block interior_xml %}
{% endblock %}
</OAI-PMH>
Empty file removed oaipmh/templates/error.html
Empty file.
9 changes: 9 additions & 0 deletions oaipmh/templates/errors.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% extends "base.xml" %}

{% block request_element %}
{{ macros.request_element() }}
{% endblock %}

{% block interior_xml %}
<error code='{{error.code}}'>{{error.description}}</error>
{% endblock %}
6 changes: 5 additions & 1 deletion tests/test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,8 @@

def test_basic(test_client):
response = test_client.get("/oai")
assert response.status_code == 200
text=response.text
assert response.status_code == 200
assert 'xmlns="http://www.openarchives.org/OAI/2.0/"' in text
assert '<responseDate>' in text
assert '/oai</request>' in text
22 changes: 21 additions & 1 deletion tests/test_verb_sorting.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,24 @@ def test_list_sets(test_client):
assert response.status_code == 200
mock_list_sets.assert_called_once_with(params)

#TODO test no/bad verb
def test_no_verb(test_client):
params = {"not_verb": "ListSets"}

response = test_client.get("/oai", query_string=params)
assert response.status_code == 200
assert "<error code='badVerb'>" in response.text

response = test_client.post("/oai", data=params)
assert response.status_code == 200
assert "<error code='badVerb'>" in response.text

def test_bad_verb(test_client):
params = {"verb": "chaos!"}

response = test_client.get("/oai", query_string=params)
assert response.status_code == 200
assert "<error code='badVerb'>" in response.text

response = test_client.post("/oai", data=params)
assert response.status_code == 200
assert "<error code='badVerb'>" in response.text

0 comments on commit abd284a

Please sign in to comment.