无法在我的WKWebView POST请求上设置标头

Mat*_*yhr 21 objective-c nsurlrequest ios wkwebview charles-proxy

我想对我做一个POST请求,WKWebView但是当我用Charles监视请求时,标题没有设置,因此请求失败.这有什么不对?

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];
Run Code Online (Sandbox Code Playgroud)

这就是查尔斯所说的请求如下:

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
Run Code Online (Sandbox Code Playgroud)

因此,正如您所看到的那样,Content-Length0,Accept是,application/json并且没有请求正文被发送.

谢谢你的帮助.

小智 16

我遇到了与WKWebView相同的问题,我决定使用UIWebView来避免iOS 8中的选择器崩溃.我可以想到两种方式:

  1. 使用NSURLConnection发出请求,然后用它的响应数据填充WKWebView.你可以在这里找到一个例子: /sf/answers/705445751/(你只需要connection:didReceiveData:connectionDidFinishLoading:从委托,如果你不使用自签名的SSL证书)
  2. 使用JavaScript来发出POST请求.这是一个例子:

创建文件,例如."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>
Run Code Online (Sandbox Code Playgroud)

在您希望加载请求的代码中:

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]];
Run Code Online (Sandbox Code Playgroud)

添加方法:

- (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;
}
Run Code Online (Sandbox Code Playgroud)

最后添加WKNavigationDelegate:

- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
    if (!didMakePostRequest) {
        [self makePostRequest];
    }
}
Run Code Online (Sandbox Code Playgroud)


Oha*_*adM 16

正如OP所述,我在Charles中也确认身体是0字节后webView.load(request).

这个WKWebViewbug 有一个解决方法,我们将POST使用URLSession 发起请求,将服务器返回的数据转换为String,而不是加载url,我们将使用loadHTMLString,它将:

设置网页内容和基本URL.

并且内容是我们转换的字符串:

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()
Run Code Online (Sandbox Code Playgroud)

  • 辉煌.仍然是2018-09-13的问题 (5认同)

小智 8

这似乎是一个错误.
https://bugs.webkit.org/show_bug.cgi?id=140188

希望很快就会得到解决.与此同时,恢复到UIWebView或实施Spas Bilyarski在他的回答中提出的解决方案似乎是最好的选择.

  • 这个bug已经修复了一个月前https://bugs.webkit.org/show_bug.cgi?id=167131 (2认同)

Har*_*hak 7

我使用这个委托方法,它的工作原理!

#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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 在iOS 10.3中,对于httpBody来说,它是无限的。 (2认同)