The qDecoder Project

qHttpClient.c File Reference

HTTP client API. More...


Defines

#define HTTP_NO_RESPONSE   (0)
#define HTTP_CODE_CONTINUE   (100)
#define HTTP_CODE_OK   (200)
#define HTTP_CODE_CREATED   (201)
#define HTTP_CODE_NO_CONTENT   (204)
#define HTTP_CODE_MULTI_STATUS   (207)
#define HTTP_CODE_MOVED_TEMPORARILY   (302)
#define HTTP_CODE_NOT_MODIFIED   (304)
#define HTTP_CODE_BAD_REQUEST   (400)
#define HTTP_CODE_FORBIDDEN   (403)
#define HTTP_CODE_NOT_FOUND   (404)
#define HTTP_CODE_METHOD_NOT_ALLOWED   (405)
#define HTTP_CODE_REQUEST_TIME_OUT   (408)
#define HTTP_CODE_REQUEST_URI_TOO_LONG   (414)
#define HTTP_CODE_INTERNAL_SERVER_ERROR   (500)
#define HTTP_CODE_NOT_IMPLEMENTED   (501)
#define HTTP_CODE_SERVICE_UNAVAILABLE   (503)
#define HTTP_PROTOCOL_11   "HTTP/1.1"
#define SET_TCP_LINGER_TIMEOUT   (15)
#define SET_TCP_NODELAY   (1)
#define MAX_SHUTDOWN_WAIT   (5 * 1000)
#define MAX_ATOMIC_DATA_SIZE   (32 * 1024)

Functions

Q_HTTPCLIENTqHttpClient (const char *hostname, int port)
 Initialize & create new HTTP client.
static void _setTimeout (Q_HTTPCLIENT *client, int timeoutms)
 Q_HTTPCLIENT->setTimeout(): Set connection wait timeout.
static void _setKeepalive (Q_HTTPCLIENT *client, bool keepalive)
 Q_HTTPCLIENT->setKeepalive(): Set KEEP-ALIVE feature on/off.
static void _setUseragent (Q_HTTPCLIENT *client, const char *useragent)
 Q_HTTPCLIENT->setUseragent(): Set user-agent string.
static bool _open (Q_HTTPCLIENT *client)
 Q_HTTPCLIENT->open(): Open(establish) connection to the remote host.
static bool _sendRequest (Q_HTTPCLIENT *client, const char *method, const char *uri, Q_ENTRY *reqheaders)
 Q_HTTPCLIENT->sendRequest(): Send HTTP request to the remote host.
static int _readResponse (Q_HTTPCLIENT *client, Q_ENTRY *resheaders)
 Q_HTTPCLIENT->readResponse(): Read and parse HTTP response from the remote host.
static bool _get (Q_HTTPCLIENT *client, const char *uri, int fd, off_t *savesize, int *rescode, Q_ENTRY *reqheaders, Q_ENTRY *resheaders, bool(*callback)(void *userdata, off_t recvbytes), void *userdata)
 Q_HTTPCLIENT->get(): Download file from remote host using GET method.
static bool _put (Q_HTTPCLIENT *client, const char *uri, int fd, off_t length, int *rescode, Q_ENTRY *reqheaders, Q_ENTRY *resheaders, bool(*callback)(void *userdata, off_t sentbytes), void *userdata)
 Q_HTTPCLIENT->put(): Upload file to remote host using PUT method.
static void * _cmd (Q_HTTPCLIENT *client, const char *method, const char *uri, int *rescode, size_t *contentslength, Q_ENTRY *reqheaders, Q_ENTRY *resheaders)
 Q_HTTPCLIENT->cmd(): Send custom method to remote host.
static bool _close (Q_HTTPCLIENT *client)
 Q_HTTPCLIENT->close(): Close the connection.
static void _free (Q_HTTPCLIENT *client)
 Q_HTTPCLIENT->free(): De-allocate object.


Detailed Description

HTTP client API.


Function Documentation

Q_HTTPCLIENT* qHttpClient ( const char *  hostname,
int  port 
)

Initialize & create new HTTP client.

Parameters:
hostname remote IP or FQDN domain name
port remote port number
Returns:
HTTP client object if succcessful, otherwise returns NULL.
   // create new HTTP client
   Q_HTTPCLIENT *httpClient = qHttpClient("www.qdecoder.org", 80);
   if(httpClient == NULL) return;

   // set options
   httpClient->setKeepalive(httpClient, true);

   // make a connection
   if(httpClient->open(httpClient) == false) return;

   // upload files
   httpClient->put(httpClient, ...);
   httpClient->put(httpClient, ...); // this will be done within same connection using KEEP-ALIVE

   // close connection - not necessary, just for example
   httpClient->close(httpClient);

   // de-allocate HTTP client object
   httpClient->free(httpClient);

static void _setTimeout ( Q_HTTPCLIENT client,
int  timeoutms 
) [static]

Q_HTTPCLIENT->setTimeout(): Set connection wait timeout.

Parameters:
client Q_HTTPCLIENT object pointer
timeoutms timeout mili-seconds. 0 for system defaults
   httpClient->setTimeout(httpClient, 0);    // default
   httpClient->setTimeout(httpClient, 5000); // 5 seconds

static void _setKeepalive ( Q_HTTPCLIENT client,
bool  keepalive 
) [static]

Q_HTTPCLIENT->setKeepalive(): Set KEEP-ALIVE feature on/off.

Parameters:
client Q_HTTPCLIENT object pointer
keepalive true to set keep-alive on, false to set keep-alive off
   httpClient->setKeepalive(httpClient, true);  // keep-alive on
   httpClient->setKeepalive(httpClient, false); // keep-alive off

static void _setUseragent ( Q_HTTPCLIENT client,
const char *  useragent 
) [static]

Q_HTTPCLIENT->setUseragent(): Set user-agent string.

Parameters:
client Q_HTTPCLIENT object pointer
useragent user-agent string
   httpClient->setUseragent(httpClient, "qDecoderAgent/1.0");

static bool _open ( Q_HTTPCLIENT client  )  [static]

Q_HTTPCLIENT->open(): Open(establish) connection to the remote host.

Parameters:
client Q_HTTPCLIENT object pointer
Returns:
true if successful, otherwise returns false
Note:
Don't need to open a connection unless you definitely need to do this, because qHttpClient open a connection automatically when it's needed. This function also can be used to veryfy a connection failure with remote host.
   if(httpClient->open(httpClient) == false) return;

static bool _sendRequest ( Q_HTTPCLIENT client,
const char *  method,
const char *  uri,
Q_ENTRY reqheaders 
) [static]

Q_HTTPCLIENT->sendRequest(): Send HTTP request to the remote host.

Parameters:
client Q_HTTPCLIENT object pointer
method HTTP method name
uri URI string for the method. ("/path" or "http://.../path")
reqheaders Q_ENTRY pointer which contains additional user request headers. (can be NULL)
Returns:
true if successful, otherwise returns false
Note:
3 default headers(Host, User-Agent, Connection) will be sent if reqheaders does not have those headers in it.
   Q_ENTRY *reqheaders = qEntry();
   reqheaders->putStr(reqheaders,  "Date", qTimeGetGmtStaticStr(0), true);

   httpClient->sendRequest(client, "DELETE", "/img/qdecoder.png", reqheaders);

static int _readResponse ( Q_HTTPCLIENT client,
Q_ENTRY resheaders 
) [static]

Q_HTTPCLIENT->readResponse(): Read and parse HTTP response from the remote host.

Parameters:
client Q_HTTPCLIENT object pointer
resheaders Q_ENTRY pointer for storing response headers. (can be NULL)
Returns:
numeric HTTP response code if successful, otherwise returns 0.
   // send request
   httpClient->sendRequest(client, "DELETE", "/img/qdecoder.png", NULL);

   // read response
   Q_ENTRY *resheaders = qEntry();
   int rescode = httpClient->readResponse(client, resheaders);

static bool _get ( Q_HTTPCLIENT client,
const char *  uri,
int  fd,
off_t *  savesize,
int *  rescode,
Q_ENTRY reqheaders,
Q_ENTRY resheaders,
bool(*)(void *userdata, off_t recvbytes)  callback,
void *  userdata 
) [static]

Q_HTTPCLIENT->get(): Download file from remote host using GET method.

Parameters:
client Q_HTTPCLIENT object pointer.
uri remote URL for downloading file. ("/path" or "http://.../path")
fd opened file descriptor for writing.
savesize if not NULL, the length of stored bytes will be stored. (can be NULL)
rescode if not NULL, remote response code will be stored. (can be NULL)
reqheaders Q_ENTRY pointer which contains additional user request headers. (can be NULL)
resheaders Q_ENTRY pointer for storing response headers. (can be NULL)
callback set user call-back function. (can be NULL)
userdata set user data for call-back. (can be NULL)
Returns:
true if successful, otherwise returns false
Note:
The call-back function will be called peridically whenever it send data as much as MAX_ATOMIC_DATA_SIZE. To stop uploading, return false in the call-back function, then PUT process will be stopped immediately. If a connection was not opened, it will open a connection automatically.
   struct userdata {
     ...
   };

   static bool callback(void *userdata, off_t sentbytes) {
     struct userdata *pMydata = (struct userdata*)userdata;
     ...(codes)...
     if(need_to_cancel) return false; // stop file uploading immediately
     return true;
   }

   main() {
     // create new HTTP client
     Q_HTTPCLIENT *httpClient = qHttpClient("www.qdecoder.org", 80);
     if(httpClient == NULL) return;

     // open file
     int nFd = open("/tmp/test.data", O_WRONLY | O_CREAT, 0644);

     // set additional custom headers
     Q_ENTRY *pReqHeaders = qEntry();
     Q_ENTRY *pResHeaders = qEntry();

     // set userdata
     struct userdata mydata;
     ...(codes)...

     // send file
     int nRescode = 0;
     off_t nSavesize = 0;
     bool bRet = httpClient->get(httpClient, "/img/qdecoder.png", nFd, &nSavesize, &nRescode,
                                 pReqHeaders, pResHeaders,
                                 callback, (void*)&mydata);
     // to print out request, response headers
     pReqHeaders->print(pReqHeaders, stdout, true);
     pResHeaders->print(pResHeaders, stdout, true);

     // check results
     if(bRet == false) {
       ...(error occured)...
     }

     // free resources
     httpClient->free(httpClient);
     pReqHeaders->free(pReqHeaders);
     pResHeaders->free(pResHeaders);
     close(nFd);
   }

static bool _put ( Q_HTTPCLIENT client,
const char *  uri,
int  fd,
off_t  length,
int *  rescode,
Q_ENTRY reqheaders,
Q_ENTRY resheaders,
bool(*)(void *userdata, off_t sentbytes)  callback,
void *  userdata 
) [static]

Q_HTTPCLIENT->put(): Upload file to remote host using PUT method.

Parameters:
client Q_HTTPCLIENT object pointer.
uri remote URL for uploading file. ("/path" or "http://.../path")
fd opened file descriptor for reading.
length send size.
rescode if not NULL, remote response code will be stored. (can be NULL)
reqheaders Q_ENTRY pointer which contains additional user request headers. (can be NULL)
resheaders Q_ENTRY pointer for storing response headers. (can be NULL)
callback set user call-back function. (can be NULL)
userdata set user data for call-back. (can be NULL)
Returns:
true if successful, otherwise returns false
Note:
The call-back function will be called peridically whenever it send data as much as MAX_ATOMIC_DATA_SIZE. To stop uploading, return false in the call-back function, then PUT process will be stopped immediately. If a connection was not opened, it will open a connection automatically.
   struct userdata {
     ...
   };

   static bool callback(void *userdata, off_t sentbytes) {
     struct userdata *pMydata = (struct userdata*)userdata;
     ...(codes)...
     if(need_to_cancel) return false; // stop file uploading immediately
     return true;
   }

   main() {
     // create new HTTP client
     Q_HTTPCLIENT *httpClient = qHttpClient("www.qdecoder.org", 80);
     if(httpClient == NULL) return;

     // open file
     int nFd = open(...);
     off_t nFileSize = ...;
     char *pFileMd5sum = ...;
     time_t nFileDate = ...;

     // set additional custom headers
     Q_ENTRY *pReqHeaders = qEntry();
     pReqHeaders->putStr(pReqHeaders, "X-FILE-MD5SUM", pFileMd5sum, true);
     pReqHeaders->putInt(pReqHeaders, "X-FILE-DATE", nFileDate, true);

     // set userdata
     struct userdata mydata;
     ...(codes)...

     // send file
     int nRescode = 0;
     Q_ENTRY *pResHeaders = qEntry();
     bool bRet = httpClient->put(httpClient, "/img/qdecoder.png", nFd, nFileSize, &nRescode,
                                      pReqHeaders, pResHeaders,
                                      callback, (void*)&mydata);
     // to print out request, response headers
     pReqHeaders->print(pReqHeaders, stdout, true);
     pResHeaders->print(pResHeaders, stdout, true);

     // check results
     if(bRet == false) {
       ...(error occured)...
     }

     // free resources
     httpClient->free(httpClient);
     pReqHeaders->free(pReqHeaders);
     pResHeaders->free(pResHeaders);
     close(nFd);
   }

static void* _cmd ( Q_HTTPCLIENT client,
const char *  method,
const char *  uri,
int *  rescode,
size_t *  contentslength,
Q_ENTRY reqheaders,
Q_ENTRY resheaders 
) [static]

Q_HTTPCLIENT->cmd(): Send custom method to remote host.

Parameters:
client Q_HTTPCLIENT object pointer.
method method name.
uri remote URL for uploading file. ("/path" or "http://.../path")
rescode if not NULL, remote response code will be stored. (can be NULL)
contentslength if not NULL, the contents length will be stored. (can be NULL)
reqheaders Q_ENTRY pointer which contains additional user request headers. (can be NULL)
resheaders Q_ENTRY pointer for storing response headers. (can be NULL)
Returns:
malloced contents data if successful, otherwise returns NULL
   int nResCode;
   size_t nContentsLength;
   void *contents = httpClient->cmd(httpClient, "DELETE" "/img/qdecoder.png",
                                      &nRescode, &nContentsLength
                                      NULL, NULL);
   if(contents == NULL) {
     ...(error occured)...
   } else {
     printf("Response code : %d\n", nResCode);
     printf("Contents length : %zu\n", nContentsLength);
     printf("Contents : %s\n", (char*)contents);  // if contents is printable
     free(contents);  // de-allocate
   }

static bool _close ( Q_HTTPCLIENT client  )  [static]

Q_HTTPCLIENT->close(): Close the connection.

Parameters:
Q_HTTPCLIENT HTTP object pointer
Returns:
true if successful, otherwise returns false
   httpClient->close(httpClient);

static void _free ( Q_HTTPCLIENT client  )  [static]

Q_HTTPCLIENT->free(): De-allocate object.

Parameters:
Q_HTTPCLIENT HTTP object pointer
Note:
If the connection was not closed, it will close the connection first prior to de-allocate object.
   httpClient->free(httpClient);


Copyright (c) 2008 The qDecoder Project