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);
Send me an email, then I'll place our discussion on this page (with your permission).