在自定义 NSURLProtocol 中捕获 POST 参数

Posted

技术标签:

【中文标题】在自定义 NSURLProtocol 中捕获 POST 参数【英文标题】:Capture POST parameters in custom NSURLProtocol 【发布时间】:2019-03-22 10:27:36 【问题描述】:

我有一个 NSURLProtocol 监听 UIWebView 上的 POST 请求。我尝试捕获 POST 参数并首先读取here,httpBody 始终为零,因为主体数据对象被转换为流式主体。

然后我使用以下扩展打开 HTTPBodyStream 对象并从中读取正文数据。

extension InputStream 
        func readfully() -> Data 
            var result = Data()
            var buffer = [UInt8](repeating: 0, count: 4096)

            open()

            var amount = 0
            repeat 
                amount = read(&buffer, maxLength: buffer.count)
                if amount > 0 
                    result.append(buffer, count: amount)
                
             while amount > 0

            close()

            return result
        
    

问题是我从输入流中读取的 bodyData 也是 nil。在 MyUrlProtocol 中,我重写了以下方法。

    override class func canInit(with request: URLRequest) -> Bool

        if request.httpMethod == "POST" 
            print(request.url?.absoluteString) //ok show correct POST url

            let bodyData = request.httpBodyStream?.readfully() //nil
            print(String(data: bodyData!, encoding: String.Encoding.utf8))

            return true
        

        return false
    

    override class func canonicalRequest(for request: URLRequest) -> URLRequest 
        return request
    

    override func startLoading() 
        let bodyData = self.request.httpBodyStream?.readfully() //nil
    

    override func stopLoading() 
        let bodyData = self.request.httpBodyStream?.readfully() //nil
    

为什么我的自定义 NSURLProtocol 中的 httpBodyStream 也是 Nil?

我可以在我的网络浏览器中使用网络开发工具正确查看同一 URL 的 POST 参数。

【问题讨论】:

检查是否在httpBody中设置? 再看你提到的答案。在 2018 年 1 月 18 日的评论中,作者解释了设置流代理以读取流所必须执行的步骤。 @SachinVas httpBody 也为零 @MikeTaverne 是的,这正是我在扩展中所做的,打开流并读取字节。这个扩展曾经可以工作,但我不知道为什么我不能再捕获 httpBodyStream 数据了 【参考方案1】:

你不能像那样同步地从流中读取。您必须等待字节在流上可用,然后读取,然后再次等待,等等,直到其中一个读取返回零字节。如果没有等待部分,您就不会读取 while 内容,因为您读取数据的代码几乎肯定会阻塞应该填充流对另一端的线程。

这里描述了从流中读取的完整步骤:

https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Streams/Articles/ReadingInputStreams.html

如果数据太大而无法放入 RAM,您可能需要在解析数据时将各个位写入磁盘,然后提供新的输入流。

无论哪种方式,您都必须异步执行。

【讨论】:

以上是关于在自定义 NSURLProtocol 中捕获 POST 参数的主要内容,如果未能解决你的问题,请参考以下文章

如何捕获 UIButton 事件:在自定义 UITableViewCell 实现中添加了 UIButton

什么方法可以捕获在自定义视图(布局)中选择的上下文菜单项?

如何在自定义变体上捕获数组索引

NSURLProtocol 详解

iOS - 将 AFNetworking 与自定义 NSURLProtocol 类一起使用

如何在自定义相机中实现“捏放大”