前言:本文简述URLProtocol的简单使用,仅做参考
一、NSURLProtocol 简介
URLProtocol是URL Loading System的一部分。并且是一个对象。
功能:
1.拦截所有的NSURLRequest
2.忽略网络请求,返回自定义的Response。
3.修改request
4.数据拦截
这是一张从官方文档贴过来的图片:
二、URLProtocol 创建
如下代码使用 swift
做简单展示
1.创建一个子类(小白兔URLProtocol)继承自 URLProtocol
class XBTURLProtocol: URLProtocol {
}
2.协议是否可以处理给定的请求
一个具体的子类应该检查给定的请求,并确定实现是否可以用该请求执行负载。这是一个抽象方法。子类必须提供实现。
如果协议能够处理给定的请求,则为YES,如果不能,则为NO。
override open class func canInit(with request: URLRequest) -> Bool {
return true
}
3.返回给定请求NSURLRequest
取决于每个具体的协议实现,协议应该保证相同的输入请求总是产生相同的规范形式,因为请求的规范形式用于在URL缓存中查找对象,这是一个在NSURLRequest对象之间执行相等检查的过程。
override open class func canonicalRequest(for request: URLRequest) -> URLRequest {
return request
}
4.拦截的请求开始执行
启动特定于协议的请求加载。当调用此方法时,协议实现应该开始加载请求。
override open func startLoading() {
}
5. 拦截的请求停止执行
停止特定于协议的请求加载。当调用此方法时,协议实现应该结束加载请求的工作。这可能是对cancel操作的响应,因此协议实现必须能够在加载过程中处理这个调用。
override open func stopLoading() {
return
}
6.附上demo
XBTURLProtocol.swift
import Foundation
import PromiseKit
let source_delegate = true
//拦截的有关内容
let ext_arr:[String:String] = [
"js": "application/javascript",
"css": "text/css",
// "png": "image/png",
"woff": "text/plain",
"html": "text/html"
];
class GURLProtocol: URLProtocol {
override open class func canInit(with request: URLRequest) -> Bool {
var ext: String? = request.url?.pathExtension;
if(source_delegate) {
let range = request.url?.absoluteString.range(of: "可以是你的hosturl")
let is_page = request.url?.absoluteString.range(of: "or 你的web url")
let has_at = request.url?.absoluteString.range(of: "特定的字符串")
if(is_page != nil && has_at == nil) {
ext = "html"
}
if((ext_arr[ext!]) != nil && range == nil) {
return true
}
else {
return false
}
}
else {
return false
}
}
override open class func canonicalRequest(for request: URLRequest) -> URLRequest {
return request
}
//对拦截的request做重定向处理
override open func startLoading() {
var ext: String? = request.url?.pathExtension;
let path = self.request.url?.relativePath
var url_str:String? = "\("重定向后的hosturl")\(path!)"
let is_page = self.request.url?.absoluteString.range(of: "特定url")
if(is_page != nil) {
url_str = self.request.url?.absoluteString
ext = "html"
}
let url = URL.init(string: url_str!)
let success = {
(result: Any?) -> () in
let data = result as! Data
let mimeType: String? = ext_arr[ext!]
let response = URLResponse.init(url: url!, mimeType: mimeType!, expectedContentLength: 10000, textEncodingName: nil)
self.client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: URLCache.StoragePolicy.notAllowed)
self.client?.urlProtocol(self, didLoad: data)
self.client?.urlProtocolDidFinishLoading(self)
}
let failure = {
(result: Any?) -> () in
printLog(msg: result!)
}
//如下是封装的get请求的基类
Network().getWithPath(path: url_str!, success: success, failure: failure)
}
override open func stopLoading() {
return
}
}
三、XBTURLProtocol的使用
1.在APPDelegate.swift注册
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
URLProtocol.wk_registerScheme("http")
URLProtocol.registerClass(XBTURLProtocol.self)
return true
}
2.在工程基类中注册
XXXXXController.swift
override func viewDidLoad() {
super.viewDidLoad()
URLProtocol.wk_registerScheme("http")
URLProtocol.wk_registerScheme("https")
}
继续探索ing