October 14, 2010 at 22:48
filed under Coding
Tagged Coding, curl, gzip
| Download: | Source (11K) |
I wasn’t entirely satisfied with my previous attempt at HTTP/POST gzip-compression, so I wrote a more elegant solution (no XMLRPC libraries this time).
A function to perform gzip-compression on a string:
// see zlib's compress.c:compress() function for the original of this
// modified function
//
// dest : destination buffer, malloc'd already
// destLen : size of the malloc'd buffer
// source : the uncompressed text
// sourceLen : the size of the uncompressed text
//
// this function returns an error code from the zlib library.
// upon return, dest contains the compressed output, and destLen
// contains the size of dest.
int string_gzip (char *dest, unsigned long *destLen, char *source, unsigned long sourceLen)
{
char *header;
sprintf(dest, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1],
Z_DEFLATED, 0 , 0,0,0,0 , 0 , OS_CODE);
// , flags , time , xflags , );
header = dest;
dest = &dest[10]; // skip ahead of the header
*destLen -= 10; // update our available length
z_stream stream;
int err;
stream.next_in = source;
stream.avail_in = sourceLen;
#ifdef MAXSEG_64K
/* Check for source > 64K on 16-bit machine: */
if (stream.avail_in != sourceLen)
return Z_BUF_ERROR;
#endif
stream.next_out = dest;
stream.avail_out = *destLen;
if (stream.avail_out != *destLen)
return Z_BUF_ERROR;
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
// instructs zlib not to write a zlib header
err = deflateInit2( &stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY );
if (err != Z_OK)
return err;
err = deflate(&stream, Z_FINISH); // Z_FINISH or Z_NO_FLUSH if we have
// more input still (we don't)
if (err != Z_STREAM_END) {
deflateEnd(&stream);
return err == Z_OK ? Z_BUF_ERROR : err;
}
*destLen = stream.total_out;
err = deflateEnd(&stream);
dest = header; // put the header back on
*destLen += 10; // update length of our data block
return err;
}
Using this function to make a gzip-compressed HTTP/POST using libcURL:
char *data = readXMLInput();
unsigned long dataLength = strlen(data);
unsigned long compressedDataLength = dataLength*1.1 + 22; // see zlib's compress.c
char *compressedData = calloc(compressedDataLength,1);
string_gzip(compressedData, &compressedDataLength, (char*)data, dataLength);
curl = curl_easy_init();
struct curl_slist *header_list=NULL;
curl_easy_setopt(curl, CURLOPT_URL, "www.example.com/xmlrpc.php");
// set the "Accept-Encoding: " header
curl_easy_setopt(curl, CURLOPT_ENCODING, "gzip");
// set the "Content-Encoding: ", "Content-Length: ", "Content-Type: " headers
header_list = curl_slist_append(header_list, "Content-Encoding: gzip");
header_list = curl_slist_append(header_list, "Content-Type: text/xml");
sprintf(contentLengthBuf, "Content-Length: %d", compressedDataLength);
header_list = curl_slist_append(header_list, contentLengthBuf);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, header_list);
// Now specify the POST data
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, compressedData);
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, compressedDataLength);
// Perform request
res = curl_easy_perform(curl);
curl_slist_free_all(header_list);
curl_easy_cleanup(curl);
free(compressedData);
no comments
RSS / trackback