Verwenden eines benutzerdefinierten NsurlProtocols mit UIWebView- und Postanforderungen
-
25-10-2019 - |
Frage
In meiner iOS -App verwende ich eine UIWebView und ein benutzerdefiniertes Protokoll (mit meiner eigenen NsurlProtocol -Implementierung). Ich war ziemlich vorsichtig damit, sicherzustellen, dass ich so etwas in meine UIWebview lade: wenn ich eine URL lade:
MyProtocol: // Myserver/MyPath
Und in meiner NsurlProtocol -Implementierung nehme ich eine veränderliche Kopie des NsurlRequest, konvertieren die URL in HTTP: und sende dies an meinen Server.
Alles funktioniert für HTTP -Anfragen. Das Problem, das ich begegne, besteht bei Postanfragen. Es scheint, als ob die UIWebView die Formulardaten im HTTPBODY nicht ordnungsgemäß ordnungsgemäß codieren, wenn die Anforderung mein benutzerdefiniertes Protokoll verwendet.
Eine Arbeit, da ich HTTPS für meine Serveranfragen verwende, ist, dass ich meinen Protokollhandler registriere, um HTTP abzufangen: anstelle von MyProtocol: Und ich kann alle Anrufe in HTTPS konvertieren: Diese andere Frage, diese andere Frage, hier, zeigte mich auf diese Lösung:
Aber ich frage mich, ob es eine alternative und/oder bessere Möglichkeit gibt, das zu erreichen, was ich will.
Lösung
Anstatt zu versuchen, Postanfragen zu verwenden, besteht eine Arbeit darin, weiterhin GET -Anfragen für zu verwenden myprotocol://
URLs, aber verwandeln Sie sie in Ihre NSURLProtocol
Implementierung zu an http://
und Stellen Sie die Anforderung an Ihren Server mit der Anfrage -Abfragezeichenfolge als Körperschaft des Posts an.
Die Sorge bei der Verwendung von GET -Anfragen zum Senden großer Datenmengen besteht darin, dass die Anforderungszeile irgendwo entlang der Anforderungskette abgeschnitten wird. Dies scheint jedoch kein Problem mit lokal implementierten Protokollen zu sein.
Ich habe eine kurze Cordova -Test -App geschrieben, um zu experimentieren, und stellte fest, dass ich etwas mehr als 1 MIB Daten schicken konnte http://http-echo.jgate.de/
Hier ist mein startLoading
Implementierung:
- (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];
}
}
Ich habe dann das implementiert NSURLConnection
Protokollmethoden, um sich an die angemessenen zu leiten NSURLProtocolClient
Methode, aber die Antwortdaten im Fall von aufbauen Transfer-Encoding:chunked
(Wie bei Antworten von http://http-echo.jgate.de/).
Andere Tipps
Leider sieht es so aus http:
und https:
Schemaanfragen werden etwas anders behandelt als andere (einschließlich benutzerdefinierter) Programme nach Foundation Framework. Offensichtlich HTTPBody
und HTTPBodyStream
Aufrufe relevant NSURLRequest
kehrt immer zurück nil
für frühere. Dies wird bereits vorangegangen [NSURLProtocol canInitWithRequest]
Daher individuell NSURLProtocol
Implementierung kann dies nicht beeinflussen (es ist zu spät).
Es scheint so anders NSURLRequest
Klasse wird verwendet für http:
und https:
als 'a Standardes'. Standard -GNUSTEP -Implementierung dieser Klasse kehrt zurück stets nil
aus HTTPBody
und HTTPBodyStream
Anrufe. Daher wählen bestimmte Implementierungen (z. NSURLRequest
-typ der Klasse basierend auf Schema vor der Beratung, die mit dem mit NSURLProtocol
. Für benutzerdefinierte Programme erhalten Sie NSURLRequest
Das kehrt zurück nil
für beide HTTPBody
und HTTPBodyStream
die die Verwendung von Post -Methoden (und anderen Methoden mit Körper) im benutzerdefinierten URI -Schema -Handler effektiv deaktiviert.
Vielleicht gibt es eine Möglichkeit, die Entscheidung zu beeinflussen NSURLRequest
Die Klasse wird tatsächlich verwendet, aber es ist mir derzeit unbekannt.
Als Problemumgehung können Sie immer noch verwenden http:
oder https:
programmieren und entscheiden in [NSURLProtocol canInitWithRequest]
Basierend auf anderen Kriterien (z. B. Hostname).