ios - título - No se pueden establecer encabezados en mi solicitud POST WKWebView
quitar titulo pagina wordpress (8)
Swift3
Cambia la baseurl
y el token
a tus necesidades.
extension MyWebView: WKNavigationDelegate {
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Swift.Void) {
let request: URLRequest = navigationAction.request
let urlString: String = request.url?.absoluteString ?? ""
let baseurl: String = "http://materik.me/"
let needsAuthorization: Bool = urlString.hasPrefix(baseurl)
if !needsAuthorization {
print("url doesn''t need authorization. /(urlString)")
decisionHandler(.allow)
return
}
let headerFields: [String : String] = request.allHTTPHeaderFields ?? [:]
//print("url: /(urlString) fields: /(headerFields)")
if headerFields["Authorization"] != nil {
print("already has authorization header. /(urlString)")
decisionHandler(.allow)
return
}
print("add authorization header. /(urlString)")
let token: String = "sw_gu6GpGXRG50PR9oxewI"
var mutableRequest = request
mutableRequest.setValue("Bearer /(token)", forHTTPHeaderField: "Authorization")
decisionHandler(.cancel)
webView.load(mutableRequest)
}
}
Quiero hacer una solicitud POST a mi WKWebView
pero los encabezados no se configuran cuando superviso las solicitudes con Charles, por lo que la solicitud falla. ¿Que esta mal aquí?
NSString *post = [NSString stringWithFormat: @"email=%@&password=%@", email, password];
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *contentLength = [NSString stringWithFormat:@"%d", postData.length];
NSURL *url = [NSURL URLWithString:@"http://materik.me/endpoint"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:postData];
[request setValue:contentLength forHTTPHeaderField:@"Content-Length"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[webview loadRequest:request];
Y así es como Charles dice que la petición es como:
POST /endpoint HTTP/1.1
Host: materik.me
Content-Type: application/x-www-form-urlencoded
Origin: null
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (iPhone; CPU OS 8_0 like Mac OS X)
Content-Length: 0
Accept-Language: en-us
Accept-Encoding: gzip, deflate
Entonces, como puede ver, Content-Length
es 0
, Accept
no es application/json
y no se envió ningún cuerpo de solicitud.
Gracias por cualquier ayuda.
Como declaró el OP, también confirmé en Charles que el cuerpo tiene 0 bytes después de webView.load(request)
.
Hay una solución para este error de WKWebView
, iniciaremos una solicitud POST
utilizando URLSession para convertir los datos devueltos por el servidor a String
y, en lugar de cargar la url, usaremos loadHTMLString que:
Establecer el contenido de la página web y la URL base.
y el contenido es nuestra cadena convertida:
var request = URLRequest(url: URL(string: "http://www.yourWebsite")!)
request.httpMethod = "POST"
let params = "do=something&andAgain=something"
request.httpBody = params.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { (data : Data?, response : URLResponse?, error : Error?) in
if data != nil
{
if let returnString = String(data: data!, encoding: .utf8)
{
self.webView.loadHTMLString(returnString, baseURL: URL(string: "http://www.yourWebsite.com")!)
}
}
}
task.resume()
Esto parece ser un error.
https://bugs.webkit.org/show_bug.cgi?id=140188
Esperemos que sea abordado en breve. Mientras tanto, volver a UIWebView o implementar la solución alternativa propuesta por Spas Bilyarski en su respuesta parece ser la mejor opción.
Puedo confirmar este problema. Una solución simple para mí fue una solicitud AJAX, con jQuery:
$.ajax({
type : ''POST'',
url : $(''#checkout-form'').attr(''action''),
data : $(''#checkout-form'').serialize()
}).done(function(response, status) {
// response if return value 200
}).fail(function(status, error) {
console.log(error);
});
donde se ve mi forma
<form id="checkout-form" method="POST" action="/shop/checkout">
...
</form>
Espero que esto ayude a alguien...
Tuve el mismo problema con WKWebView, que decidí usar en lugar de UIWebView para evitar el bloqueo de los selectores en iOS 8. Hay dos formas en las que puedo pensar:
- Use NSURLConnection para realizar la solicitud y luego complete el WKWebView con sus datos de respuesta. Puede encontrar un ejemplo aquí: https://.com/a/10077796/4116680 (solo necesita
connection:didReceiveData:
yconnectionDidFinishLoading:
del delegado si no usa un certificado SSL autofirmado) - Utilice un JavaScript para realizar la solicitud POST. Aquí hay un ejemplo:
Crear archivo por ejemplo. "POSTRequestJS.html":
<html>
<head>
<script>
//POST request example:
//post(''URL'', {key: ''value''});
function post(path, params) {
var method = "post";
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", path);
for(var key in params) {
if(params.hasOwnProperty(key)) {
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", params[key]);
form.appendChild(hiddenField);
}
}
document.body.appendChild(form);
form.submit();
}
</script>
</head>
<body>
</body>
</html>
Y en su código después de donde desea cargar su solicitud:
NSString *path = [[NSBundle mainBundle] pathForResource:@"POSTRequestJS" ofType:@"html"];
NSString *html = [[NSString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
WKWebView.navigationDelegate = self;
[WKWebView loadHTMLString:html baseURL:[[NSBundle mainBundle] bundleURL]];
Añadir método:
- (void)makePostRequest
{
NSString *postData = [NSString stringWithFormat: @"email=%@&password=%@", email, password];
NSString *urlString = @"http://materik.me/endpoint";
NSString *jscript = [NSString stringWithFormat:@"post(''%@'', {%@});", urlString, postData];
DLog(@"Javascript: %@", jscript);
[WKWebView evaluateJavaScript:jscript completionHandler:nil];
didMakePostRequest = YES;
}
Y por último agregar el WKNavigationDelegate:
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
if (!didMakePostRequest) {
[self makePostRequest];
}
}
Yo uso este método de delegado y funciona !!!
#pragma mark - WKNavigationDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
NSLog(@"%@",navigationAction.request.allHTTPHeaderFields);
NSString *accessToken = @"Bearer 527d3401f16a8a7955aeae62299dbfbd";
NSMutableURLRequest *request = [navigationAction.request mutableCopy];
if(![[request.allHTTPHeaderFields allKeys] containsObject:@"Authorization"]){
[request setValue:accessToken forHTTPHeaderField:@"Authorization"];
decisionHandler(WKNavigationActionPolicyCancel);
[Helper hideProgressHUD];
[webView loadRequest:request];
} else {
decisionHandler(WKNavigationActionPolicyAllow);
}
}
solución: truco usando html5 y javascript.
Agregue un archivo html5 con el contenido a continuación a su proyecto de xcode. Para publicar datos utilizando el formulario javascript y h5:
<html>
<head>
<script>
//how to call: post(''URL'', {"key": "value"});
function post(path, params) {
var method = "post";
var form = document.createElement("form");
form.setAttribute("method", method);
form.setAttribute("action", path);
for(var key in params) {
if(params.hasOwnProperty(key)) {
var hiddenField = document.createElement("input");
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("name", key);
hiddenField.setAttribute("value", params[key]);
form.appendChild(hiddenField);
}
}
document.body.appendChild(form);
form.submit();
}
</script>
</head>
<body>
</body>
</html>
Cargue el archivo h5 a WKWebView:
WKWebViewConfiguration* config = [[WKWebViewConfiguration alloc] init];
config.preferences = [[WKPreferences alloc]init];
config.preferences.javaScriptEnabled = YES;
WKWebView* webView = [[WKWebView alloc] initWithFrame:[UIScreen mainScreen].bounds configuration:config];
webView.navigationDelegate = self;
[self.view addSubview:webView];
NSString *path = [[NSBundle mainBundle] pathForResource:@"JSPOST" ofType:@"html"];
NSString *html = [[NSString alloc] initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
[webView loadHTMLString:html baseURL:[[NSBundle mainBundle] bundleURL]];
Preparar los parámetros para publicar. es decir. una cadena y una matriz de diccionario Nota: cuando convierta una matriz en una cadena json utilizando NSJSONSerialization, ''/ r'' se puede agregar automáticamente. Debe eliminar todo el ''/ r'' en la cadena json, o el javascript no se puede analizar correctamente.
// parameters to post
NSString* name = @"Swift";
NSArray* array = @[@{@"id":@"1", @"age":@"12"}, @{@"id":@"2", @"age":@"22"}];
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:array options:NSJSONWritingPrettyPrinted error:nil];
NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
jsonString = [jsonString stringByReplacingOccurrencesOfString:@"/"" withString:@"///'"];
// trim spaces and newline characters
jsonString = [jsonString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
jsonString = [jsonString stringByReplacingOccurrencesOfString:@"/r" withString:@""];
jsonString = [jsonString stringByReplacingOccurrencesOfString:@"/n" withString:@""];
NSString *postData = [NSString stringWithFormat: @"''name'':''%@'', ''contacts'':''%@''", name, jsonString];
// page url to request
NSString *urlStr = @"http:api.example.com/v1/detail";
// javascript to evalute
NSString *jscript = [NSString stringWithFormat:@"post(''%@'',{%@});", urlStr, postData];
//NSLog(@"Javzascript: %@", jscript);
Ponga esto en el delegado de didFinishNavigation
: didFinishNavigation
// call the javascript in step 3
(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
GCD_MAIN((^{
[_web evaluateJavaScript:jscript completionHandler:^(id object, NSError * _Nullable error) {
if (error) {
NSLog(@"----------->>>>>>>>>>>>> evaluateJavaScript error : %@", [error localizedDescription]);
}
}];
}));
}
WKWebView.load
método WKWebView.load
no funciona con la solicitud de publicación con el cuerpo de la publicación. Tienes que usar JavaScript para hacer el truco, verifica WKWebView.evaluateJavascript
.
Tal vez sea un error, pero Apple no lo ha abordado hasta ahora.