Ben Copsey

Always attempt a persistent connection unless http1.0 or !shouldAttemptPersisten…

…tConnection or we get a connection:close header
Stop relying on receiving a keep-alive header for persistent connections
@@ -21,7 +21,7 @@ @@ -21,7 +21,7 @@
21 #import "ASIInputStream.h" 21 #import "ASIInputStream.h"
22 22
23 // Automatically set on build 23 // Automatically set on build
24 -NSString *ASIHTTPRequestVersion = @"v1.5-46 2010-02-24"; 24 +NSString *ASIHTTPRequestVersion = @"v1.5-47 2010-02-24";
25 25
26 NSString* const NetworkRequestErrorDomain = @"ASIHTTPRequestErrorDomain"; 26 NSString* const NetworkRequestErrorDomain = @"ASIHTTPRequestErrorDomain";
27 27
@@ -1619,11 +1619,11 @@ static BOOL isiPhoneOS2; @@ -1619,11 +1619,11 @@ static BOOL isiPhoneOS2;
1619 { 1619 {
1620 [self setAuthenticationNeeded:ASINoAuthenticationNeededYet]; 1620 [self setAuthenticationNeeded:ASINoAuthenticationNeededYet];
1621 1621
1622 - CFHTTPMessageRef headers = (CFHTTPMessageRef)CFReadStreamCopyProperty((CFReadStreamRef)[self readStream], kCFStreamPropertyHTTPResponseHeader); 1622 + CFHTTPMessageRef message = (CFHTTPMessageRef)CFReadStreamCopyProperty((CFReadStreamRef)[self readStream], kCFStreamPropertyHTTPResponseHeader);
1623 - if (!headers) { 1623 + if (!message) {
1624 return; 1624 return;
1625 } 1625 }
1626 - if (CFHTTPMessageIsHeaderComplete(headers)) { 1626 + if (CFHTTPMessageIsHeaderComplete(message)) {
1627 1627
1628 #if DEBUG_REQUEST_STATUS 1628 #if DEBUG_REQUEST_STATUS
1629 if ([self totalBytesSent] == [self postLength]) { 1629 if ([self totalBytesSent] == [self postLength]) {
@@ -1631,12 +1631,12 @@ static BOOL isiPhoneOS2; @@ -1631,12 +1631,12 @@ static BOOL isiPhoneOS2;
1631 } 1631 }
1632 #endif 1632 #endif
1633 1633
1634 - CFDictionaryRef headerFields = CFHTTPMessageCopyAllHeaderFields(headers); 1634 + CFDictionaryRef headerFields = CFHTTPMessageCopyAllHeaderFields(message);
1635 [self setResponseHeaders:(NSDictionary *)headerFields]; 1635 [self setResponseHeaders:(NSDictionary *)headerFields];
1636 1636
1637 CFRelease(headerFields); 1637 CFRelease(headerFields);
1638 - [self setResponseStatusCode:CFHTTPMessageGetResponseStatusCode(headers)]; 1638 + [self setResponseStatusCode:CFHTTPMessageGetResponseStatusCode(message)];
1639 - [self setResponseStatusMessage:[(NSString *)CFHTTPMessageCopyResponseStatusLine(headers) autorelease]]; 1639 + [self setResponseStatusMessage:[(NSString *)CFHTTPMessageCopyResponseStatusLine(message) autorelease]];
1640 1640
1641 // Is the server response a challenge for credentials? 1641 // Is the server response a challenge for credentials?
1642 if ([self responseStatusCode] == 401) { 1642 if ([self responseStatusCode] == 401) {
@@ -1773,20 +1773,35 @@ static BOOL isiPhoneOS2; @@ -1773,20 +1773,35 @@ static BOOL isiPhoneOS2;
1773 } 1773 }
1774 1774
1775 // Handle connection persistence 1775 // Handle connection persistence
1776 - if ([self shouldAttemptPersistentConnection] && [[[self responseHeaders] objectForKey:@"Connection"] isEqualToString:@"Keep-Alive"]) { 1776 + NSString *httpVersion = [(NSString *)CFHTTPMessageCopyVersion(message) autorelease];
1777 - NSString *keepAliveHeader = [[self responseHeaders] objectForKey:@"Keep-Alive"]; 1777 +
1778 - if (keepAliveHeader) { 1778 + // We won't re-use this connection if this request is set to use HTTP 1.0, or the server is talking in HTTP 1.0, or persistent connections are turned off for this request
1779 - int timeout = 0; 1779 + if (![self useHTTPVersionOne] && [self shouldAttemptPersistentConnection] && ![httpVersion isEqualToString:(NSString *)kCFHTTPVersion1_0]) {
1780 - int max = 0; 1780 +
1781 - NSScanner *scanner = [NSScanner scannerWithString:keepAliveHeader]; 1781 + // See if server explicitly told us to close the connection
1782 - [scanner scanString:@"timeout=" intoString:NULL]; 1782 + if (![[[[self responseHeaders] objectForKey:@"Connection"] lowercaseString] isEqualToString:@"close"]) {
1783 - [scanner scanInt:&timeout]; 1783 +
1784 - [scanner scanUpToString:@"max=" intoString:NULL]; 1784 + NSString *keepAliveHeader = [[self responseHeaders] objectForKey:@"Keep-Alive"];
1785 - [scanner scanString:@"max=" intoString:NULL]; 1785 +
1786 - [scanner scanInt:&max]; 1786 + // If we got a keep alive header, we'll reuse the connection for as long as the server tells us
1787 - if (max > 5) { 1787 + if (keepAliveHeader) {
  1788 + int timeout = 0;
  1789 + int max = 0;
  1790 + NSScanner *scanner = [NSScanner scannerWithString:keepAliveHeader];
  1791 + [scanner scanString:@"timeout=" intoString:NULL];
  1792 + [scanner scanInt:&timeout];
  1793 + [scanner scanUpToString:@"max=" intoString:NULL];
  1794 + [scanner scanString:@"max=" intoString:NULL];
  1795 + [scanner scanInt:&max];
  1796 + if (max > 5) {
  1797 + [self setCanUsePersistentConnection:YES];
  1798 + closeStreamTime = timeout;
  1799 + }
  1800 +
  1801 + // Otherwise, we'll assume we can keep this connection open
  1802 + } else {
1788 [self setCanUsePersistentConnection:YES]; 1803 [self setCanUsePersistentConnection:YES];
1789 - closeStreamTime = timeout; 1804 + closeStreamTime = 60;
1790 } 1805 }
1791 } 1806 }
1792 } 1807 }
@@ -1794,7 +1809,7 @@ static BOOL isiPhoneOS2; @@ -1794,7 +1809,7 @@ static BOOL isiPhoneOS2;
1794 1809
1795 1810
1796 1811
1797 - CFRelease(headers); 1812 + CFRelease(message);
1798 } 1813 }
1799 1814
1800 #pragma mark http authentication 1815 #pragma mark http authentication