Domanda

Nel mio iOS, sto usando un UIWebView e un protocollo personalizzato (con la mia propria implementazione NSURLProtocol). Sono stato abbastanza attento a fare in modo che ogni volta che carico un URL, mi carico qualcosa di simile nella mia UIWebView:

myprotocol: // myserver / mypath

e nella mia implementazione NSURLProtocol, prendo una copia mutabile della NSURLRequest, convertire l'URL http:. E inviare che al mio server

Tutto funziona per le richieste HTTP GET. L'incontro problema che ho è con richieste POST. Sembra che l'UIWebView non codificare correttamente i dati del modulo nel HTTPBody se la richiesta usa il mio protocollo personalizzato.

Un work-around, dal momento che sto utilizzando il protocollo HTTPS per le mie richieste al server, è che registro il mio gestore di protocollo di intercettare http: invece di myprotocol: e posso convertire tutte le chiamate a https: Questa altra domanda, qui , mi ha puntato verso quella soluzione:

Ma mi chiedo se c'è un modo alternativo e / o migliore di realizzare ciò che voglio.

È stato utile?

Soluzione

Invece di cercare di utilizzare richieste POST, un lavoro intorno è quello di continuare a utilizzare le richieste GET di URL myprotocol://, ma trasformarli nell'implementazione NSURLProtocol a un http:// e richiesta POST al server utilizzando la richiesta stringa di query come il corpo del post.

La preoccupazione con l'utilizzo di richieste GET per inviare grandi quantità di dati è che da qualche parte lungo la catena richiesta, la linea di richiesta potrebbe avere troncato. Questo sembra non essere un problema, però, con i protocolli a livello locale implementati.

ho scritto un breve test app Cordova a sperimentare e ho scoperto che ero in grado di inviare tramite un poco più di 1 Mb di dati senza difficoltà alla richiesta HTTP servizio di eco http://http-echo.jgate.de/

Ecco la mia implementazione 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];
    }
}

Ho poi implementato i metodi del protocollo NSURLConnection di trasmettere al metodo NSURLProtocolClient appropriato, ma costruire i dati di risposta nel caso di Transfer-Encoding:chunked (come è il caso per una risposta da http://http-echo.jgate.de/ ).

Altri suggerimenti

Purtroppo sembra che le richieste di schema http: e https: vengono gestiti in modo leggermente diverso rispetto agli altri (compresi personalizzato) schemi di Fondazione Framework. Ovviamente le chiamate HTTPBody e HTTPBodyStream sui rendimenti NSURLRequest rilevanti sempre nil per i più vecchi. Questo è deciso già prima della chiamata del [NSURLProtocol canInitWithRequest] quindi NSURLProtocol personalizzato implementazione non ha alcun modo di influenzare che (è troppo tardi).

Sembra che diverse classi NSURLRequest viene utilizzato per http: e https: di 'uno di default'. Predefinito implementazione GNUstep di questa classe restituisce sempre nil dalle chiamate HTTPBody e HTTPBodyStream. Pertanto implementazioni particolari (ad esempio, uno sotto PhoneGap, probabilmente parte di Fondazione quadro) scelgono NSURLRequest-tipo di classe basata su schema di prima consulenza che con NSURLProtocol. Per i regimi personalizzati, si ottiene NSURLRequest che i rendimenti nil sia per HTTPBody e HTTPBodyStream che di fatto disabilita l'uso del metodo POST (e altri metodi con il corpo) in costume gestore schema URI.

Forse c'è un modo per influenzare la decisione di quale classe NSURLRequest viene effettivamente utilizzato, ma è attualmente sconosciuto per me.

Per risolvere il problema, è comunque possibile utilizzare schema http: o https: e decidere in [NSURLProtocol canInitWithRequest] sulla base di altri criteri (ad esempio nome host).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top