diff --git a/MSDKDns.xcodeproj/project.pbxproj b/MSDKDns.xcodeproj/project.pbxproj index ead27de..189eac8 100644 --- a/MSDKDns.xcodeproj/project.pbxproj +++ b/MSDKDns.xcodeproj/project.pbxproj @@ -1047,7 +1047,7 @@ LINK_WITH_STANDARD_LIBRARIES = NO; MACH_O_TYPE = mh_object; MACOSX_DEPLOYMENT_TARGET = ""; - MARKETING_VERSION = 1.10.1; + MARKETING_VERSION = 1.10.2; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = "-fembed-bitcode"; OTHER_LDFLAGS = ( @@ -1094,7 +1094,7 @@ LINK_WITH_STANDARD_LIBRARIES = NO; MACH_O_TYPE = mh_object; MACOSX_DEPLOYMENT_TARGET = ""; - MARKETING_VERSION = 1.10.1; + MARKETING_VERSION = 1.10.2; OTHER_CFLAGS = "-fembed-bitcode"; OTHER_LDFLAGS = ( "-ObjC", @@ -1137,7 +1137,7 @@ LINK_WITH_STANDARD_LIBRARIES = NO; MACH_O_TYPE = mh_object; MACOSX_DEPLOYMENT_TARGET = ""; - MARKETING_VERSION = 1.10.1; + MARKETING_VERSION = 1.10.2; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = "-fembed-bitcode"; OTHER_LDFLAGS = ( @@ -1179,7 +1179,7 @@ LINK_WITH_STANDARD_LIBRARIES = NO; MACH_O_TYPE = mh_object; MACOSX_DEPLOYMENT_TARGET = ""; - MARKETING_VERSION = 1.10.1; + MARKETING_VERSION = 1.10.2; OTHER_CFLAGS = "-fembed-bitcode"; OTHER_LDFLAGS = ( "-ObjC", @@ -1228,7 +1228,7 @@ LINK_WITH_STANDARD_LIBRARIES = NO; MACH_O_TYPE = mh_object; MACOSX_DEPLOYMENT_TARGET = ""; - MARKETING_VERSION = 1.10.1; + MARKETING_VERSION = 1.10.2; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = "-fembed-bitcode"; OTHER_LDFLAGS = ( @@ -1276,7 +1276,7 @@ LINK_WITH_STANDARD_LIBRARIES = NO; MACH_O_TYPE = mh_object; MACOSX_DEPLOYMENT_TARGET = ""; - MARKETING_VERSION = 1.10.1; + MARKETING_VERSION = 1.10.2; OTHER_CFLAGS = "-fembed-bitcode"; OTHER_LDFLAGS = ( "-ObjC", @@ -1314,7 +1314,7 @@ LINK_WITH_STANDARD_LIBRARIES = NO; MACH_O_TYPE = mh_object; MACOSX_DEPLOYMENT_TARGET = ""; - MARKETING_VERSION = 1.10.1; + MARKETING_VERSION = 1.10.2; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = "-fembed-bitcode"; OTHER_LDFLAGS = ( @@ -1354,7 +1354,7 @@ LINK_WITH_STANDARD_LIBRARIES = NO; MACH_O_TYPE = mh_object; MACOSX_DEPLOYMENT_TARGET = ""; - MARKETING_VERSION = 1.10.1; + MARKETING_VERSION = 1.10.2; OTHER_CFLAGS = "-fembed-bitcode"; OTHER_LDFLAGS = ( "-ObjC", diff --git a/MSDKDns/MSDKDns.h b/MSDKDns/MSDKDns.h index 4a8147f..19feb7a 100644 --- a/MSDKDns/MSDKDns.h +++ b/MSDKDns/MSDKDns.h @@ -5,7 +5,7 @@ #ifndef __MSDKDns_H__ #define __MSDKDns_H__ -#define MSDKDns_Version @"1.10.1" +#define MSDKDns_Version @"1.10.2" #import diff --git a/MSDKDns/MSDKDnsHttpMessageTools.m b/MSDKDns/MSDKDnsHttpMessageTools.m index 03755b7..168ac29 100644 --- a/MSDKDns/MSDKDnsHttpMessageTools.m +++ b/MSDKDns/MSDKDnsHttpMessageTools.m @@ -7,6 +7,7 @@ #import "MSDKDnsLog.h" #import "MSDKDnsParamsManager.h" #import "MSDKDnsManager.h" +#import #import #import "MSDKDns.h" @@ -32,13 +33,19 @@ @implementation MSDKDnsHttpMessageTools */ + (BOOL)canInitWithRequest:(NSURLRequest *)request { + if([[request.URL absoluteString] isEqual:@"about:blank"]) { + return NO; + } + /* 防止无限循环,因为一个请求在被拦截处理过程中,也会发起一个请求,这样又会走到这里,如果不进行处理,就会造成无限循环 */ if ([NSURLProtocol propertyForKey:protocolKey inRequest:request]) { return NO; } NSString * url = request.URL.absoluteString; - NSString * domain = [request.allHTTPHeaderFields objectForKey:@"host"]; - + NSURL *URL = request.URL; + NSString * originHost = [request.allHTTPHeaderFields objectForKey:@"host"]; + NSString * domain = request.URL.host; + NSArray * hijackDomainArray = [[[MSDKDnsParamsManager shareInstance] hijackDomainArray] copy]; NSArray * noHijackDomainArray = [[[MSDKDnsParamsManager shareInstance] noHijackDomainArray] copy]; @@ -54,12 +61,48 @@ + (BOOL)canInitWithRequest:(NSURLRequest *)request { return NO; } } - // 如果url以https开头,且不为httpdns服务器ip,则进行拦截处理,否则不处理 - NSString *dnsIp = [[MSDKDnsManager shareInstance] currentDnsServer]; - if ([url hasPrefix:@"https"] && ![url containsString:dnsIp]) { - return YES; + // 如果为ip,则不拦截处理 + if ([self isIPV4:domain]){ + return NO; } - return NO; + if ([self isIPV6:domain]){ + return NO; + } + return YES; +} + ++ (BOOL)isIPV4:(NSString *)ipSting { + BOOL isIPV4 = YES; + + if (ipSting) { + const char *utf8 = [ipSting UTF8String]; + int success = 0; + struct in_addr dst; + success = inet_pton(AF_INET, utf8, &dst); + if (success != 1) { + isIPV4 = NO; + } + } else { + isIPV4 = NO; + } + return isIPV4; +} + ++ (BOOL)isIPV6:(NSString *)ipSting { + BOOL isIPV6 = YES; + + if (ipSting) { + const char *utf8 = [ipSting UTF8String]; + int success = 0; + struct in6_addr dst6; + success = inet_pton(AF_INET6, utf8, &dst6); + if (success != 1) { + isIPV6 = NO; + } + } else { + isIPV6 = NO; + } + return isIPV6; } /** @@ -76,18 +119,84 @@ - (void)startLoading { NSMutableURLRequest *request = [self.request mutableCopy]; // 表示该请求已经被处理,防止无限循环 [NSURLProtocol setProperty:@(YES) forKey:protocolKey inRequest:request]; - self.curRequest = request; + self.curRequest = [self applyHttpDnsIpDirectConnect:request]; [self startRequest]; } +- (NSString *)cookieForURL:(NSURL *)URL { + NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; + NSMutableArray *cookieList = [NSMutableArray array]; + for (NSHTTPCookie *cookie in [cookieStorage cookies]) { + if (![self p_checkCookie:cookie URL:URL]) { + continue; + } + [cookieList addObject:cookie]; + } + + if (cookieList.count > 0) { + NSDictionary *cookieDic = [NSHTTPCookie requestHeaderFieldsWithCookies:cookieList]; + if ([cookieDic objectForKey:@"Cookie"]) { + return cookieDic[@"Cookie"]; + } + } + return nil; +} + + +- (BOOL)p_checkCookie:(NSHTTPCookie *)cookie URL:(NSURL *)URL { + if (cookie.domain.length <= 0 || URL.host.length <= 0) { + return NO; + } + if ([URL.host containsString:cookie.domain]) { + return YES; + } + return NO; +} + +- (NSURLRequest*)applyHttpDnsIpDirectConnect:(NSURLRequest*)request { + NSURL* originUrl = request.URL; + NSString* originHost = originUrl.host; + NSString *cookie = [self cookieForURL:originUrl]; + NSURL* newUrl = [self getIpAndReplace:[originUrl absoluteString]]; + + NSMutableURLRequest* mutableRequest = [request copy]; + mutableRequest.URL = newUrl; + [mutableRequest setValue:originHost forHTTPHeaderField:@"Host"]; + [mutableRequest setValue:cookie forHTTPHeaderField:@"Cookie"]; + + return [mutableRequest copy]; +} + +- (NSURL*)getIpAndReplace:(NSString*)urlString { + NSURL* url = [NSURL URLWithString:urlString]; + NSString* originHost = url.host; + + NSTimeInterval start = [[NSDate date] timeIntervalSince1970]; + NSArray* result = [[MSDKDns sharedInstance] WGGetHostByName:url.host]; + NSString* ip = nil; + if (result && result.count > 1) { + if (![result[0] isEqualToString:@"0"]) { + ip = result[0]; + } else { + ip = result[1]; + } + } + // 通过HTTPDNS获取IP成功,进行URL替换和HOST头设置 + if (originHost.length > 0 && ip.length > 0) { + NSString* originUrlStringafterdispatch = [url absoluteString]; + NSRange hostRange = [originUrlStringafterdispatch rangeOfString:url.host]; + NSString* urlString = [originUrlStringafterdispatch stringByReplacingCharactersInRange:hostRange withString:ip]; + url = [NSURL URLWithString:urlString]; + } + return url; +} + /** * 取消请求 */ - (void)stopLoading { if (_inputStream.streamStatus == NSStreamStatusOpen) { - [_inputStream removeFromRunLoop:_curRunLoop forMode:NSRunLoopCommonModes]; - [_inputStream setDelegate:nil]; - [_inputStream close]; + [self closeStream:_inputStream]; } [self.client URLProtocol:self didFailWithError:[[NSError alloc] initWithDomain:@"stop loading" code:-1 userInfo:nil]]; } @@ -98,34 +207,31 @@ - (void)stopLoading { - (void)startRequest { // 原请求的header信息 NSDictionary *headFields = _curRequest.allHTTPHeaderFields; - // 添加http post请求所附带的数据 - CFStringRef requestBody = CFSTR(""); - CFDataRef bodyData = CFStringCreateExternalRepresentation(kCFAllocatorDefault, requestBody, kCFStringEncodingUTF8, 0); - if (_curRequest.HTTPBody) { - bodyData = (__bridge_retained CFDataRef) _curRequest.HTTPBody; - } else if (headFields[@"originalBody"]) { - // 使用NSURLSession发POST请求时,将原始HTTPBody从header中取出 - bodyData = (__bridge_retained CFDataRef) [headFields[@"originalBody"] dataUsingEncoding:NSUTF8StringEncoding]; - } - CFStringRef url = (__bridge CFStringRef) [_curRequest.URL absoluteString]; CFURLRef requestURL = CFURLCreateWithString(kCFAllocatorDefault, url, NULL); - // 原请求所使用的方法,GET或POST CFStringRef requestMethod = (__bridge_retained CFStringRef) _curRequest.HTTPMethod; - // 根据请求的url、方法、版本创建CFHTTPMessageRef对象 CFHTTPMessageRef cfrequest = CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, requestURL, kCFHTTPVersion1_1); - CFHTTPMessageSetBody(cfrequest, bodyData); + // 添加http post请求所附带的数据 + CFStringRef requestBody = CFSTR(""); + CFDataRef bodyData = CFStringCreateExternalRepresentation(kCFAllocatorDefault, requestBody, kCFStringEncodingUTF8, 0); + if (_curRequest.HTTPBody) { + bodyData = (__bridge_retained CFDataRef) _curRequest.HTTPBody; + } else if(_curRequest.HTTPBodyStream) { + NSData *data = [self dataWithInputStream:_curRequest.HTTPBodyStream]; + CFDataRef body = (__bridge_retained CFDataRef) data; + CFHTTPMessageSetBody(cfrequest, body); + CFRelease(body); + } else { + CFHTTPMessageSetBody(cfrequest, bodyData); + } // copy原请求的header信息 - for (NSString *header in headFields) { - if (![header isEqualToString:@"originalBody"]) { - // 不包含POST请求时存放在header的body信息 - CFStringRef requestHeader = (__bridge CFStringRef) header; - CFStringRef requestHeaderValue = (__bridge CFStringRef) [headFields valueForKey:header]; - CFHTTPMessageSetHeaderFieldValue(cfrequest, requestHeader, requestHeaderValue); - } + for (NSString* header in headFields) { + CFStringRef requestHeader = (__bridge CFStringRef) header; + CFStringRef requestHeaderValue = (__bridge CFStringRef) [headFields valueForKey:header]; + CFHTTPMessageSetHeaderFieldValue(cfrequest, requestHeader, requestHeaderValue); } // 创建CFHTTPMessage对象的输入流 @@ -137,115 +243,46 @@ - (void)startRequest { if (!host) { host = _curRequest.URL.host; } + [_inputStream setProperty:NSStreamSocketSecurityLevelNegotiatedSSL forKey:NSStreamSocketSecurityLevelKey]; NSDictionary *sslProperties = [[NSDictionary alloc] initWithObjectsAndKeys: host, (__bridge id) kCFStreamSSLPeerName, nil]; [_inputStream setProperty:sslProperties forKey:(__bridge_transfer NSString *) kCFStreamPropertySSLSettings]; [_inputStream setDelegate:self]; - if (!_curRunLoop) + if (!_curRunLoop) { // 保存当前线程的runloop,这对于重定向的请求很关键 self.curRunLoop = [NSRunLoop currentRunLoop]; + } // 将请求放入当前runloop的事件队列 [_inputStream scheduleInRunLoop:_curRunLoop forMode:NSRunLoopCommonModes]; [_inputStream open]; CFRelease(cfrequest); CFRelease(requestURL); - // ARC模式下,需注释此句 - // CFRelease(url); cfrequest = NULL; CFRelease(bodyData); CFRelease(requestBody); CFRelease(requestMethod); } -/** - * 根据服务器返回的响应内容进行不同的处理 - */ -- (void)handleResponse { - // 获取响应头部信息 - CFReadStreamRef readStream = (__bridge_retained CFReadStreamRef) _inputStream; - CFHTTPMessageRef message = (CFHTTPMessageRef) CFReadStreamCopyProperty(readStream, kCFStreamPropertyHTTPResponseHeader); - if (CFHTTPMessageIsHeaderComplete(message)) { - // 确保response头部信息完整 - NSDictionary *headDict = (__bridge NSDictionary *) (CFHTTPMessageCopyAllHeaderFields(message)); - - // 获取响应头部的状态码 - CFIndex statusCode = CFHTTPMessageGetResponseStatusCode(message); - - // 把当前请求关闭 - [_inputStream removeFromRunLoop:_curRunLoop forMode:NSRunLoopCommonModes]; - [_inputStream setDelegate:nil]; - [_inputStream close]; - - if (statusCode >= 200 && statusCode < 300) { - // 返回码为2xx,直接通知client - [self.client URLProtocolDidFinishLoading:self]; - } else if (statusCode >= 300 && statusCode < 400) { - // 返回码为3xx,需要重定向请求,继续访问重定向页面 - NSString *location = headDict[@"Location"]; - if (!location) { - location = headDict[@"location"]; - } - if (!location) { - // 直接返回响应信息给client - if (statusCode == 304) { - NSURL* url = (__bridge NSURL *) CFHTTPMessageCopyRequestURL(message); - NSString* httpVersion = (__bridge NSString *) CFHTTPMessageCopyVersion(message); - NSHTTPURLResponse* response = [[NSHTTPURLResponse alloc] initWithURL:url statusCode:statusCode - HTTPVersion:httpVersion headerFields:headDict]; - [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed]; - } - [self.client URLProtocolDidFinishLoading:self]; - return; - } - NSURL *url = [[NSURL alloc] initWithString:location]; - _curRequest.URL = url; - if ([[_curRequest.HTTPMethod lowercaseString] isEqualToString:@"post"]) { - // 根据RFC文档,当重定向请求为POST请求时,要将其转换为GET请求 - _curRequest.HTTPMethod = @"GET"; - _curRequest.HTTPBody = nil; - } - - /***********重定向通知client处理或内部处理*************/ - // client处理 - // NSURLResponse* response = [[NSURLResponse alloc] initWithURL:curRequest.URL MIMEType:headDict[@"Content-Type"] expectedContentLength:[headDict[@"Content-Length"] integerValue] textEncodingName:@"UTF8"]; - // [self.client URLProtocol:self wasRedirectedToRequest:curRequest redirectResponse:response]; - - // 内部处理,将url中的host通过HTTPDNS转换为IP,不能在startLoading线程中进行同步网络请求,会被阻塞 - __block NSArray* result; - [[MSDKDns sharedInstance] WGGetHostByNameAsync:url.host returnIps:^(NSArray *ipsArray) { - result = ipsArray; - }]; - NSString *ip = nil; - if (result && result.count > 1) { - if (![result[1] isEqualToString:@"0"]) { - ip = result[1]; - } else { - ip = result[0]; - } - } - if (ip && ip.length > 0 && ![ip isEqualToString:@"0"]) { - MSDKDNSLOG(@"Get IP from HTTPDNS Successfully!"); - NSRange hostFirstRange = [location rangeOfString:url.host]; - if (NSNotFound != hostFirstRange.location) { - NSString *urlString = [location stringByReplacingCharactersInRange:hostFirstRange withString:ip]; - _curRequest.URL = [NSURL URLWithString:urlString]; - [_curRequest setValue:url.host forHTTPHeaderField:@"host"]; - } - } - [self startRequest]; - } else { - // 其他情况,直接返回响应信息给client - [self.client URLProtocolDidFinishLoading:self]; - } - } else { - // 头部信息不完整,关闭inputstream,通知client - [_inputStream removeFromRunLoop:_curRunLoop forMode:NSRunLoopCommonModes]; - [_inputStream setDelegate:nil]; - [_inputStream close]; - [self.client URLProtocolDidFinishLoading:self]; +-(NSData*)dataWithInputStream:(NSInputStream*)stream { + NSMutableData *data = [NSMutableData data]; + [stream open]; + NSInteger result; + uint8_t buffer[1024]; + + while ((result = [stream read:buffer maxLength:1024]) != 0) { + if (result > 0) { + // buffer contains result bytes of data to be handled + [data appendBytes:buffer length:result]; + } else if (result < 0) { + // The stream had an error. You can get an NSError object using [iStream streamError] + data = nil; + break; } + } + [stream close]; + return data; } #pragma mark - NSStreamDelegate @@ -266,6 +303,7 @@ - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { if (!alreadyAdded || ![alreadyAdded boolValue]) { objc_setAssociatedObject(aStream, (__bridge const void *)(kAnchorAlreadyAdded), [NSNumber numberWithBool:YES], OBJC_ASSOCIATION_COPY); // 通知client已收到response,只通知一次 + NSDictionary *headDict = (__bridge NSDictionary *) (CFHTTPMessageCopyAllHeaderFields(message)); CFStringRef httpVersion = CFHTTPMessageCopyVersion(message); // 获取响应头部的状态码 @@ -273,6 +311,7 @@ - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:_curRequest.URL statusCode:statusCode HTTPVersion:(__bridge NSString *) httpVersion headerFields:headDict]; + [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed]; // 验证证书 @@ -290,39 +329,42 @@ - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { */ SecTrustSetPolicies(trust, (__bridge CFArrayRef) policies); if (SecTrustEvaluate(trust, &res) != errSecSuccess) { - [aStream removeFromRunLoop:_curRunLoop forMode:NSRunLoopCommonModes]; - [aStream setDelegate:nil]; - [aStream close]; + [self closeStream:aStream]; [self.client URLProtocol:self didFailWithError:[[NSError alloc] initWithDomain:@"can not evaluate the server trust" code:-1 userInfo:nil]]; + return; } if (res != kSecTrustResultProceed && res != kSecTrustResultUnspecified) { /* 证书验证不通过,关闭input stream */ - [aStream removeFromRunLoop:_curRunLoop forMode:NSRunLoopCommonModes]; - [aStream setDelegate:nil]; - [aStream close]; + [self closeStream:aStream]; [self.client URLProtocol:self didFailWithError:[[NSError alloc] initWithDomain:@"fail to evaluate the server trust" code:-1 userInfo:nil]]; - } else { - // 证书通过,返回数据 - if (![inputstream getBuffer:&buf length:&length]) { - NSInteger amount = [inputstream read:buffer maxLength:sizeof(buffer)]; - buf = buffer; - length = amount; - } - if ((NSInteger)length >= 0) { - NSData *data = [[NSData alloc] initWithBytes:buf length:length]; - [self.client URLProtocol:self didLoadData:data]; + // 证书校验通过 + if (statusCode >= 300 && statusCode < 400) { + // 处理重定向错误码 + [self closeStream:aStream]; + [self handleRedirect:message]; } else { - NSError *error = inputstream.streamError; - if (!error) { - error = [[NSError alloc] initWithDomain:@"inputstream length is invalid" - code:-2 - userInfo:nil]; + // 返回成功收到的数据 + if (![inputstream getBuffer:&buf length:&length]) { + NSInteger amount = [inputstream read:buffer maxLength:sizeof(buffer)]; + buf = buffer; + length = amount; + } + if ((NSInteger)length >= 0) { + NSData *data = [[NSData alloc] initWithBytes:buf length:length]; + [self.client URLProtocol:self didLoadData:data]; + } else { + NSError *error = inputstream.streamError; + if (!error) { + error = [[NSError alloc] initWithDomain:@"inputstream length is invalid" + code:-2 + userInfo:nil]; + } + [aStream removeFromRunLoop:_curRunLoop forMode:NSRunLoopCommonModes]; + [aStream setDelegate:nil]; + [aStream close]; + [self.client URLProtocol:self didFailWithError:error]; } - [aStream removeFromRunLoop:_curRunLoop forMode:NSRunLoopCommonModes]; - [aStream setDelegate:nil]; - [aStream close]; - [self.client URLProtocol:self didFailWithError:error]; } } } else { @@ -348,16 +390,49 @@ - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { [self.client URLProtocol:self didFailWithError:error]; } } + CFRelease((CFReadStreamRef)inputstream); + CFRelease(message); } } else if (eventCode == NSStreamEventErrorOccurred) { - [aStream removeFromRunLoop:_curRunLoop forMode:NSRunLoopCommonModes]; - [aStream setDelegate:nil]; - [aStream close]; + [self closeStream:aStream]; // 通知client发生错误了 - [self.client URLProtocol:self didFailWithError:[aStream streamError]]; + [self.client URLProtocol:self didFailWithError: + [[NSError alloc] initWithDomain:@"NSStreamEventErrorOccurred" code:-1 userInfo:nil]]; } else if (eventCode == NSStreamEventEndEncountered) { - [self handleResponse]; + [self closeStream:_inputStream]; + [self.client URLProtocolDidFinishLoading:self]; } } +- (void)closeStream:(NSStream*)stream { + [stream removeFromRunLoop:_curRunLoop forMode:NSRunLoopCommonModes]; + [stream setDelegate:nil]; + [stream close]; +} + +- (void)handleRedirect:(CFHTTPMessageRef)messageRef { + // 响应头 + CFDictionaryRef headerFieldsRef = CFHTTPMessageCopyAllHeaderFields(messageRef); + NSDictionary *headDict = (__bridge_transfer NSDictionary *)headerFieldsRef; + [self redirect:headDict]; +} + +- (void)redirect:(NSDictionary *)headDict { + // 重定向时如果有cookie需求的话,注意处理 + NSString *location = headDict[@"Location"]; + if (!location) + location = headDict[@"location"]; + NSURL *url = [[NSURL alloc] initWithString:location]; + _curRequest.URL = url; + if ([[_curRequest.HTTPMethod lowercaseString] isEqualToString:@"post"]) { + // 根据RFC文档,当重定向请求为POST请求时,要将其转换为GET请求 + _curRequest.HTTPMethod = @"GET"; + _curRequest.HTTPBody = nil; + } + + _curRequest.URL = [self getIpAndReplace:[url absoluteString]]; + [_curRequest setValue:url.host forHTTPHeaderField:@"host"]; + [self startRequest]; +} + @end