Захват параметров POST в пользовательском NSURLProtocol - PullRequest
0 голосов
/ 22 марта 2019

У меня есть NSURLProtocol, слушающий запросы POST на UIWebView. Я пытаюсь захватить параметры 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
        }
    }

Проблема в том, что мои данные 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
    }

Почему httpBodyStream также является Nil внутри моего собственного NSURLProtocol?

Я могу правильно видеть параметры POST для того же URL-адреса с помощью инструмента сетевого разработчика в моем веб-браузере.

1 Ответ

0 голосов
/ 23 марта 2019

Вы не можете читать из потока синхронно, как это. Вам нужно подождать, пока байты будут доступны в потоке, затем прочитать, затем снова подождать и т. Д., Пока одно из этих чтений не возвратит ноль байтов. Без ожидающей части вы не читаете пока что, потому что ваш код для чтения данных почти наверняка блокирует поток, который должен заполнить другой конец пары потоков.

Полный набор шагов для чтения из потока описан здесь:

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

И если данные слишком велики, чтобы поместиться в ОЗУ, вам может потребоваться записать различные биты на диск при его разборе, а затем предоставить новый входной поток.

В любом случае, вам придется делать это асинхронно.

...