Reputation: 89
I have an NSURLProtocol listening to POST requests on a UIWebView. I try to capture the POST parameters and first read here that httpBody is always nil as body data objects are converted into streaming-style bodies.
Then I use the following extension to open the HTTPBodyStream object and read the body data from it.
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
}
}
Problem is my bodyData read from the input stream is also nil. Inside MyUrlProtocol, I override the following methods.
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
}
Why is the httpBodyStream also Nil inside my custom NSURLProtocol?
I can see the POST parameters correctly for the same URL with the network dev tool in my web browser.
Upvotes: 0
Views: 519
Reputation: 10407
You can’t read from a stream synchronously like that. You have to wait for bytes to be available on the stream, then read, then wait again, etc. until one of those reads returns zero bytes. Without the waiting part, you’re not reading the while thing, because your code to read the data is almost certainly blocking the thread that is supposed to fill the other end of the stream pair.
The complete set of steps for reading from a stream are described here:
And if the data is too big to fit in RAM, you may need to write the various bits to disk as you parse it and then provide a new input stream.
Either way, you’ll have to do it asynchronously.
Upvotes: 0