Introduction
CHttpClient
is 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 your stdafx.h file, add the following line:
#include "RyeolHttpClient.h"
Note: The namespace and file names have been changed. If you use the previous version of the CHttpClient
, 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
CHttpClient
supports RequestGet
method which sends a request using HTTP GET:
CHttpResponse * CHttpClient::RequestGet (PCSZ szUrl,
BOOL bUseCache = FALSE) throw (Exception &) ;
The following code demonstrates the basic usage of the RequestGet
method:
using 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, CHttpClient
provides BeginPost
method.
void CHttpClient::BeginPost (PCSZ szUrl,
BOOL bUseCache = FALSE) throw (Exception &) ;
The following code demonstrates the basic usage of the BeginPost
method:
using 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, CHttpClient
provides BeginUpload
method.
void CHttpClient::BeginUpload (PCSZ szUrl,
BOOL bUseCache = FALSE) throw (Exception &) ;
The following code demonstrates the basic usage of the BeginUpload
method:
using 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 using CHttpClient
, all the methods will return CHttpResponse
object. CHttpResponse
represents the response returned by a HTTP web server. CHttpResponse
provides the following methods:
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 the CHttpResponse
object:
using 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, httpclientexception
object is thrown:
class 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 call BeginPost
or BeginUpload
method, the POST context is automatically canceled. You should write the following try
-catch
block to handle the exception:
using 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 call BeginPost
or BeginUpload
method, you can retrieve the progress information using the Query
method:
void CHttpClient::Query (CHttpPostStat & objPostStat) throw () ;
CHttpPostStat
represents the progress information of the current POST context. The following code demonstrates the basic usage of the CHttpPostStat
object:
using 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
CHttpClient
COM Edition is the component version of CHttpClient
. I won't explain here how to use it because it is similar to CHttpClient
. You can refer to the attached examples and the help file of CHttpClient
COM edition. If you want to use CHttpClient
COM edition, you need to install RyeolHttpClient2.dll. Because it is a COM DLL, you have to register it by using the regsvr32.exe program. 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%System32 folder and do not remove it even if your program is uninstalled.
History
- 3rd February, 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
SaveContent
method has been added.
- The namespace and file names have been changed.
- CHttpClient COM Edition has been added.
- 9th August, 2004
- Some methods have been added to support proxy authorization.
- 29th July, 2004