在自定义NSURLProtocol中捕获POST参数

时间:2019-03-22 10:27:36

标签: ios swift uiwebview nsurlprotocol

我有一个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也为零。在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也没有显示?

在我的Web浏览器中,可以使用network dev工具正确看到相同URL的POST参数。

1 个答案:

答案 0 :(得分:0)

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

此处描述了从流中读取的完整步骤集:

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

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

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