Skip to content

Instantly share code, notes, and snippets.

@gtasko
Last active January 22, 2016 01:22
Show Gist options
  • Save gtasko/8822394 to your computer and use it in GitHub Desktop.
Save gtasko/8822394 to your computer and use it in GitHub Desktop.
NSURLProtocol implementation to intercept HTTP networking and continue with original call.
//
// SLKURLProtocol.m
// InterceptionHttp
//
// Created by G.Tas on 1/14/14.
// Copyright (c) 2014. All rights reserved.
//
#import "SLKURLProtocol.h"
#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#define WORKAROUND_MUTABLE_COPY_LEAK 1
#if WORKAROUND_MUTABLE_COPY_LEAK
// required to workaround http://openradar.appspot.com/11596316
@interface NSURLRequest(MutableCopyWorkaround)
- (id) mutableCopyWorkaround;
@end
#endif
@interface SLKURLProtocol ()
@property (nonatomic, readwrite, strong) NSURLConnection* connection;
@end
static NSString* SLKInterceptionURLHeader = @"X-SLKIntercepted";
@implementation SLKURLProtocol
+ (NSURLRequest*) canonicalRequestForRequest:(NSURLRequest *)request
{
return request;
}
+ (BOOL) canInitWithRequest:(NSURLRequest *)request
{
// only handle http requests we haven't marked with our header.
if ([[[request URL] scheme] isEqualToString:@"http"] &&
([request valueForHTTPHeaderField:SLKInterceptionURLHeader] == nil))
{
return YES;
}
return NO;
}
- (void) startLoading
{
// dispatch_async(kBgQueue,
// ^{
NSString* dataString = [NSString stringWithUTF8String:[self.request.HTTPBody bytes]];
NSUInteger length = [self.request.HTTPBody length];
NSData* data = [NSData dataWithBytes:[self.request.HTTPBody bytes] length:length];
NSLog(@"Intercept Request startLoading");
NSURLRequest* request = self.request;
NSLog(@"URL: %@", request.URL);
NSLog(@"HTTP Method: %@", request.HTTPMethod);
NSLog(@"Data: %@", dataString);
NSMutableURLRequest *connectionRequest =
#if WORKAROUND_MUTABLE_COPY_LEAK
[[self request] mutableCopyWorkaround];
#else
[[self request] mutableCopy];
#endif
[connectionRequest setValue:@"" forHTTPHeaderField:SLKInterceptionURLHeader];
NSURLConnection *connection = [NSURLConnection connectionWithRequest:connectionRequest
delegate:self];
[self setConnection:connection];
[[self client] URLProtocol:self didReceiveResponse:[[NSURLResponse alloc] init] cacheStoragePolicy:NSURLCacheStorageNotAllowed];
[[self client] URLProtocol:self didLoadData:data];
[[self client] URLProtocolDidFinishLoading:self];
// });
}
- (void) stopLoading
{
// dispatch_async(kBgQueue,
// ^{
[self.connection cancel];
NSLog(@"Intercept Request stopLoading");
// });
}
@end
#if WORKAROUND_MUTABLE_COPY_LEAK
@implementation NSURLRequest(MutableCopyWorkaround)
- (id) mutableCopyWorkaround {
NSMutableURLRequest *mutableURLRequest = [[NSMutableURLRequest alloc] initWithURL:[self URL]
cachePolicy:[self cachePolicy]
timeoutInterval:[self timeoutInterval]];
[mutableURLRequest setAllHTTPHeaderFields:[self allHTTPHeaderFields]];
return mutableURLRequest;
}
@end
#endif
@gtasko
Copy link
Author

gtasko commented Feb 6, 2014

With "intercept" I mean, examine the request and let the original caller continue with the operation, so, I want to get info about the request using NSURLProtocol and then AFNetworking continue normally the operation.

Will try with copying and pasting the whole RNCachingURLProtocol. I don't actually need caching, I will keep the info to a file but I want the request of the original caller to continue.

@yaominator
Copy link

In theory , you can just modify RNCachingURLProtocol for your purpose. You can just remove the logic for caching. I am working on a very similar project , but I am not allowed to open source it without permission. I can tell you that the modification of RNCachingURLProtocol works just fine for me in GET/PUT/POST and so on. It also works for AFNetworking and NSURLConnection

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment