Added Gzip support
Summary: Added Gzip function to RCTUtils. This uses dlopen to load the zlib library at runtime so there's no need to link it into your project. The main reason for this feature is to support gzipping of HTTP request bodies. Now, if you add 'Content-Encoding:gzip' to your request headers when using XMLHttpRequest, your request body will be automatically gzipped on the native side before sending. (Note: Gzip decoding of *response* bodies is handled automatically by iOS, and was already available).
This commit is contained in:
parent
36f76e5893
commit
81ad713f5f
|
@ -249,8 +249,15 @@ RCT_EXPORT_MODULE()
|
||||||
request.HTTPBody = result[@"body"];
|
request.HTTPBody = result[@"body"];
|
||||||
NSString *contentType = result[@"contentType"];
|
NSString *contentType = result[@"contentType"];
|
||||||
if (contentType) {
|
if (contentType) {
|
||||||
[request setValue:contentType forHTTPHeaderField:@"content-type"];
|
[request setValue:contentType forHTTPHeaderField:@"Content-Type"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gzip the request body
|
||||||
|
if ([request.allHTTPHeaderFields[@"Content-Encoding"] isEqualToString:@"gzip"]) {
|
||||||
|
request.HTTPBody = RCTGzipData(request.HTTPBody, -1 /* default */);
|
||||||
|
[request setValue:[@(request.HTTPBody.length) description] forHTTPHeaderField:@"Content-Length"];
|
||||||
|
}
|
||||||
|
|
||||||
[self sendRequest:request
|
[self sendRequest:request
|
||||||
incrementalUpdates:incrementalUpdates
|
incrementalUpdates:incrementalUpdates
|
||||||
responseSender:responseSender];
|
responseSender:responseSender];
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#import "RCTAssert.h"
|
#import "RCTAssert.h"
|
||||||
#import "RCTDefines.h"
|
#import "RCTDefines.h"
|
||||||
|
|
||||||
// Utility functions for JSON object <-> string serialization/deserialization
|
// JSON serialization/deserialization
|
||||||
RCT_EXTERN NSString *RCTJSONStringify(id jsonObject, NSError **error);
|
RCT_EXTERN NSString *RCTJSONStringify(id jsonObject, NSError **error);
|
||||||
RCT_EXTERN id RCTJSONParse(NSString *jsonString, NSError **error);
|
RCT_EXTERN id RCTJSONParse(NSString *jsonString, NSError **error);
|
||||||
RCT_EXTERN id RCTJSONParseMutable(NSString *jsonString, NSError **error);
|
RCT_EXTERN id RCTJSONParseMutable(NSString *jsonString, NSError **error);
|
||||||
|
@ -24,7 +24,7 @@ RCT_EXTERN id RCTJSONParseWithOptions(NSString *jsonString, NSError **error, NSJ
|
||||||
// Strip non JSON-safe values from an object graph
|
// Strip non JSON-safe values from an object graph
|
||||||
RCT_EXTERN id RCTJSONClean(id object);
|
RCT_EXTERN id RCTJSONClean(id object);
|
||||||
|
|
||||||
// Get MD5 hash of a string (TODO: currently unused. Remove?)
|
// Get MD5 hash of a string
|
||||||
RCT_EXTERN NSString *RCTMD5Hash(NSString *string);
|
RCT_EXTERN NSString *RCTMD5Hash(NSString *string);
|
||||||
|
|
||||||
// Get screen metrics in a thread-safe way
|
// Get screen metrics in a thread-safe way
|
||||||
|
@ -64,3 +64,6 @@ RCT_EXTERN id RCTNullIfNil(id value);
|
||||||
|
|
||||||
// Convert data to a Base64-encoded data URL
|
// Convert data to a Base64-encoded data URL
|
||||||
RCT_EXTERN NSURL *RCTDataURL(NSString *mimeType, NSData *data);
|
RCT_EXTERN NSURL *RCTDataURL(NSString *mimeType, NSData *data);
|
||||||
|
|
||||||
|
// Gzip functionality - compression level in range 0 - 1 (-1 for default)
|
||||||
|
RCT_EXTERN NSData *RCTGzipData(NSData *data, float level);
|
||||||
|
|
|
@ -10,12 +10,15 @@
|
||||||
#import "RCTUtils.h"
|
#import "RCTUtils.h"
|
||||||
|
|
||||||
#import <mach/mach_time.h>
|
#import <mach/mach_time.h>
|
||||||
#import <objc/runtime.h>
|
#import <objc/message.h>
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
#import <CommonCrypto/CommonCrypto.h>
|
#import <CommonCrypto/CommonCrypto.h>
|
||||||
|
|
||||||
|
#import <zlib.h>
|
||||||
|
#import <dlfcn.h>
|
||||||
|
|
||||||
#import "RCTLog.h"
|
#import "RCTLog.h"
|
||||||
|
|
||||||
NSString *RCTJSONStringify(id jsonObject, NSError **error)
|
NSString *RCTJSONStringify(id jsonObject, NSError **error)
|
||||||
|
@ -305,3 +308,51 @@ NSURL *RCTDataURL(NSString *mimeType, NSData *data)
|
||||||
[data base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)0]]];
|
[data base64EncodedStringWithOptions:(NSDataBase64EncodingOptions)0]]];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL RCTIsGzippedData(NSData *data)
|
||||||
|
{
|
||||||
|
UInt8 *bytes = (UInt8 *)data.bytes;
|
||||||
|
return (data.length >= 2 && bytes[0] == 0x1f && bytes[1] == 0x8b);
|
||||||
|
}
|
||||||
|
|
||||||
|
NSData *RCTGzipData(NSData *input, float level)
|
||||||
|
{
|
||||||
|
if (input.length == 0 || RCTIsGzippedData(input)) {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *libz = dlopen("libz.dylib", RTLD_NOW);
|
||||||
|
int (*deflateInit2_)(z_streamp, int, int, int, int, int, const char *, int) = dlsym(libz, "deflateInit2_");
|
||||||
|
int (*deflate)(z_streamp, int) = dlsym(libz, "deflate");
|
||||||
|
int (*deflateEnd)(z_streamp) = dlsym(libz, "deflateEnd");
|
||||||
|
|
||||||
|
z_stream stream;
|
||||||
|
stream.zalloc = Z_NULL;
|
||||||
|
stream.zfree = Z_NULL;
|
||||||
|
stream.opaque = Z_NULL;
|
||||||
|
stream.avail_in = (uint)input.length;
|
||||||
|
stream.next_in = (Bytef *)input.bytes;
|
||||||
|
stream.total_out = 0;
|
||||||
|
stream.avail_out = 0;
|
||||||
|
|
||||||
|
static const NSUInteger RCTGZipChunkSize = 16384;
|
||||||
|
|
||||||
|
NSMutableData *output = nil;
|
||||||
|
int compression = (level < 0.0f)? Z_DEFAULT_COMPRESSION: (int)(roundf(level * 9));
|
||||||
|
if (deflateInit2(&stream, compression, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY) == Z_OK) {
|
||||||
|
output = [NSMutableData dataWithLength:RCTGZipChunkSize];
|
||||||
|
while (stream.avail_out == 0) {
|
||||||
|
if (stream.total_out >= output.length) {
|
||||||
|
output.length += RCTGZipChunkSize;
|
||||||
|
}
|
||||||
|
stream.next_out = (uint8_t *)output.mutableBytes + stream.total_out;
|
||||||
|
stream.avail_out = (uInt)(output.length - stream.total_out);
|
||||||
|
deflate(&stream, Z_FINISH);
|
||||||
|
}
|
||||||
|
deflateEnd(&stream);
|
||||||
|
output.length = stream.total_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
dlclose(libz);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue