Skip to content

Instantly share code, notes, and snippets.

@jfricker
Created March 22, 2010 00:03
Show Gist options
  • Save jfricker/339667 to your computer and use it in GitHub Desktop.
Save jfricker/339667 to your computer and use it in GitHub Desktop.
/* 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