Skip to content

Commit

Permalink
Improve exception handling in S3Simulator
Browse files Browse the repository at this point in the history
Centralise error response generationImprove exception handling in S3Simulator,
driven by throwing and catching exceptions.

Add a method to BoxException to quickly check what type of exception it is, and
a macro to make this even shorter.
  • Loading branch information
qris committed Nov 14, 2016
1 parent 39fc054 commit b81caf3
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 23 deletions.
6 changes: 6 additions & 0 deletions lib/common/BoxException.h
Expand Up @@ -29,11 +29,17 @@ class BoxException : public std::exception

virtual unsigned int GetType() const throw() = 0;
virtual unsigned int GetSubType() const throw() = 0;
bool IsType(unsigned int Type, unsigned int SubType)
{
return GetType() == Type && GetSubType() == SubType;
}
virtual const std::string& GetMessage() const = 0;

private:
};

#define EXCEPTION_IS_TYPE(exception_obj, type, subtype) \
exception_obj.IsType(type::ExceptionType, type::subtype)

#endif // BOXEXCEPTION__H

43 changes: 20 additions & 23 deletions lib/httpserver/S3Simulator.cpp
Expand Up @@ -167,9 +167,8 @@ void S3Simulator::Handle(HTTPRequest &rRequest, HTTPResponse &rResponse)
if (!rRequest.GetHeader("authorization", &actualAuth) ||
actualAuth != expectedAuth)
{
rResponse.SetResponseCode(HTTPResponse::Code_Unauthorized);
SendInternalErrorResponse("Authentication Failed",
rResponse);
THROW_EXCEPTION_MESSAGE(HTTPException, AuthenticationFailed,
"Authentication code mismatch");
}
else if (rRequest.GetMethod() == HTTPRequest::Method_GET)
{
Expand All @@ -181,14 +180,27 @@ void S3Simulator::Handle(HTTPRequest &rRequest, HTTPResponse &rResponse)
}
else
{
rResponse.SetResponseCode(HTTPResponse::Code_BadRequest);
SendInternalErrorResponse("Unsupported Method",
rResponse);
THROW_EXCEPTION_MESSAGE(HTTPException, BadRequest,
"Unsupported Amazon S3 Method");
}
}
catch (CommonException &ce)
catch (BoxException &ce)
{
SendInternalErrorResponse(ce.what(), rResponse);

// Override the default status code 500 for a few specific exceptions.
if(EXCEPTION_IS_TYPE(ce, CommonException, OSFileOpenError))
{
rResponse.SetResponseCode(HTTPResponse::Code_NotFound);
}
else if(EXCEPTION_IS_TYPE(ce, CommonException, AccessDenied))
{
rResponse.SetResponseCode(HTTPResponse::Code_Forbidden);
}
else if(EXCEPTION_IS_TYPE(ce, HTTPException, AuthenticationFailed))
{
rResponse.SetResponseCode(HTTPResponse::Code_Unauthorized);
}
}
catch (std::exception &e)
{
Expand Down Expand Up @@ -231,22 +243,7 @@ void S3Simulator::HandleGet(HTTPRequest &rRequest, HTTPResponse &rResponse)
path += rRequest.GetRequestURI();
std::auto_ptr<FileStream> apFile;

try
{
apFile.reset(new FileStream(path));
}
catch (CommonException &ce)
{
if (ce.GetSubType() == CommonException::OSFileOpenError)
{
rResponse.SetResponseCode(HTTPResponse::Code_NotFound);
}
else if (ce.GetSubType() == CommonException::AccessDenied)
{
rResponse.SetResponseCode(HTTPResponse::Code_Forbidden);
}
throw;
}
apFile.reset(new FileStream(path));

// http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingRESTOperations.html
apFile->CopyStreamTo(rResponse);
Expand Down

0 comments on commit b81caf3

Please sign in to comment.