Utilizando un protocolo NSURL personalizado con requestes UIWebView y POST

En mi aplicación de iOS, estoy usando un UIWebView y un protocolo personalizado (con mi propia implementación NSURLProtocol). He tenido bastante cuidado en asegurarme de que cada vez que cargué una url, cargué algo así en mi UIWebView:

myprotocol: // myserver / mypath

y en mi implementación NSURLProtocol, tomo una copy mutable de NSURLRequest, convierto la URL a http: y la envío a mi server.

Todo funciona para requestes HTTP GET. El problema que encuentro es con las requestes POST. Parece que UIWebView no codifica correctamente los datos del formulario en el cuerpo HTTP si la request utiliza mi protocolo personalizado.

Una solución, ya que estoy usando HTTPS para las requestes de mi server, es que logging mi controller de protocolo para interceptar http: en lugar de myprotocol: y puedo convertir todas las llamadas a https: esta otra pregunta, aquí , me indicó que solución:

Pero me pregunto si hay alguna alternativa y / o mejor manera de lograr lo que quiero.

En lugar de tratar de usar las requestes POST, una myprotocol:// es seguir utilizando requestes GET para myprotocol:// URL, pero transformarlas en su implementación NSURLProtocol en una request http:// y POST a su server utilizando la cadena de consulta de request como la cuerpo del POST.

La preocupación con el uso de las requestes GET para enviar grandes cantidades de datos es que en algún lugar a lo largo de la cadena de requestes, la línea de request puede quedar truncada. Sin embargo, esto parece no ser un problema con los protocolos implementados localmente.

Escribí una breve aplicación de testing Cordova para experimentar y descubrí que pude enviar un poco más de 1 MiB de datos sin problemas al service de eco de la request HTTP http://http-echo.jgate.de/

Aquí está mi implementación 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]; } } 

Luego implementé los methods del protocolo NSURLConnection para reenviar al método NSURLProtocolClient apropiado, pero NSURLProtocolClient los datos de respuesta en el caso de Transfer-Encoding:chunked de Transfer-Encoding:chunked (como es el caso de las respuestas de http://http-echo.jgate.de/ )

Lamentablemente, parece que las requestes de esquema http: y https: se manejan de forma ligeramente diferente a otros esquemas (incluidos los personalizados) por Foundation Framework. Obviamente, HTTPBody y HTTPBodyStream invoca las NSURLRequest relevantes NSURLRequest siempre es nil para las anteriores. Esto ya se decidió con la llamada previa de [NSURLProtocol canInitWithRequest] por NSURLProtocol implementación personalizada de NSURLProtocol no tiene forma de influir en eso (es demasiado tarde).

Parece que se NSURLRequest class NSURLRequest diferente para http: y https: que 'una pnetworkingeterminada'. La implementación pnetworkingeterminada de GnuStep de esta class siempre devuelve nil de llamadas HTTPBody y HTTPBodyStream . Por lo tanto, las implementaciones particulares (por ejemplo, una en PhoneGap, parte probable de Foundation Framework) eligen NSURLRequest -type de class basado en el esquema que consulta previamente con NSURLProtocol . Para los esquemas personalizados, obtiene NSURLRequest que devuelve nil tanto para HTTPBody como para HTTPBodyStream que efectivamente deshabilita el uso del método POST (y otros methods con el cuerpo) en el controller de esquema de URI personalizado.

Tal vez hay una manera de influir en la decisión de qué class de NSURLRequest se utiliza realmente, pero actualmente no me es conocida.

Como solución alternativa, puede utilizar http: o https: esquema y decidir en [NSURLProtocol canInitWithRequest] según otros criterios (por ejemplo, nombre de host).