为什么 NSURLProtocol 子类中请求的 HTTPBody 始终为零?

Jam*_*ham 4 nsurlprotocol ios swift

我有我的 NSURLProtocol MyGreatProtocol。我将它添加到 URL 加载系统中,

NSURLProtocol.registerClass(MyGreatProtocol)
Run Code Online (Sandbox Code Playgroud)

然后我开始MyGreatProtocol在网络会话期间接收内部事件。

假设我在注册我的协议后创建会话,

let session = NSURLSession.sharedSession()
    let request = NSMutableURLRequest(URL: NSURL(string:"http://example.com")!, cachePolicy: .ReloadIgnoringLocalCacheData, timeoutInterval: 2.0) //arbitrary 404
    request.HTTPBody = ([1, 3, 3, 7] as [UInt8]).toNSData
    print("body data: \(request.HTTPBody)") //prints `Optional(<01030307>)`
    request.HTTPMethod = "POST"
    session.dataTaskWithRequest(request) { (data, response, err) in
        print("data: \(data)\nresponse: \(response)\nerror\(err)")
    }.resume()
Run Code Online (Sandbox Code Playgroud)

我希望请求的 HTTP 正文1/3/3/7出现在 中MyGreatProtocol,而实际上却没有。

在里面MyGreatProtocol,我覆盖了以下方法。

override class func canonicalRequestForRequest(request: NSURLRequest) -> NSURLRequest {
    print(request.HTTPBody) //prints nil
    return request
}

override class func canInitWithRequest(request: NSURLRequest) -> Bool {
    print(request.HTTPBody) //prints nil
    return true
}

override func startLoading() {
    print(self.request.HTTPBody) //prints nil
}
Run Code Online (Sandbox Code Playgroud)

NSURLRequest 的其他属性似乎被保留了。URL、HTTP 动词、标头等都在那里。关于身体性质的一些具体情况仍然难以捉摸。

为什么自定义 NSURLProtocol 中的 HTTP 正文为零?

之前提交的雷达似乎有一些类似的讨论(即https://bugs.webkit.org/show_bug.cgi?id=137299

bau*_*sic 9

下面是读取 httpBody 的示例代码:

斯威夫特 5

extension URLRequest {

    func bodySteamAsJSON() -> Any? {

        guard let bodyStream = self.httpBodyStream else { return nil }

        bodyStream.open()

        // Will read 16 chars per iteration. Can use bigger buffer if needed
        let bufferSize: Int = 16

        let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bufferSize)

        var dat = Data()

        while bodyStream.hasBytesAvailable {

            let readDat = bodyStream.read(buffer, maxLength: bufferSize)
            dat.append(buffer, count: readDat)
        }

        buffer.deallocate()

        bodyStream.close()

        do {
            return try JSONSerialization.jsonObject(with: dat, options: JSONSerialization.ReadingOptions.allowFragments)
        } catch {

            print(error.localizedDescription)

            return nil
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,在 URLProtocol 中:

override func startLoading() {

    ...

    if let jsonBody = self.request.bodySteamAsJSON() {

        print("JSON \(jsonBody)")

    }

    ...
}
Run Code Online (Sandbox Code Playgroud)