Introduction
CHttpClientis a helper class using WinInet API. The purpose of this class is to help you interact with a HTTP web server. The class design goal is as follows:
- Easy to use.
- As many flexibilities as possible.
- Strict error handling.
I will briefly show you how to use this class. All detailed description has been documented in the attached help file.
How to use CHttpClient
In your project, include the following files:
- RyeolException.h
- RyeolException.cpp
- RyeolHttpClient.h
- RyeolHttpClient.cpp
- SafeInt.hpp
In yourstdafx.hfile, add the following line:
Collapse#include "RyeolHttpClient.h"
Note: The namespace and file names have been changed. If you use the previous version of theCHttpClient, you need to update as follows:
- LyoulException.h --> RyeolException.h
- LyoulException.cpp --> RyeolException.cpp
- LyoulHttpClient.h --> RyeolHttpClient.h
- LyoulHttpClient.cpp --> RyeolHttpClient.cpp
- #include "LyoulHttpClient.h" --> #include "RyeolHttpClient.h"
- using namespace Lyoul --> using namespace Ryeol
How to Send a Request Using HTTP GET
CHttpClientsupportsRequestGetmethod which sends a request using HTTP GET:
Collapse
CHttpResponse * CHttpClient::RequestGet (PCSZ szUrl,
BOOL bUseCache = FALSE) throw (Exception &) ;
The following code demonstrates the basic usage of theRequestGetmethod:
Collapseusing namespace Ryeol ;
CHttpClient objHttpReq ;
CHttpResponse * pobjHttpRes = NULL ;
try {
objHttpReq.SetInternet (_T ("My User Agent v1.0")) ;
objHttpReq.SetUseUtf8 (FALSE) ;
objHttpReq.SetAnsiCodePage (949) ;
objHttpReq.AddHeader (_T ("Ryeol-Magic"), _T ("My Magic Header")) ;
objHttpReq.AddHeader (_T ("User-Magic"), _T ("User's Magic Header")) ;
objHttpReq.AddParam (_T ("where"), _T ("nexearch")) ;
objHttpReq.AddParam (_T ("frm"), _T ("t1")) ;
objHttpReq.AddParam (_T ("query"),
_T ("%C3%D6%C1%F6%BF%EC"), CHttpClient::ParamEncodedValue) ;
pobjHttpRes =
objHttpReq.RequestGet (_T ("http://search.naver.com/search.naver")) ;
...
} catch (httpclientexception & e) {
...
}How to Send a Request Using HTTP POST
The HTTP POST method is used in two ways. One is to post simple text, the other is to upload files. To post simple text,CHttpClientprovidesBeginPostmethod.
Collapse
void CHttpClient::BeginPost (PCSZ szUrl,
BOOL bUseCache = FALSE) throw (Exception &) ;
The following code demonstrates the basic usage of theBeginPostmethod:
Collapseusing namespace Ryeol ;
CHttpClient objHttpReq ;
CHttpResponse * pobjHttpRes = NULL ;
try {
objHttpReq.SetInternet (_T ("My User Agent v1.0")) ;
objHttpReq.AddHeader (_T ("Ryeol-Magic"), _T ("My Magic Header")) ;
objHttpReq.AddHeader (_T ("User-Magic"), _T ("User's Magic Header")) ;
objHttpReq.AddParam (_T ("st"), _T ("kw")) ;
objHttpReq.AddParam (_T ("target"), _T ("WinInet")) ;
objHttpReq.BeginPost (_T ("http://www.codeproject.com/info/search.asp")) ;
const DWORD cbProceed = 1024 ;
do {
...
} while ( !(pobjHttpRes = objHttpReq.Proceed (cbProceed)) ) ;
...
} catch (httpclientexception & e) {
...
}To upload file,CHttpClientprovidesBeginUploadmethod.
Collapse
void CHttpClient::BeginUpload (PCSZ szUrl,
BOOL bUseCache = FALSE) throw (Exception &) ;
The following code demonstrates the basic usage of theBeginUploadmethod:
Collapseusing namespace Ryeol ;
CHttpClient objHttpReq ;
CHttpResponse * pobjHttpRes = NULL ;
try {
objHttpReq.SetInternet (_T ("My User Agent v1.0")) ;
objHttpReq.AddHeader (_T ("Ryeol-Magic"), _T ("My Magic Header")) ;
objHttpReq.AddHeader (_T ("User-Magic"), _T ("User's Magic Header")) ;
objHttpReq.AddParam (_T ("nohtml"), _T ("1")) ;
objHttpReq.AddParam (_T ("title"), _T ("The K-NET photo")) ;
objHttpReq.AddParam (_T ("content"), _T ("A photo of the K-NET")) ;
objHttpReq.AddParam (_T ("ufile01"),
_T ("D://My Photo//K-NET//photo1.jpg"),
CHttpClient::ParamFile) ;
objHttpReq.BeginUpload (_T ("http://club.hooriza.com")
_T ("/cmd/box.html?clubid=1&boxid=53&action=store&link=")) ;
const DWORD cbProceed = 1024 ;
do {
...
} while ( !(pobjHttpRes = objHttpReq.Proceed (cbProceed)) ) ;
...
} catch (httpclientexception && e) {
...
}How to Handle the Returned CHttpResponse Object
When you send a request usingCHttpClient, all the methods will returnCHttpResponseobject.CHttpResponserepresents the response returned by a HTTP web server.CHttpResponseprovides the following methods:
Collapse
DWORD CHttpResponse::GetHeaderCount (PCSZ szName) throw (Exception &) ;
PCSZ CHttpResponse::GetHeader (PCSZ szName,
DWORD nIdx = 0) throw (Exception &) ;
DWORD CHttpResponse::GetStatus (void) throw (Exception &) ;
PCSZ CHttpResponse::GetStatusText (void) throw (Exception &) ;
BOOL CHttpResponse::GetContentLength (DWORD & cbContLen) throw (Exception &) ;
DWORD CHttpResponse::ReadContent (BYTE * pbyBuff,
DWORD cbBuff) throw (Exception &) ;The following code demonstrates the basic usage of theCHttpResponseobject:
Collapseusing namespace Ryeol ;
CHttpResponse * pobjHttpRes = NULL ;
try {
pobjHttpRes = ... ;
_tprintf (_T ("%u"), pobjHttpRes->GetStatus ()) ;
_tprintf (_T (" %s/n"), pobjHttpRes->GetStatusText ()) ;
static LPCTSTR szHeaders[] =
{ _T ("Server"), _T ("Date"), _T ("X-Powered-By"),
_T ("Content-Length"), _T ("Set-Cookie")
, _T ("Expires"), _T ("Cache-control"),
_T ("Connection"), _T ("Transfer-Encoding")
, _T ("Content-Type") } ;
LPCTSTR szHeader ;
for (size_t i = 0; i < sizeof (szHeaders) / sizeof (LPCTSTR); i++) {
if ( szHeader = pobjHttpRes->GetHeader (szHeaders[i]) )
_tprintf (_T ("%s: %s/n"), szHeaders[i], szHeader) ;
else
_tprintf (_T ("'%s' header does not exist../n"),
szHeaders[i]) ;
}
_tprintf (_T ("/n")) ;
BOOL bIsText = FALSE ;
if ( szHeader = pobjHttpRes->GetHeader (_T ("Content-Type")) )
bIsText = (0 == ::_tcsncicmp (szHeader, _T ("text/"), 5)) ;
DWORD dwContSize ;
if ( !pobjHttpRes->GetContentLength (dwContSize) )
dwContSize = 0 ;
const DWORD cbBuff = 1024 * 10 ;
BYTE byBuff[cbBuff] ;
DWORD dwRead ;
size_t cbTotal = 0 ;
while ( dwRead = pobjHttpRes->ReadContent (byBuff, cbBuff - 1) ) {
cbTotal += dwRead ;
if ( bIsText ) {
byBuff[dwRead] = '/0' ;
printf ("%s", reinterpret_cast<LPCSTR> (byBuff)) ;
}
}
if ( !bIsText )
_tprintf (_T ("%u bytes skipped../n"), cbTotal) ;
} catch (httpclientexception & e) {
...
}
delete pobjHttpRes ;
pobjHttpRes = NULL ;How to Handle Exception
When an error occurs,httpclientexceptionobject is thrown:
Collapseclass httpclientexception {
public:
DWORD LastError (void) const throw () ;
LPCTSTR errmsg (void) const throw () ;
DWORD Win32LastError (void) const throw () ;
} ;Before throwing an exception, most methods restore their internal states (all or nothing like transaction). But if you callBeginPostorBeginUploadmethod, the POST context is automatically canceled. You should write the followingtry-catchblock to handle the exception:
Collapseusing namespace Ryeol ;
try {
...
} catch (httpclientexception & e) {
_tprintf (_T ("An error has been occured/n")) ;
_tprintf (_T ("ErrCode: 0x%x/n"), e.LastError ()) ;
_tprintf (_T ("ErrMsg: %s/n"), e.errmsg ()) ;
if ( e.Win32LastError () != NO_ERROR ) {
TCHAR szErrMsg[512] ;
GetWinInetErrMsg (szErrMsg, 512, e.Win32LastError ()) ;
_tprintf (_T ("Win32ErrCode: 0x%x/n"), e.Win32LastError ()) ;
_tprintf (_T ("Win32ErrMsg: %s/n"), szErrMsg) ;
}
}How to Show the Progress Information to the User
If you callBeginPostorBeginUploadmethod, you can retrieve the progress information using theQuerymethod:
Collapse
void CHttpClient::Query (CHttpPostStat & objPostStat) throw () ;
CHttpPostStatrepresents the progress information of the current POST context. The following code demonstrates the basic usage of theCHttpPostStatobject:
Collapseusing namespace Ryeol ;
CHttpClient objHttpReq ;
CHttpResponse * pobjHttpRes = NULL ;
size_t cbProceed = 1024 ;
try {
... ;
objHttpReq.BeginPost (...) or objHttpReq.BeginUpload (...) ;
CHttpPostStat objPostStat ;
do {
objHttpReq.Query (objPostStat) ;
_tprintf (_T ("/nPost in progress... %2u/%2u/n")
, objPostStat.PostedCount ()
, objPostStat.TotalCount ()) ;
_tprintf (_T ("%s: %10u/%10u %10u/%10u %10u/%10u/n")
, objPostStat.CurrParam ()
, objPostStat.CurrParamPostedByte ()
, objPostStat.CurrParamTotalByte ()
, objPostStat.PostedByte ()
, objPostStat.TotalByte ()
, objPostStat.ActualPostedByte ()
, objPostStat.ActualTotalByte ()) ;
if ( objPostStat.CurrParamIsFile () )
_tprintf (_T ("-->%s/n")
, objPostStat.CurrFile ()) ;
} while ( !(pobjHttpRes = objHttpReq.Proceed (cbProceed)) ) ;
... ;
} catch (httpclientexception & e) {
...
}About CHttpClient COM Edition
CHttpClientCOM Edition is the component version ofCHttpClient. I won't explain here how to use it because it is similar toCHttpClient. You can refer to the attached examples and the help file ofCHttpClientCOM edition. If you want to useCHttpClientCOM edition, you need to installRyeolHttpClient2.dll. Because it is a COM DLL, you have to register it by using theregsvr32.exeprogram. You can install it anywhere you want provided you don't distribute it. But if you want to distribute it, I recommend that you install it in the%WINDOWS%System32folder and do not remove it even if your program is uninstalled.
History
- 3rdFebruary, 2006
- The assertion behavior has been changed to throw an exception if the assertion expression is failed.
- The pragma warning (push) and (pop) directives are used to restore the previous warning state.
- The
SaveContentmethod has been added. - The namespace and file names have been changed.
- CHttpClient COM Edition has been added.
- 9thAugust, 2004
- Some methods have been added to support proxy authorization.
- 29thJuly, 2004