Использование пользовательского NSURLProtocol с UIWEBVIEW и POST запросов
-
25-10-2019 - |
Вопрос
В моем приложении для iOS я использую UIWebView и пользовательский протокол (с моей собственной реализацией nsurlProtocol). Я был довольно осторожен с тем, чтобы убедиться, что всякий раз, когда загружаю URL, я загружаю что -то подобное в свой UIWebView:
myprotocol: // myserver/mypath
И в моей реализации nsurlprotocol я беру изменяющуюся копию NsurlRequest, преобразовываю URL в HTTP: и отправляю это на мой сервер.
Все работает для HTTP Get запросов. Проблема, с которой я сталкиваюсь, связана с запросами. Похоже, что UIWebView не должным образом кодирует данные формы в HTTPBody, если в запросе используется мой пользовательский протокол.
Одним из рабочих обходных данных, поскольку я использую HTTPS для запросов на сервер, является то, что я регистрирую свой обработчик протокола для перехвата http: вместо myprotocol: и я могу конвертировать все вызовы в HTTPS: этот другой вопрос, здесь, указал мне на это решение:
Но мне интересно, есть ли какой -либо альтернативный и/или лучший способ выполнить то, что я хочу.
Решение
Вместо того, чтобы пытаться использовать запросы на почту, одна работа должна продолжать использовать запросы на получение запросов myprotocol://
URL -адреса, но трансформируйте их в своем NSURLProtocol
реализация в http://
а также Разместите запрос на ваш сервер, используя строку запроса запроса в качестве корпуса сообщения.
Беспокойство с использованием запросов GET для отправки больших объемов данных заключается в том, что где -то вдоль цепочки запросов линия запроса может быть усечена. Однако это не является проблемой с локально внедренными протоколами.
Я написал короткое тестовое приложение Cordova для эксперимента, и я обнаружил, что смог отправить чуть более 1 MIB данных без проблем в сервис Echoing HTTP -запроса http://http-echo.jgate.de/
Вот мой startLoading
реализация:
- (void)startLoading {
NSURL *url = [[self request] URL];
NSString *query = [url query];
// Create a copy of `url` without the query string.
url = [[[NSURL alloc] initWithScheme:@"http" host:@"http-echo.jgate.de" path:[url path]] autorelease];
NSMutableURLRequest *newRequest = [NSMutableURLRequest requestWithURL:url];
[newRequest setHTTPMethod:@"POST"];
[newRequest setAllHTTPHeaderFields:[[self request] allHTTPHeaderFields]];
[newRequest addValue:@"close" forHTTPHeaderField:@"Connection"];
[newRequest addValue:@"application/x-www-form-urlencoded;charset=UTF-8" forHTTPHeaderField:@"Content-Type"];
[newRequest setHTTPBody:[query dataUsingEncoding:NSUTF8StringEncoding]];
urlConnection = [[NSURLConnection alloc] initWithRequest:newRequest delegate:self];
if (urlConnection) {
receivedData = [[NSMutableData data] retain];
}
}
Затем я внедрил NSURLConnection
Методы протокола для пересылки к соответствующему NSURLProtocolClient
метод, но создание данных ответа в случае Transfer-Encoding:chunked
(как в случае ответов http://http-echo.jgate.de/).
Другие советы
К сожалению, это похоже на это http:
а также https:
Запросы схемы обрабатываются чуть иначе, чем другие (включая пользовательские) схемы по основам. Очевидно HTTPBody
а также HTTPBodyStream
вызывает актуальность NSURLRequest
возвращается всегда nil
для бывших. Это решительно уже предшествует звонку [NSURLProtocol canInitWithRequest]
поэтому обычай NSURLProtocol
Реализация не может влиять на это (уже слишком поздно).
Кажется, что другой NSURLRequest
Класс используется для http:
а также https:
чем «по умолчанию один». Реализация GNUSTEP этого класса по умолчанию всегда nil
из HTTPBody
а также HTTPBodyStream
вызовы Поэтому конкретные реализации (например, один под PhoneGap, вероятно, часть Foundation Framework) выбирают NSURLRequest
-Type of Class на основе схемы предшествующего консультации, который с NSURLProtocol
. Анкет Для пользовательских схем вы получаете NSURLRequest
это возвращается nil
для обоих HTTPBody
а также HTTPBodyStream
который эффективно отключает использование метода Post (и других методов с телом) в пользовательском обработчике схемы URI.
Может быть, есть способ влиять на решение о котором NSURLRequest
Класс фактически используется, но в настоящее время мне неизвестно.
В качестве обходного пути вы все равно можете использовать http:
или же https:
схема и решайте в [NSURLProtocol canInitWithRequest]
на основе других критериев (например, имя хоста).