Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
marcuswestin committed Jun 6, 2013
2 parents 22c2f4c + cfa2930 commit f25b6dd
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 6 deletions.
@@ -1,6 +1,6 @@
#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>
@interface AppDelegate : UIResponder <UIApplicationDelegate, NSURLConnectionDataDelegate>

@property (strong, nonatomic) UIWindow *window;

Expand Down
6 changes: 6 additions & 0 deletions ExampleWebViewProxyApp/ExampleWebViewProxyApp/AppDelegate.m
Expand Up @@ -72,6 +72,12 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
[WebViewProxy handleRequestsMatching:[NSPredicate predicateWithFormat:@"host MATCHES[cd] '[foo|bar]'"] handler:^(NSURLRequest* req, WVPResponse *res) {
// ...
}];

[WebViewProxy handleRequestsWithHost:@"example.proxy" handler:^(NSURLRequest *req, WVPResponse *res) {
NSString* proxyUrl = [req.URL.absoluteString stringByReplacingOccurrencesOfString:@"example.proxy" withString:@"example.com"];
NSURLRequest* proxyReq = [NSURLRequest requestWithURL:[NSURL URLWithString:proxyUrl]];
[NSURLConnection connectionWithRequest:proxyReq delegate:res];
}];

return YES;
}
Expand Down
Expand Up @@ -6,4 +6,6 @@
<img src="http://intercept_black_and_white/Galaxy.png" />
<img src="https://www.google.com/images/srpr/logo3w.png" />
<img src="https://black_and_white.google.com/images/srpr/logo3w.png" />

<iframe src="http://example.proxy"></iframe>
</body></html>
37 changes: 33 additions & 4 deletions README.md
Expand Up @@ -141,14 +141,21 @@ Examples
[res respondWithError:404 text:@"Not found"];

##### - (void) setHeader:(NSString\*)headerName value:(NSString\*)headerValue;
Set response headers before responding.
Set a response header before responding.

Examples

[res setHeader:@"Content-Type" value:@"image/gif"];
[res setHeader:@"Content-Type" value:@"audio/wav"];
[res setHeader:@"Host" value:@"WebViewProxy"];

##### - (void) setHeaders:(NSDictionary*)headers;
Set multiple response headers before responding.

Examples

[res setHeaders:@{ @"Content-Type":@"image/gif", @"Host":@"WebViewProxy" }];

##### - (void) respondWithData:(NSData\*)data mimeType:(NSString\*)mimeType;

Respond with the given data and mime type (the mime type gets sent as the HTTP header `Content-Type`).
Expand Down Expand Up @@ -184,6 +191,31 @@ Examples
response.cachePolicy = NSURLCacheStorageAllowedInMemoryOnly;
response.cachePolicy = NSURLCacheStorageNotAllowed;

#### Proxy requests to remote servers

There are many ways to proxy remote requests with `WebViewProxy`.

The easiest approach uses `WebViewProxyResponse` as a `NSURLConnection` delegate. This pipes the response through the proxy response:

[WebViewProxy handleRequestsWithHost:@"example.proxy" handler:^(NSURLRequest *req, WVPResponse *res) {
NSString* proxyUrl = [req.URL.absoluteString stringByReplacingOccurrencesOfString:@"example.proxy" withString:@"example.com"];
NSURLRequest* proxyReq = [NSURLRequest requestWithURL:[NSURL URLWithString:proxyUrl]];
[NSURLConnection connectionWithRequest:proxyReq delegate:res];
}];

Another approach which sports more control but reads the entire response into memory:

NSOperationQueue* queue = [[NSOperationQueue alloc] init];
[WebViewProxy handleRequestsWithHost:@"example.proxy" handler:^(NSURLRequest *req, WVPResponse *res) {
NSString* proxyUrl = [req.URL.absoluteString stringByReplacingOccurrencesOfString:@"example.proxy" withString:@"example.com"];
NSURLRequest* proxyReq = [NSURLRequest requestWithURL:[NSURL URLWithString:proxyUrl]];
[NSURLConnection sendAsynchronousRequest:proxyReq queue:queue completionHandler:^(NSURLResponse* proxyRes, NSData* proxyData, NSError* proxyErr) {
if (proxyErr) { return [res respondWithError:203 text:@"Could not reach server"]; }
NSInteger statusCode = [(NSHTTPURLResponse*)proxyRes statusCode];
[res setHeaders:[(NSHTTPURLResponse*)proxyRes allHeaderFields]];
[res respondWithData:proxyData mimeType:proxyRes.MIMEType statusCode:statusCode];
}];
}];

#### Piping response API

Expand All @@ -192,13 +224,10 @@ Pipe an `NSURLResponse` and its data into the `WVPResponse`. This makes it simp
Examples to be written.

##### - (void) pipeResponse:(NSURLResponse\*)response;

Pipe an NSURLResponse into the response.

##### - (void) pipeData:(NSData\*)data;

Pipe data into the response.

##### - (void) pipeEnd;

Finish a piped response.
3 changes: 2 additions & 1 deletion WebViewProxy/WebViewProxy.h
@@ -1,6 +1,6 @@
#import <Foundation/Foundation.h>

@interface WVPResponse : NSObject
@interface WVPResponse : NSObject <NSURLConnectionDataDelegate>
@property (assign,nonatomic) NSURLCacheStoragePolicy cachePolicy;
@property (strong,nonatomic) NSURLRequest* request;
// High level API
Expand All @@ -12,6 +12,7 @@
// Low level API
- (void) respondWithError:(NSInteger)statusCode text:(NSString*)text;
- (void) setHeader:(NSString*)headerName value:(NSString*)headerValue;
- (void) setHeaders:(NSDictionary*)headers;
- (void) respondWithData:(NSData*)data mimeType:(NSString*)mimeType;
- (void) respondWithData:(NSData*)data mimeType:(NSString*)mimeType statusCode:(NSInteger)statusCode;
// Pipe data API
Expand Down
18 changes: 18 additions & 0 deletions WebViewProxy/WebViewProxy.m
Expand Up @@ -80,6 +80,11 @@ - (void)respondWithHTML:(NSString *)html {
- (void)setHeader:(NSString *)headerName value:(NSString *)headerValue {
_headers[headerName] = headerValue;
}
- (void)setHeaders:(NSDictionary *)headers {
for (NSString* headerName in headers) {
[self setHeader:headerName value:headers[headerName]];
}
}
- (void)respondWithData:(NSData *)data mimeType:(NSString *)mimeType {
[self respondWithData:data mimeType:mimeType statusCode:200];
}
Expand Down Expand Up @@ -140,6 +145,19 @@ - (void)pipeEnd {
if (_stopped) { return; }
[_protocol.client URLProtocolDidFinishLoading:_protocol];
}
// NSURLConnectionDataDelegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[self pipeResponse:response];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self pipeData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[self pipeEnd];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[self pipeEnd];
}
@end

// The NSURLProtocol implementation that allows us to intercept requests.
Expand Down

0 comments on commit f25b6dd

Please sign in to comment.