Skip to content

Commit

Permalink
Add support for the DELETE method to the S3Simulator and S3Client
Browse files Browse the repository at this point in the history
Also adds a test for the PUT method.
  • Loading branch information
qris committed Dec 13, 2016
1 parent 9b324d3 commit fd36820
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 8 deletions.
3 changes: 2 additions & 1 deletion lib/httpserver/HTTPException.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ NoStreamConfigured 13
RequestFailedUnexpectedly 14 The request was expected to succeed, but it failed.
ContentLengthAlreadySet 15 Tried to send a request without content, but the Content-Length header is already set.
WrongContentLength 16 There was too much or not enough data in the request content stream.
AuthenticationFailed 17 The request could not be authenticated.
AuthenticationFailed 19 The request could not be authenticated.
S3SimulatorError 20 An unspecified error occurred in the S3Simulator.
16 changes: 16 additions & 0 deletions lib/httpserver/S3Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,22 @@ HTTPResponse S3Client::HeadObject(const std::string& rObjectURI)
}


// --------------------------------------------------------------------------
//
// Function
// Name: S3Client::DeleteObject(const std::string& rObjectURI)
// Purpose: Delete the object with the specified URI (key) from
// your S3 bucket.
// Created: 27/01/2016
//
// --------------------------------------------------------------------------

HTTPResponse S3Client::DeleteObject(const std::string& rObjectURI)
{
return FinishAndSendRequest(HTTPRequest::Method_DELETE, rObjectURI);
}


// --------------------------------------------------------------------------
//
// Function
Expand Down
1 change: 1 addition & 0 deletions lib/httpserver/S3Client.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class S3Client
HTTPResponse HeadObject(const std::string& rObjectURI);
HTTPResponse PutObject(const std::string& rObjectURI,
IOStream& rStreamToSend, const char* pContentType = NULL);
HTTPResponse DeleteObject(const std::string& rObjectURI);
void CheckResponse(const HTTPResponse& response, const std::string& message) const;
int GetNetworkTimeout() const { return mNetworkTimeout; }

Expand Down
38 changes: 38 additions & 0 deletions lib/httpserver/S3Simulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,10 @@ void S3Simulator::Handle(HTTPRequest &rRequest, HTTPResponse &rResponse)
{
HandlePut(rRequest, rResponse);
}
else if(rRequest.GetMethod() == HTTPRequest::Method_DELETE)
{
HandleDelete(rRequest, rResponse);
}
else
{
THROW_EXCEPTION_MESSAGE(HTTPException, BadRequest,
Expand Down Expand Up @@ -329,6 +333,40 @@ void S3Simulator::HandleGet(HTTPRequest &rRequest, HTTPResponse &rResponse)
rResponse.AddHeader("Server", "AmazonS3");
}

// --------------------------------------------------------------------------
//
// Function
// Name: S3Simulator::HandleDelete(HTTPRequest &rRequest,
// HTTPResponse &rResponse)
// Purpose: Handles an S3 DELETE request, i.e. deleting an
// existing object from the simulated store.
// Created: 27/01/2016
//
// --------------------------------------------------------------------------

void S3Simulator::HandleDelete(HTTPRequest &rRequest, HTTPResponse &rResponse)
{
std::string path = GetConfiguration().GetKeyValue("StoreDirectory");
path += rRequest.GetRequestURI();

// I think that DELETE is idempotent.
if(FileExists(path))
{
if(::unlink(path.c_str()) != 0)
{
THROW_SYS_FILE_ERROR("Failed to delete file", path,
HTTPException, S3SimulatorError);
}
}

// http://docs.amazonwebservices.com/AmazonS3/2006-03-01/UsingRESTOperations.html
rResponse.SetResponseCode(HTTPResponse::Code_NoContent);

rResponse.AddHeader("x-amz-id-2", "qBmKRcEWBBhH6XAqsKU/eg24V3jf/kWKN9dJip1L/FpbYr9FDy7wWFurfdQOEMcY");
rResponse.AddHeader("x-amz-request-id", "F2A8CCCA26B4B26D");
rResponse.AddHeader("Date", "Wed, 01 Mar 2006 12:00:00 GMT");
rResponse.AddHeader("Server", "AmazonS3");
}

// --------------------------------------------------------------------------
//
Expand Down
1 change: 1 addition & 0 deletions lib/httpserver/S3Simulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class S3Simulator : public HTTPServer
virtual void Handle(HTTPRequest &rRequest, HTTPResponse &rResponse);
virtual void HandleGet(HTTPRequest &rRequest, HTTPResponse &rResponse);
virtual void HandlePut(HTTPRequest &rRequest, HTTPResponse &rResponse);
virtual void HandleDelete(HTTPRequest &rRequest, HTTPResponse &rResponse);

virtual const char *DaemonName() const
{
Expand Down
23 changes: 16 additions & 7 deletions test/httpserver/testhttpserver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,15 +165,20 @@ bool exercise_s3client(S3Client& client)
TEST_EQUAL("dc3b8c5e57e71d31a0a9d7cbeee2e011", digest);
}

// TODO: upload this file using PUT instead:
{
FileStream newfile("testfiles/store/newfile", O_CREAT | O_WRONLY | O_BINARY);
fs.CopyStreamTo(newfile);
fs.Seek(0, IOStream::SeekType_Absolute);
}
std::string newfile_path = "testfiles/store/newfile";

TEST_THAT(!FileExists(newfile_path));
response = client.PutObject("/newfile", fs);
TEST_EQUAL(200, response.GetResponseCode());
TEST_THAT(!response.IsKeepAlive());
TEST_EQUAL("\"" + digest + "\"", response.GetHeaders().GetHeaderValue("etag"));

// This will fail if the file was created in the wrong place:
TEST_THAT(FileExists(newfile_path));

response = client.GetObject("/newfile");
TEST_EQUAL(200, response.GetResponseCode());
fs.Seek(0, IOStream::SeekType_Absolute);
TEST_THAT(fs.CompareWith(response));
TEST_EQUAL("\"" + digest + "\"", response.GetHeaders().GetHeaderValue("etag"));

Expand All @@ -191,7 +196,10 @@ bool exercise_s3client(S3Client& client)
TEST_EQUAL(false, response.GetHeaders().HasHeader("etag"));

// This will fail if the file was created in the wrong place:
TEST_EQUAL(0, ::unlink("testfiles/store/newfile"));
TEST_THAT(FileExists(newfile_path));
response = client.DeleteObject("/newfile");
TEST_EQUAL(HTTPResponse::Code_NoContent, response.GetResponseCode());
TEST_THAT(!FileExists(newfile_path));

// Test is successful if the number of failures has not increased.
return (num_failures == num_failures_initial);
Expand Down Expand Up @@ -729,6 +737,7 @@ bool test_httpserver()
FileStream f1("testfiles/dsfdsfs98.fd");
FileStream f2("testfiles/store/newfile");
TEST_THAT(f1.CompareWith(f2));
TEST_THAT(::unlink("testfiles/store/newfile") == 0);
}

// S3Client tests with S3Simulator daemon for realism
Expand Down

0 comments on commit fd36820

Please sign in to comment.