Changeset 2447


Ignore:
Timestamp:
09/01/2009 11:50:10 (3 years ago)
Author:
chris
Message:

Move S3Client class into its own files for public access.

Location:
box/trunk
Files:
2 added
1 edited

Legend:

Unmodified
Added
Removed
  • box/trunk/test/httpserver/testhttpserver.cpp

    r2446 r2447  
    2121#include "HTTPServer.h" 
    2222#include "IOStreamGetLine.h" 
     23#include "S3Client.h" 
    2324#include "ServerControl.h" 
    2425#include "Test.h" 
     
    326327        rResponse.SetResponseCode(HTTPResponse::Code_OK); 
    327328} 
    328  
    329 class S3Client 
    330 { 
    331         public: 
    332         S3Client(S3Simulator* pSimulator, const std::string& rHostName, 
    333                 const std::string& rAccessKey, const std::string& rSecretKey) 
    334         : mpSimulator(pSimulator), 
    335           mHostName(rHostName), 
    336           mAccessKey(rAccessKey), 
    337           mSecretKey(rSecretKey) 
    338         { } 
    339          
    340         S3Client(std::string HostName, int Port, const std::string& rAccessKey, 
    341                 const std::string& rSecretKey) 
    342         : mpSimulator(NULL), 
    343           mHostName(HostName), 
    344           mPort(Port), 
    345           mAccessKey(rAccessKey), 
    346           mSecretKey(rSecretKey) 
    347         { } 
    348                  
    349         HTTPResponse GetObject(const std::string& rObjectURI); 
    350         HTTPResponse PutObject(const std::string& rObjectURI, 
    351                 IOStream& rStreamToSend, const char* pContentType = NULL); 
    352  
    353         private: 
    354         S3Simulator* mpSimulator; 
    355         std::string mHostName; 
    356         int mPort; 
    357         std::auto_ptr<SocketStream> mapClientSocket; 
    358         std::string mAccessKey, mSecretKey; 
    359  
    360         HTTPResponse FinishAndSendRequest(HTTPRequest::Method Method, 
    361                 const std::string& rRequestURI, 
    362                 IOStream* pStreamToSend = NULL, 
    363                 const char* pStreamContentType = NULL); 
    364         HTTPResponse SendRequest(HTTPRequest& rRequest, 
    365                 IOStream* pStreamToSend = NULL, 
    366                 const char* pStreamContentType = NULL); 
    367 }; 
    368  
    369 HTTPResponse S3Client::GetObject(const std::string& rObjectURI) 
    370 { 
    371         return FinishAndSendRequest(HTTPRequest::Method_GET, rObjectURI); 
    372 } 
    373  
    374 HTTPResponse S3Client::PutObject(const std::string& rObjectURI, 
    375         IOStream& rStreamToSend, const char* pContentType) 
    376 { 
    377         return FinishAndSendRequest(HTTPRequest::Method_PUT, rObjectURI, 
    378                 &rStreamToSend, pContentType); 
    379 } 
    380  
    381 HTTPResponse S3Client::FinishAndSendRequest(HTTPRequest::Method Method, 
    382         const std::string& rRequestURI, IOStream* pStreamToSend, 
    383         const char* pStreamContentType) 
    384 { 
    385         HTTPRequest request(Method, rRequestURI); 
    386         request.SetHostName(mHostName); 
    387          
    388         std::ostringstream date; 
    389         time_t tt = time(NULL); 
    390         struct tm *tp = gmtime(&tt); 
    391         if (!tp) 
    392         { 
    393                 BOX_ERROR("Failed to get current time"); 
    394                 THROW_EXCEPTION(HTTPException, Internal); 
    395         } 
    396         const char *dow[] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; 
    397         date << dow[tp->tm_wday] << ", "; 
    398         const char *month[] = {"Jan","Feb","Mar","Apr","May","Jun", 
    399                 "Jul","Aug","Sep","Oct","Nov","Dec"}; 
    400         date << std::internal << std::setfill('0') << 
    401                 std::setw(2) << tp->tm_mday << " " << 
    402                 month[tp->tm_mon] << " " << 
    403                 (tp->tm_year + 1900) << " "; 
    404         date << std::setw(2) << tp->tm_hour << ":" << 
    405                 std::setw(2) << tp->tm_min  << ":" << 
    406                 std::setw(2) << tp->tm_sec  << " GMT"; 
    407         request.AddHeader("Date", date.str()); 
    408  
    409         if (pStreamContentType) 
    410         { 
    411                 request.AddHeader("Content-Type", pStreamContentType); 
    412         } 
    413          
    414         std::string s3suffix = ".s3.amazonaws.com"; 
    415         std::string bucket; 
    416         if (mHostName.size() > s3suffix.size()) 
    417         { 
    418                 std::string suffix = mHostName.substr(mHostName.size() - 
    419                         s3suffix.size(), s3suffix.size()); 
    420                 if (suffix == s3suffix) 
    421                 { 
    422                         bucket = mHostName.substr(0, mHostName.size() - 
    423                                 s3suffix.size()); 
    424                 } 
    425         } 
    426          
    427         std::ostringstream data; 
    428         data << request.GetVerb() << "\n"; 
    429         data << "\n"; /* Content-MD5 */ 
    430         data << request.GetContentType() << "\n"; 
    431         data << date.str() << "\n"; 
    432                  
    433         if (! bucket.empty()) 
    434         { 
    435                 data << "/" << bucket; 
    436         } 
    437          
    438         data << request.GetRequestURI(); 
    439         std::string data_string = data.str(); 
    440  
    441         unsigned char digest_buffer[EVP_MAX_MD_SIZE]; 
    442         unsigned int digest_size = sizeof(digest_buffer); 
    443         /* unsigned char* mac = */ HMAC(EVP_sha1(), 
    444                 mSecretKey.c_str(), mSecretKey.size(), 
    445                 (const unsigned char*)data_string.c_str(), 
    446                 data_string.size(), digest_buffer, &digest_size); 
    447         std::string digest((const char *)digest_buffer, digest_size); 
    448          
    449         base64::encoder encoder; 
    450         std::string auth_code = "AWS " + mAccessKey + ":" + 
    451                 encoder.encode(digest); 
    452  
    453         if (auth_code[auth_code.size() - 1] == '\n') 
    454         { 
    455                 auth_code = auth_code.substr(0, auth_code.size() - 1); 
    456         } 
    457  
    458         request.AddHeader("Authorization", auth_code); 
    459          
    460         if (mpSimulator) 
    461         { 
    462                 if (pStreamToSend) 
    463                 { 
    464                         pStreamToSend->CopyStreamTo(request); 
    465                 } 
    466  
    467                 request.SetForReading(); 
    468                 CollectInBufferStream response_buffer; 
    469                 HTTPResponse response(&response_buffer); 
    470          
    471                 mpSimulator->Handle(request, response); 
    472                 return response; 
    473         } 
    474         else 
    475         { 
    476                 try 
    477                 { 
    478                         if (!mapClientSocket.get()) 
    479                         { 
    480                                 mapClientSocket.reset(new SocketStream()); 
    481                                 mapClientSocket->Open(Socket::TypeINET, 
    482                                         mHostName, mPort); 
    483                         } 
    484                         return SendRequest(request, pStreamToSend, 
    485                                 pStreamContentType); 
    486                 } 
    487                 catch (ConnectionException &ce) 
    488                 { 
    489                         if (ce.GetType() == ConnectionException::SocketWriteError) 
    490                         { 
    491                                 // server may have disconnected us, 
    492                                 // try to reconnect, just once 
    493                                 mapClientSocket->Open(Socket::TypeINET, 
    494                                         mHostName, mPort); 
    495                                 return SendRequest(request, pStreamToSend, 
    496                                         pStreamContentType); 
    497                         } 
    498                         else 
    499                         { 
    500                                 throw; 
    501                         } 
    502                 } 
    503         } 
    504 } 
    505  
    506 HTTPResponse S3Client::SendRequest(HTTPRequest& rRequest, 
    507         IOStream* pStreamToSend, const char* pStreamContentType) 
    508 {                
    509         HTTPResponse response; 
    510          
    511         if (pStreamToSend) 
    512         { 
    513                 rRequest.SendWithStream(*mapClientSocket, 
    514                         30000 /* milliseconds */, 
    515                         pStreamToSend, response); 
    516         } 
    517         else 
    518         { 
    519                 rRequest.Send(*mapClientSocket, 30000 /* milliseconds */); 
    520                 response.Receive(*mapClientSocket, 30000 /* milliseconds */); 
    521         } 
    522                  
    523         return response; 
    524 }        
    525329 
    526330int test(int argc, const char *argv[]) 
Note: See TracChangeset for help on using the changeset viewer.