WKWebView HTTPHeaderField
WKWebView的请求头添加字段。
系统的NSMutableHTTPURLRequest类提供了获取HTTP请求的请求头(HTTPHeader)和设置/添加HTTP请求的请求头的API。
@property (nullable, copy) NSDictionary<NSString *, NSString *> *allHTTPHeaderFields;
/*!
@method setValue:forHTTPHeaderField:
@abstract Sets the value of the given HTTP header field.
@discussion If a value was previously set for the given header
field, that value is replaced with the given value. Note that, in
keeping with the HTTP RFC, HTTP header field names are
case-insensitive.
@param value the header field value.
@param field the header field name (case-insensitive).
*/
- (void)setValue:(nullable NSString *)value forHTTPHeaderField:(NSString *)field;
/*!
@method addValue:forHTTPHeaderField:
@abstract Adds an HTTP header field in the current header
dictionary.
@discussion This method provides a way to add values to header
fields incrementally. If a value was previously set for the given
header field, the given value is appended to the previously-existing
value. The appropriate field delimiter, a comma in the case of HTTP,
is added by the implementation, and should not be added to the given
value by the caller. Note that, in keeping with the HTTP RFC, HTTP
header field names are case-insensitive.
@param value the header field value.
@param field the header field name (case-insensitive).
*/
- (void)addValue:(NSString *)value forHTTPHeaderField:(NSString *)field;
我们知道向HTTP请求的请求头里添加字段使用系统提供的上面两个API,并在请求知道添加即可,但是向WKWebView的请求Request的请求头里添加字段可能会有添加不上的情况。
可以跑Demo试一下,然后在Safari浏览器连手机在网页检查器里查看是否添加成功。
#import "ViewController.h"
#import <WebKit/WebKit.h>
@interface ViewController ()<WKUIDelegate,WKNavigationDelegate>
@property (nonatomic, strong) WKWebView *webView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
WKWebViewConfiguration *confirg = [[WKWebViewConfiguration alloc] init];
confirg.allowsInlineMediaPlayback = YES;
self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:confirg];
self.webView.UIDelegate = self;
self.webView.navigationDelegate = self;
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"https://www.jianshu.com/p/adb641dea4e0?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation"]];
// 1. 设置无效
//[request setValue:@"My App 20.01" forHTTPHeaderField:@"CustumAgent"];
[self.webView loadRequest:request];
[self.view addSubview:self.webView];
}
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
// // 2. 设置无效
// NSMutableURLRequest *request = (NSMutableURLRequest *)navigationAction.request;
// NSString *custumAgent = [request valueForHTTPHeaderField:@"CustumAgent"];
// if (!custumAgent || !custumAgent.length) {
// [request setValue:@"My App 20.01" forHTTPHeaderField:@"CustumAgent"];
// }
// decisionHandler(WKNavigationActionPolicyAllow);
// // 3. 设置无效
// NSMutableURLRequest *request = (NSMutableURLRequest *)navigationAction.request;
// NSString *custumAgent = [request valueForHTTPHeaderField:@"CustumAgent"];
// if (!custumAgent || !custumAgent.length) {
// [request setValue:@"My App 20.01" forHTTPHeaderField:@"CustumAgent"];
// [self.webView loadRequest:request];
// }
// decisionHandler(WKNavigationActionPolicyAllow);
// 4. iOS 14.2 上可行,iOS 14.1 以及以下版本无效
NSMutableURLRequest *request = (NSMutableURLRequest *)navigationAction.request;
NSString *custumAgent = [request valueForHTTPHeaderField:@"CustumAgent"];
if (!custumAgent || !custumAgent.length) {
[request setValue:@"My App 20.01" forHTTPHeaderField:@"CustumAgent"];
[self.webView loadRequest:request];
decisionHandler(WKNavigationActionPolicyCancel);
return;
}
decisionHandler(WKNavigationActionPolicyAllow);
}
@end
综上,个人建议不要往WKWebView的请求中设置HTTPHeader,NSMutableHTTPURLRequest虽然提供了这个设置HeaderField的API,因为在加载WebView之前设置,不会生效,在webView:decidePolicyForNavigationAction:中再去设置的话感觉会有些晚了,逻辑上应该在发起请求之前就设置。
iOS 14.7 iPad Air 3,测试上述的两种设置方法,发现设置无效,无论是请求前还是回调后设置都设置不成功。
最后决定还是通过注入 js 的方式来设置吧
// 添加webView
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.applicationNameForUserAgent = @"iOS iPad";
self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
self.webView.UIDelegate = self;
self.webView.navigationDelegate = self;
[self.view addSubview:self.webView];
// 加载webView
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:URLStr]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:50];
[self.webView loadRequest:request];
// 方法注入,设置CustomUserAgent的值
NSString *CustomUserAgent = [NSString stringWithFormat:@"%@ %@",@"1.234" ,@"5678"];
[self addScriptHandlerTo:self.webView message:nil javascript:[NSString stringWithFormat:@"function addCustomUserAgentNode() { \n var hdObj = document.createElement(\"input\"); \n hdObj.type = \"hidden\"; \n hdObj.id = \"CustomUserAgent\"; \n hdObj.value = \"%@\"; document.body.appendChild(hdObj);}", CustomUserAgent]];
- (void)addScriptHandlerTo:(WKWebView *)webView message:(NSString *)message javascript:(NSString *)javascript {
if (message) {
[webView.configuration.userContentController addScriptMessageHandler:self name:message];
}
if (javascript) {
WKUserScript *userScript = [[WKUserScript alloc] initWithSource:javascript
injectionTime:WKUserScriptInjectionTimeAtDocumentEnd
forMainFrameOnly:YES];
[webView.configuration.userContentController addUserScript:userScript];
}
}
#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
}
以下是 jd 端部分代码
if (typeof addCustomUserAgentNode === "function") {
const CustomUserAgent = document.getElementById("CustomUserAgent").value;
myRequest.SetRequestHeader("CustomUserAgent", CustomUserAgent);
}
function getCustomUserAgent() {
if (typeof addCustomUserAgentNode === "function") {
addCustomUserAgentNode();
}
let CustomUserAgent = "";
const customUserAgentNode = document.getElementById("CustomUserAgent");
if (customUserAgentNode) {
CustomUserAgent = document.getElementById("CustomUserAgent").value;
}
return CustomUserAgent;
}
最后在浏览器里调试一下