Changeset 2447
- Timestamp:
- 09/01/2009 11:50:10 (3 years ago)
- Location:
- box/trunk
- Files:
-
- 2 added
- 1 edited
-
lib/httpserver/S3Client.cpp (added)
-
lib/httpserver/S3Client.h (added)
-
test/httpserver/testhttpserver.cpp (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
box/trunk/test/httpserver/testhttpserver.cpp
r2446 r2447 21 21 #include "HTTPServer.h" 22 22 #include "IOStreamGetLine.h" 23 #include "S3Client.h" 23 24 #include "ServerControl.h" 24 25 #include "Test.h" … … 326 327 rResponse.SetResponseCode(HTTPResponse::Code_OK); 327 328 } 328 329 class S3Client330 {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 else475 {476 try477 {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 once493 mapClientSocket->Open(Socket::TypeINET,494 mHostName, mPort);495 return SendRequest(request, pStreamToSend,496 pStreamContentType);497 }498 else499 {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 else518 {519 rRequest.Send(*mapClientSocket, 30000 /* milliseconds */);520 response.Receive(*mapClientSocket, 30000 /* milliseconds */);521 }522 523 return response;524 }525 329 526 330 int test(int argc, const char *argv[])
Note: See TracChangeset
for help on using the changeset viewer.
