Skip to content

Commit

Permalink
Raise more accurate ATHR::RequestBody deserialization errors (#490)
Browse files Browse the repository at this point in the history
  • Loading branch information
Blacksmoke16 authored Dec 15, 2024
1 parent ee5fc7a commit 13a0c6f
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,30 @@ struct RequestBodyResolverTest < ASPEC::TestCase

def test_raises_on_invalid_json : Nil
expect_raises ATH::Exception::BadRequest, "Malformed JSON payload." do
@target.resolve new_request(body: "<abc123>"), self.get_config(MockJSONSerializableEntity)
@target.resolve new_request(body: %(<blah>)), self.get_config(MockJSONSerializableEntity)
end
end

def test_raises_on_invalid_nested_json : Nil
expect_raises ATH::Exception::BadRequest, "Malformed JSON payload." do
@target.resolve new_request(body: %({"id": "foo"})), self.get_config(MockJSONSerializableEntity)
end
end

def test_raises_on_missing_json_data : Nil
expect_raises ATH::Exception::UnprocessableEntity, "Missing JSON attribute: name" do
@target.resolve new_request(body: %({"id":10})), self.get_config(MockJSONSerializableEntity)
end
end

def test_raises_on_missing_www_form_data : Nil
expect_raises ATH::Exception::BadRequest, "Malformed www form data payload." do
expect_raises ATH::Exception::UnprocessableEntity, "Missing required property: 'name'." do
@target.resolve new_request(body: "id=10", format: "form"), self.get_config(MockURISerializableEntity)
end
end

def test_raises_on_missing_query_string_data : Nil
expect_raises ATH::Exception::BadRequest, "Malformed query string." do
expect_raises ATH::Exception::UnprocessableEntity, "Missing required property: 'name'." do
@target.resolve new_request(query: "id=10"), self.get_config(MockURISerializableEntity, ATHA::MapQueryString, ATHA::MapQueryStringConfiguration.new)
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,12 @@ struct Athena::Framework::Controller::ValueResolvers::RequestBody

self.deserialize_form query, parameter.type
rescue ex : URI::SerializableError
raise ATH::Exception::BadRequest.new "Malformed query string.", cause: ex
raise ATH::Exception::UnprocessableEntity.new ex.message.not_nil!, cause: ex
rescue ex : URI::Error
raise ATH::Exception::BadRequest.new "Malformed www form data payload.", cause: ex
end

# ameba:disable Metrics/CyclomaticComplexity:
private def map_request_body(request : ATH::Request, parameter : ATH::Controller::ParameterMetadata, configuration : ATHA::MapRequestBodyConfiguration)
if !(body = request.body) || body.peek.try &.empty?
raise ATH::Exception::BadRequest.new "Request does not have a body."
Expand All @@ -215,9 +218,21 @@ struct Athena::Framework::Controller::ValueResolvers::RequestBody
else
raise ATH::Exception::UnsupportedMediaType.new "Unsupported format."
end
rescue ex : JSON::SerializableError
# JSON::Serializable seems to sometimes re-raise parse exceptions as `JSON::SerializableError`,
# so we handle those first based on the cause.
case cause = ex.cause
when JSON::ParseException
raise ATH::Exception::BadRequest.new "Malformed JSON payload.", cause: cause
else
raise ATH::Exception::UnprocessableEntity.new ex.message.not_nil!
end
rescue ex : JSON::ParseException | ASR::Exception::DeserializationException
# Otherwise if it really is a `ParseException` we can be assured it's just malformed
raise ATH::Exception::BadRequest.new "Malformed JSON payload.", cause: ex
rescue ex : URI::SerializableError
raise ATH::Exception::UnprocessableEntity.new ex.message.not_nil!, cause: ex
rescue ex : URI::Error
raise ATH::Exception::BadRequest.new "Malformed www form data payload.", cause: ex
end

Expand Down

0 comments on commit 13a0c6f

Please sign in to comment.