LLWebViewProxy
Web View Proxy
轻松代理 Web 视图请求,无需对 NSURLProtocol 进行任何修改。
支持 iOS 和 OSX。
拦截请求的响应可以同步或异步提供 - 这与 UIWebViewDelegate
方法 -(NSCachedURLResponse *)cachedResponseForRequest:url:host:path:
形成对比,该方法只能同步拦截请求并响应,这使得在例如无需阻塞网络请求的情况下通过代理请求访问网络变得不可能。
如果您喜欢 WebViewProxy,也应该检查一下 WebViewJavascriptBridge。
API
WebViewProxy
注册处理程序以拦截请求
1:使用 + (void) handleRequestsWithScheme:(NSString*)scheme handler:(WVPHandler)handler;
拦截所有指定方案的 UIWebView 请求。
示例
[WebViewProxy handleRequestsWithScheme:@"my_custom_scheme" handler:^(NSURLRequest* req, WVPResponse *res) {
[res respondWithText:@"Hi!"];
}];
+ (void) handleRequestsWithHost:(NSString*)host handler:(WVPHandler)handler;
拦截所有指定主机的 UIWebView 请求。
示例
[WebViewProxy handleRequestsWithHost:@"foo" handler:^(NSURLRequest* req, WVPResponse *res) {
[res respondWithText:@"Hi!"];
}];
+ (void) handleRequestsWithHost:(NSString*)host path:(NSString*)path handler:(WVPHandler)handler;
拦截所有匹配指定主机和 URL 路径的 UIWebView 请求。
示例
[WebViewProxy handleRequestsWithHost:@"foo.com" path:@"/bar" handler:^(NSURLRequest* req, WVPResponse *res) {
[res respondWithText:@"Hi!"];
}];
+ (void) handleRequestsWithHost:(NSString*)host pathPrefix:(NSString*)pathPrefix handler:(WVPHandler)handler;
拦截所有匹配指定主机和 URL 路径前缀的 UIWebView 请求。
例如,一个注册了 [WebViewProxy handleRequestsWithHost:@"foo.com" pathPrefix:@"/bar" handler:...]
的处理器将拦截对 http://foo.com/bar
、https://foo.com/bar/cat?wee=yes
、http://foo.com/bar/arbitrarily/long/subpath
等请求的处理。
示例
[WebViewProxy handleRequestsWithHost:@"foo.com" pathPrefix:@"/bar" handler:^(NSURLRequest* req, WVPResponse *res) {
[res respondWithText:@"Hi!"];
}];
+ (void) handleRequestsMatching:(NSPredicate*)predicate handler:(WVPHandler)handler;
拦截所有 NSURL
匹配给定 NSPredicate
的 UIWebView 请求。
示例
[WebViewProxy handleRequestsMatching:[NSPredicate predicateWithFormat:@"absoluteString MATCHES[cd] '^http:'"] handler:^(NSURLRequest* req, WVPResponse *res) {
[res respondWithText:@"Hi!"];
}];
[WebViewProxy handleRequestsMatching:[NSPredicate predicateWithFormat:@"host MATCHES[cd] '[foo|bar]'"] handler:^(NSURLRequest* req, WVPResponse *res) {
[res respondWithText:@"Hi!"];
}];
WVPResponse
进行响应
2: 通过 所有注册的处理程序都提供 WVPRespone* res
。您可以通过调用此对象的方法对该请求进行响应。
响应请求有3种类型的API
- 高级API:用于响应图像、文本、HTML或JSON
- 低级API:用于响应特定的HTTP头和NSData
- 管道API:用于通过
NSURLConnection
将数据/错误传递到WVPResponse
高级响应API
将详细介绍描述和示例。
- (void) respondWithImage:(UIImage*)image;
用图片进行响应(默认使用 Content-Type "image/png",对于以 .jpg
或 .jpeg
结尾的请求,使用 "image/jpg")
示例
[WebViewProxy handleRequestsWithHost:@"imageExample" path:@"GoogleLogo.png" handler:^(NSURLRequest* req, WVPResponse *res) {
UIImage* image = [UIImage imageNamed:@"GoogleLogo.png"];
[res respondWithImage:image];
}];
- (void) respondWithImage:(UIImage*)image mimeType:(NSString*)mimeType;
用指定的MIME类型响应图片。
示例
[WebViewProxy handleRequestsWithHost:@"imageExample" handler:^(NSURLRequest* req, WVPResponse *res) {
UIImage* image = [UIImage imageNamed:@"GoogleLogo.png"];
[res respondWithImage:image mimeType:@"image/png"];
}];
- (void) respondWithText:(NSString*)text;
使用 (发送) 文本响应 (Content-Type "text/plain")
[WebViewProxy handleRequestsWithHost:@"textExample" handler:^(NSURLRequest* req, WVPResponse *res) {
[res respondWithText:@"Hi!"];
}];
- (void) respondWithHTML:(NSString*)html;
以 HTML 格式响应(发送时 Content-Type 为 "text/html")
[WebViewProxy handleRequestsWithHost:@"htmlExample" handler:^(NSURLRequest* req, WVPResponse *res) {
[res respondWithText:@"<div class='notification'>Hi!</div>"];
}];
- (void) respondWithJSON:(NSDictionary*)jsonObject;
以 JSON 格式响应(发送时 Content-Type 为 "application/json")
[WebViewProxy handleRequestsWithHost:@"textExample" handler:^(NSURLRequest* req, WVPResponse *res) {
NSDictionary* jsonObject = [NSDictionary dictionaryWithObject:@"foo" forKey:@"bar"];
[res respondWithJSON:jsonObject]; // sends '{ "bar":"foo" }'
}];
低级响应 API
将详细介绍描述和示例。
- (void) respondWithStatusCode:(NSInteger)statusCode text:(NSString*)text;
以给定的 HTTP 状态码和文本响应。
示例
[res respondWithStatusCode:400 text:@"Bad request"];
[res respondWithStatusCode:404 text:@"Not found"];
- (void) setHeader:(NSString*)headerName value:(NSString*)headerValue;
在响应之前设置响应头。
示例
[res setHeader:@"Content-Type" value:@"image/gif"];
[res setHeader:@"Content-Type" value:@"audio/wav"];
[res setHeader:@"Host" value:@"WebViewProxy"];
- (void) setHeaders:(NSDictionary*)headers;
在响应之前设置多个响应头。
示例
[res setHeaders:@{ @"Content-Type":@"image/gif", @"Host":@"WebViewProxy" }];
- (void) respondWithData:(NSData*)data mimeType:(NSString*)mimeType;
使用给定数据和mime类型响应(mime类型作为HTTP头部发送为Content-Type
)。
如果mimeType为nil,WebWiewProxy将尝试从请求URL路径扩展名推断它。
示例
NSString* greeting = @"Hi!";
NSData* data = [greeting dataUsingEncoding:NSUTF8StringEncoding];
[res respondWithData:data mimeType:@"text/plain"];
- (void) respondWithData:(NSData*)data mimeType:(NSString*)mimeType statusCode:(NSInteger)statusCode;
使用给定数据、mime类型和HTTP状态码响应(mime类型作为HTTP头部Content-Type
发送)。
如果mimeType为nil,WebWiewProxy将尝试从请求URL路径扩展名推断它。
示例
NSData* data = [@"<div>Item has been created</div>" dataUsingEncoding:NSUTF8StringEncoding];
[res respondWithData:data mimeType:@"text/html" statusCode:201];
[res respondWithData:nil mimeType:nil statusCode:304]; // HTTP status code 304 "Not modified"
[res respondWithData:nil mimeType:nil statusCode:204]; // HTTP status code 204 "No Content"
NSURLCacheStoragePolicy cachePolicy (属性)
响应的缓存策略。默认值是NSURLCacheStorageNotAllowed
示例
response.cachePolicy = NSURLCacheStorageAllowed;
response.cachePolicy = NSURLCacheStorageAllowedInMemoryOnly;
response.cachePolicy = NSURLCacheStorageNotAllowed;
代理远程服务器的请求
使用WebViewProxy
代理远程请求有多种方式。
最简单的方法是将WebViewProxyResponse
作为NSURLConnection
的代理。
[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];
}];
另一种方法提供了更多控制,但必须将整个响应读入内存。
[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]];
NSOperationQueue* queue = [NSOperationQueue new];
[NSURLConnection sendAsynchronousRequest:proxyReq queue:queue completionHandler:^(NSURLResponse* proxyRes, NSData* proxyData, NSError* proxyErr) {
if (proxyErr) {
return [res pipeError:proxyErr];
} else {
NSInteger statusCode = [(NSHTTPURLResponse*)proxyRes statusCode];
[res setHeaders:[(NSHTTPURLResponse*)proxyRes allHeaderFields]];
[res respondWithData:proxyData mimeType:proxyRes.MIMEType statusCode:statusCode];
}
}];
}];
管道响应API
将NSURLResponse
及其数据管道到WVPResponse
中。这使得代理通过NSURLConnection代理请求及其响应变得简单。
示例待编写。
- (void) pipeResponse:(NSURLResponse*)response;
将NSURLResponse管道传输到响应中。
- (void) pipeData:(NSData*)data;
将数据管道传输到响应中。
- (void) pipeError:(NSError*)error;
将错误(例如网络错误)管道传输到响应中。
- (void) pipeEnd;
完成管道响应。
3: (可选)处理“停止加载”事件
请求处理器可能被告知“停止加载”。这可能是因为例如在对底层 NSURLConnection 调用 cancel: 时发生。您可以通过 WVPResponse 上的 handleStopLoadingRequest: 方法来接收此通知。
此 API 可用于示例中停止在请求处理器中执行昂贵的计算。
示例
[WebViewProxy handleRequestsMatching:predicate handler:^(NSURLRequest* req, WVPResponse *res) {
NSOperation* expensiveOperation = [self startExpensiveOperation];
[res handleStopLoadingRequest:^{
[expensiveOperation cancel]
}];
}];
4: 使用您的服务器和端口设置代理以拦截特定条件的URL
示例
拦截所有 http 方案
[WebViewProxy setupProxyHost:@"125.*.*.*" port:@8080 withScheme:@"http"];
或
[WebViewProxy setupProxyHost:@"125.*.*.*" portWithSchemeHTTP:@8080];
如果您想在拦截 URL 时处理数据,可以使用
[WebViewProxy setupProxyHost:@"125.*.*.*" port:@8080 withScheme:@"http" completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
}];
or
[WebViewProxy setupProxyHost:@"125.*.*.*" portWithSchemeHTTP:@8080 completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
}];
拦截所有 http 和 https 方案
[WebViewProxy setupProxyHost:@"125.*.*.*" port:@8080 withScheme:@"https"];
或
[WebViewProxy setupProxyHost:@"125.*.*.*" portWithSchemeHTTPS:@8080];
拦截特殊绝对 URL
[WebViewProxy setupProxyHost:@"125.*.*.*" port:@8080 withAbsoluteString:@"absolute/path"];
拦截特殊相对 URL
[WebViewProxy setupProxyHost:@"125.*.*.*" port:@8080 withRelativePath:@"relative/path"];