在自定义 NSURLProtocol 中捕获 POST 参数



我有一个NSURLProtocol在UIWebView上监听POST请求。我尝试捕获 POST 参数并首先在这里阅读 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
        }
    }

问题是我的身体从输入流读取的数据也是零。在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
    }

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

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

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

下面介绍了从流中读取的完整步骤集:

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

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

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

最新更新