Ben Copsey

Parse text encoding from Content-Type header when supplied

Thanks to Shaun Harrison for this suggestion!
... ... @@ -166,6 +166,9 @@ typedef enum _ASINetworkErrorType {
BOOL haveBuiltPostBody;
unsigned long long uploadBufferSize;
NSStringEncoding defaultResponseEncoding;
NSStringEncoding responseEncoding;
}
#pragma mark init / dealloc
... ... @@ -305,4 +308,6 @@ typedef enum _ASINetworkErrorType {
@property (assign) BOOL showAccurateProgress;
@property (assign,readonly) unsigned long long totalBytesRead;
@property (assign) unsigned long long uploadBufferSize;
@property (assign) NSStringEncoding defaultResponseEncoding;
@property (assign) NSStringEncoding responseEncoding;
@end
... ...
... ... @@ -72,6 +72,7 @@ static NSError *ASIUnableToCreateRequestError;
requestAuthentication = NULL;
haveBuiltPostBody = NO;
request = NULL;
[self setDefaultResponseEncoding:NSISOLatin1StringEncoding];
[self setUploadBufferSize:0];
[self setResponseHeaders:nil];
[self setTimeOutSeconds:10];
... ... @@ -171,7 +172,8 @@ static NSError *ASIUnableToCreateRequestError;
if (!receivedData) {
return nil;
}
return [[[NSString alloc] initWithBytes:[receivedData bytes] length:[receivedData length] encoding:NSUTF8StringEncoding] autorelease];
return [[[NSString alloc] initWithBytes:[receivedData bytes] length:[receivedData length] encoding:[self responseEncoding]] autorelease];
}
... ... @@ -738,6 +740,22 @@ static NSError *ASIUnableToCreateRequestError;
}
}
// Handle response text encoding
// If the Content-Type header specified an encoding, we'll use that, otherwise we use defaultStringEncoding (which defaults to NSISOLatin1StringEncoding)
NSString *contentType = [[self responseHeaders] objectForKey:@"Content-Type"];
NSStringEncoding encoding = [self defaultResponseEncoding];
if (contentType) {
NSArray *parts = [contentType componentsSeparatedByString:@"="];
NSString *IANAEncoding = [parts objectAtIndex:[parts count]-1];
if (IANAEncoding) {
CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)IANAEncoding);
if (cfEncoding != kCFStringEncodingInvalidId) {
encoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding);
}
}
}
[self setResponseEncoding:encoding];
// Handle cookies
NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:responseHeaders forURL:url];
[self setResponseCookies:cookies];
... ... @@ -1182,4 +1200,6 @@ static NSError *ASIUnableToCreateRequestError;
@synthesize showAccurateProgress;
@synthesize totalBytesRead;
@synthesize uploadBufferSize;
@synthesize defaultResponseEncoding;
@synthesize responseEncoding;
@end
... ...
... ... @@ -24,5 +24,6 @@
- (void)testCookies;
- (void)testBasicAuthentication;
- (void)testDigestAuthentication;
- (void)testCharacterEncoding;
@end
... ...
... ... @@ -53,9 +53,31 @@
STAssertTrue(success,@"Failed to generate an error for a bad host");
}
- (void)testCharacterEncoding
{
NSArray *IANAEncodings = [NSArray arrayWithObjects:@"UTF-8",@"US-ASCII",@"ISO-8859-1",@"UTF-16",nil];
NSUInteger NSStringEncodings[] = {NSUTF8StringEncoding,NSASCIIStringEncoding,NSISOLatin1StringEncoding,NSUnicodeStringEncoding};
int i;
for (i=0; i<[IANAEncodings count]; i++) {
NSURL *url = [[[NSURL alloc] initWithString:[NSString stringWithFormat:@"http://allseeing-i.com/ASIHTTPRequest/tests/Character-Encoding/%@",[IANAEncodings objectAtIndex:i]]] autorelease];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request start];
BOOL success = [request responseEncoding] == NSStringEncodings[i];
STAssertTrue(success,[NSString stringWithFormat:@"Failed to use the correct text encoding for %@i",[IANAEncodings objectAtIndex:i]]);
}
NSURL *url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/Character-Encoding/Something-else"] autorelease];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setDefaultResponseEncoding:NSWindowsCP1251StringEncoding];
[request start];
BOOL success = [request responseEncoding] == [request defaultResponseEncoding];
STAssertTrue(success,[NSString stringWithFormat:@"Failed to use the default string encoding"]);
}
- (void)testTimeOut
{
//Grab data
NSURL *url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com"] autorelease];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request setTimeOutSeconds:0.0001]; //It's pretty unlikely we will be able to grab the data this quickly, so the request should timeout
... ...