-
-
Save andriitishchenko/f31e55267039eb0b45e7ed0aee44262b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* example usage */ | |
JFFollowRedirect* follower = [[JFFollowRedirect alloc] init]; | |
[follower addObserver:self forKeyPath:@"redirectStr" options:NSKeyValueObservingOptionNew | |
context:follower]; | |
// follow redirect | |
[follower getRedirectURLStr:urlToFollow]; | |
/ * header */ | |
#import <Foundation/Foundation.h> | |
@interface JFFollowRedirect : NSObject { | |
NSURL *url; | |
// This class handles all errors by setting redirectStr to the originalURLStr | |
NSString *redirectStr; | |
} | |
@property (nonatomic, retain) NSString *redirectStr; | |
// parse the header received from the HEAD request | |
- (void)handleReadFromStream:(CFReadStreamRef)aStream | |
eventType:(CFStreamEventType)eventType; | |
// starts the HEAD request | |
- (void)getRedirectURLStr:(NSString *)originalURLStr; | |
@end | |
/ * implementation */ | |
#import "JFFollowRedirect.h" | |
#import <CFNetwork/CFNetwork.h> | |
void JFReadStreamCallBack | |
( | |
CFReadStreamRef aStream, | |
CFStreamEventType eventType, | |
void* inClientInfo | |
) | |
{ | |
JFFollowRedirect *follower = (JFFollowRedirect *)inClientInfo; | |
[follower handleReadFromStream:aStream eventType:eventType]; | |
} | |
@implementation JFFollowRedirect | |
@synthesize redirectStr; | |
- (id)init { | |
if (self = [super init]) { | |
url = nil; | |
} | |
return self; | |
} | |
- (void)dealloc { | |
[super dealloc]; | |
} | |
- (void)handleReadFromStream:(CFReadStreamRef)stream | |
eventType:(CFStreamEventType)eventType { | |
if (eventType == kCFStreamEventEndEncountered) { | |
CFHTTPMessageRef myResponse = (CFHTTPMessageRef)CFReadStreamCopyProperty(stream, kCFStreamPropertyHTTPResponseHeader); | |
CFStringRef header = CFHTTPMessageCopyHeaderFieldValue(myResponse, CFSTR("Location")); | |
if (header == nil) { | |
NSLog(@" *** no Location: header found"); | |
self.redirectStr = [url absoluteString]; | |
} else { | |
//NSLog(@"Location header found %@", header); | |
self.redirectStr = [NSString stringWithFormat:@"%@", header]; | |
CFRelease(header); | |
} | |
CFRelease(myResponse); | |
CFReadStreamUnscheduleFromRunLoop(stream, CFRunLoopGetCurrent(), | |
kCFRunLoopCommonModes); | |
} | |
CFReadStreamClose(stream); | |
CFRelease(stream); | |
} | |
- (void)getRedirectURLStr:(NSString *)originalURLStr { | |
url = [NSURL URLWithString:originalURLStr]; | |
if (url == nil) { | |
self.redirectStr = originalURLStr; | |
return; | |
} | |
// | |
// Create the GET request | |
// | |
CFHTTPMessageRef message= CFHTTPMessageCreateRequest(NULL, (CFStringRef)@"HEAD", (CFURLRef)url, kCFHTTPVersion1_1); | |
CFReadStreamRef stream = CFReadStreamCreateForHTTPRequest(NULL, message); | |
CFRelease(message); | |
// | |
// Enable stream redirection | |
// | |
if (CFReadStreamSetProperty( | |
stream, | |
kCFStreamPropertyHTTPShouldAutoredirect, | |
kCFBooleanFalse) == false) | |
{ | |
self.redirectStr = originalURLStr; | |
CFReadStreamClose(stream); | |
CFRelease(stream); | |
NSLog(@"error kCFStreamPropertyHTTPShouldAutoredirect"); | |
return ; | |
} | |
if (!CFReadStreamOpen(stream)) { // error | |
self.redirectStr = originalURLStr; | |
CFReadStreamClose(stream); | |
CFRelease(stream); | |
NSLog(@"CFReadStreamOpen failed!"); | |
return; | |
} | |
// | |
// Set our callback function to receive the data | |
// | |
CFStreamClientContext context = {0, self, NULL, NULL, NULL}; | |
CFReadStreamSetClient( | |
stream, | |
kCFStreamEventHasBytesAvailable | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered, | |
JFReadStreamCallBack, | |
&context); | |
CFReadStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment