为什么NSURLProtocol子类中的请求的HTTPBody总是为零?

时间:2016-04-11 17:10:18

标签: ios swift nsurlprotocol

我有我的NSURLProtocol NSURLProtocol.registerClass(MyGreatProtocol) 。我将它添加到URL加载系统,

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() 内接收事件。

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

1/3/3/7

我希望请求的HTTP正文MyGreatProtocol出现在MyGreatProtocol内,而不是。{/ p>

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 } 内,我覆盖以下方法。

fileslist <- list.files(path="/Users/joker/csv_test/", pattern=".csv")
sapply(fileslist, read.csv)

似乎保留了NSURLRequest的其他属性。 URL,HTTP动词,标题等都在那里。关于身体性质的具体事情仍然是难以捉摸的。

为什么HTTP Body Nil在自定义NSURLProtocol中?

似乎对先前提交的雷达(即https://bugs.webkit.org/show_bug.cgi?id=137299

进行了类似的讨论

2 个答案:

答案 0 :(得分:3)

IIRC,身份数据对象在到达您之前由URL加载系统透明地转换为流式样主体。如果您需要阅读数据:

  • 打开HTTPBodyStream对象
  • 从中读取身体数据

有一点需要注意:流可能无法重绕,因此不要将该请求对象传递给之后需要访问主体的任何其他代码。遗憾的是,没有机制可以请求新的正文流(请参阅Apple网站上的CustomHTTPProtocol示例代码项目中的README文件以了解其他限制)。

答案 1 :(得分:1)

以下是阅读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
        }
    }
}

然后,在URLProtocol中:

override func startLoading() {

    ...

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

        print("JSON \(jsonBody)")

    }

    ...
}