Parse text encoding from Content-Type header when supplied
Thanks to Shaun Harrison for this suggestion!
Showing
4 changed files
with
50 additions
and
2 deletions
| @@ -166,6 +166,9 @@ typedef enum _ASINetworkErrorType { | @@ -166,6 +166,9 @@ typedef enum _ASINetworkErrorType { | ||
| 166 | BOOL haveBuiltPostBody; | 166 | BOOL haveBuiltPostBody; |
| 167 | 167 | ||
| 168 | unsigned long long uploadBufferSize; | 168 | unsigned long long uploadBufferSize; |
| 169 | + | ||
| 170 | + NSStringEncoding defaultResponseEncoding; | ||
| 171 | + NSStringEncoding responseEncoding; | ||
| 169 | } | 172 | } |
| 170 | 173 | ||
| 171 | #pragma mark init / dealloc | 174 | #pragma mark init / dealloc |
| @@ -305,4 +308,6 @@ typedef enum _ASINetworkErrorType { | @@ -305,4 +308,6 @@ typedef enum _ASINetworkErrorType { | ||
| 305 | @property (assign) BOOL showAccurateProgress; | 308 | @property (assign) BOOL showAccurateProgress; |
| 306 | @property (assign,readonly) unsigned long long totalBytesRead; | 309 | @property (assign,readonly) unsigned long long totalBytesRead; |
| 307 | @property (assign) unsigned long long uploadBufferSize; | 310 | @property (assign) unsigned long long uploadBufferSize; |
| 311 | +@property (assign) NSStringEncoding defaultResponseEncoding; | ||
| 312 | +@property (assign) NSStringEncoding responseEncoding; | ||
| 308 | @end | 313 | @end |
| @@ -72,6 +72,7 @@ static NSError *ASIUnableToCreateRequestError; | @@ -72,6 +72,7 @@ static NSError *ASIUnableToCreateRequestError; | ||
| 72 | requestAuthentication = NULL; | 72 | requestAuthentication = NULL; |
| 73 | haveBuiltPostBody = NO; | 73 | haveBuiltPostBody = NO; |
| 74 | request = NULL; | 74 | request = NULL; |
| 75 | + [self setDefaultResponseEncoding:NSISOLatin1StringEncoding]; | ||
| 75 | [self setUploadBufferSize:0]; | 76 | [self setUploadBufferSize:0]; |
| 76 | [self setResponseHeaders:nil]; | 77 | [self setResponseHeaders:nil]; |
| 77 | [self setTimeOutSeconds:10]; | 78 | [self setTimeOutSeconds:10]; |
| @@ -171,7 +172,8 @@ static NSError *ASIUnableToCreateRequestError; | @@ -171,7 +172,8 @@ static NSError *ASIUnableToCreateRequestError; | ||
| 171 | if (!receivedData) { | 172 | if (!receivedData) { |
| 172 | return nil; | 173 | return nil; |
| 173 | } | 174 | } |
| 174 | - return [[[NSString alloc] initWithBytes:[receivedData bytes] length:[receivedData length] encoding:NSUTF8StringEncoding] autorelease]; | 175 | + |
| 176 | + return [[[NSString alloc] initWithBytes:[receivedData bytes] length:[receivedData length] encoding:[self responseEncoding]] autorelease]; | ||
| 175 | } | 177 | } |
| 176 | 178 | ||
| 177 | 179 | ||
| @@ -738,6 +740,22 @@ static NSError *ASIUnableToCreateRequestError; | @@ -738,6 +740,22 @@ static NSError *ASIUnableToCreateRequestError; | ||
| 738 | } | 740 | } |
| 739 | } | 741 | } |
| 740 | 742 | ||
| 743 | + // Handle response text encoding | ||
| 744 | + // If the Content-Type header specified an encoding, we'll use that, otherwise we use defaultStringEncoding (which defaults to NSISOLatin1StringEncoding) | ||
| 745 | + NSString *contentType = [[self responseHeaders] objectForKey:@"Content-Type"]; | ||
| 746 | + NSStringEncoding encoding = [self defaultResponseEncoding]; | ||
| 747 | + if (contentType) { | ||
| 748 | + NSArray *parts = [contentType componentsSeparatedByString:@"="]; | ||
| 749 | + NSString *IANAEncoding = [parts objectAtIndex:[parts count]-1]; | ||
| 750 | + if (IANAEncoding) { | ||
| 751 | + CFStringEncoding cfEncoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)IANAEncoding); | ||
| 752 | + if (cfEncoding != kCFStringEncodingInvalidId) { | ||
| 753 | + encoding = CFStringConvertEncodingToNSStringEncoding(cfEncoding); | ||
| 754 | + } | ||
| 755 | + } | ||
| 756 | + } | ||
| 757 | + [self setResponseEncoding:encoding]; | ||
| 758 | + | ||
| 741 | // Handle cookies | 759 | // Handle cookies |
| 742 | NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:responseHeaders forURL:url]; | 760 | NSArray *cookies = [NSHTTPCookie cookiesWithResponseHeaderFields:responseHeaders forURL:url]; |
| 743 | [self setResponseCookies:cookies]; | 761 | [self setResponseCookies:cookies]; |
| @@ -1182,4 +1200,6 @@ static NSError *ASIUnableToCreateRequestError; | @@ -1182,4 +1200,6 @@ static NSError *ASIUnableToCreateRequestError; | ||
| 1182 | @synthesize showAccurateProgress; | 1200 | @synthesize showAccurateProgress; |
| 1183 | @synthesize totalBytesRead; | 1201 | @synthesize totalBytesRead; |
| 1184 | @synthesize uploadBufferSize; | 1202 | @synthesize uploadBufferSize; |
| 1203 | +@synthesize defaultResponseEncoding; | ||
| 1204 | +@synthesize responseEncoding; | ||
| 1185 | @end | 1205 | @end |
| @@ -53,9 +53,31 @@ | @@ -53,9 +53,31 @@ | ||
| 53 | STAssertTrue(success,@"Failed to generate an error for a bad host"); | 53 | STAssertTrue(success,@"Failed to generate an error for a bad host"); |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | +- (void)testCharacterEncoding | ||
| 57 | +{ | ||
| 58 | + | ||
| 59 | + NSArray *IANAEncodings = [NSArray arrayWithObjects:@"UTF-8",@"US-ASCII",@"ISO-8859-1",@"UTF-16",nil]; | ||
| 60 | + NSUInteger NSStringEncodings[] = {NSUTF8StringEncoding,NSASCIIStringEncoding,NSISOLatin1StringEncoding,NSUnicodeStringEncoding}; | ||
| 61 | + | ||
| 62 | + int i; | ||
| 63 | + for (i=0; i<[IANAEncodings count]; i++) { | ||
| 64 | + NSURL *url = [[[NSURL alloc] initWithString:[NSString stringWithFormat:@"http://allseeing-i.com/ASIHTTPRequest/tests/Character-Encoding/%@",[IANAEncodings objectAtIndex:i]]] autorelease]; | ||
| 65 | + ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease]; | ||
| 66 | + [request start]; | ||
| 67 | + BOOL success = [request responseEncoding] == NSStringEncodings[i]; | ||
| 68 | + STAssertTrue(success,[NSString stringWithFormat:@"Failed to use the correct text encoding for %@i",[IANAEncodings objectAtIndex:i]]); | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + NSURL *url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/Character-Encoding/Something-else"] autorelease]; | ||
| 72 | + ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease]; | ||
| 73 | + [request setDefaultResponseEncoding:NSWindowsCP1251StringEncoding]; | ||
| 74 | + [request start]; | ||
| 75 | + BOOL success = [request responseEncoding] == [request defaultResponseEncoding]; | ||
| 76 | + STAssertTrue(success,[NSString stringWithFormat:@"Failed to use the default string encoding"]); | ||
| 77 | +} | ||
| 78 | + | ||
| 56 | - (void)testTimeOut | 79 | - (void)testTimeOut |
| 57 | { | 80 | { |
| 58 | - //Grab data | ||
| 59 | NSURL *url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com"] autorelease]; | 81 | NSURL *url = [[[NSURL alloc] initWithString:@"http://allseeing-i.com"] autorelease]; |
| 60 | ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease]; | 82 | ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease]; |
| 61 | [request setTimeOutSeconds:0.0001]; //It's pretty unlikely we will be able to grab the data this quickly, so the request should timeout | 83 | [request setTimeOutSeconds:0.0001]; //It's pretty unlikely we will be able to grab the data this quickly, so the request should timeout |
-
Please register or login to post a comment