项目特殊需求,需要在OC的iOS项目中的http网络请求报表中,手动加上对应的user-agent
之前代码是:
let url = NSURL(string: RURL + “src/report/charts.html”); self.jsContext.evaluateScript(try? String(contentsOf: url! as URL, encoding: String.Encoding.utf8)) |
现在想要想办法去给js去加载的网页加上user-agent
ios oc jsContext.evaluateScript add header
JSContext – JavaScriptCore | Apple Developer Documentation
没找到可以加header的地方
ios – How to call JavaScript Function in objective C – Stack Overflow
感觉应该是去找webview,看看哪里可以加header
iOS中UIWebView与WKWebView、JavaScript与OC交互、Cookie管理看我就够(上)_IOS开发_互联网开发技术网_传播最新的编程技术_php361.com
ios oc UIWebView add header
objective c – UIWebView – shouldStartLoadWithRequest – NSMutableURLRequest – Stack Overflow
ios – How to set http header for all requests being loaded in a UIWebView? – Stack Overflow
ios uiwebview custom user agent
cocoa touch – Change User Agent in UIWebView (iPhone SDK) – Stack Overflow
ios – How can I set the “User-Agent” header of a UIWebView in Swift – Stack Overflow
去试试:
UserDefaults.standard.register(defaults: [“UserAgent”: “fle”])
问题依旧。
iOS中修改WebView默认的User Agent – 阿P的博客
iOS: 自定义 UIWebView 和 WKWebView 的 UserAgent | veryitman
用了:
// let request = NSURLRequest(url: url! as URL) let request = NSMutableURLRequest(url: url! as URL) // request.setValue(“User-Agent”, forHTTPHeaderField: “fle”) // request.setValue(“UserAgent”, forHTTPHeaderField: “fle”) request.setValue(“fle”, forHTTPHeaderField: “User-Agent”) self.webView.loadRequest(request as URLRequest) |
虽然实际上应该是生效了,但是最后在
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool{
中得到的还是默认的user agent:
// let reqUserAgent = request.value(forHTTPHeaderField: “UserAgent”) let reqUserAgent = request.value(forHTTPHeaderField: “User-Agent”) gLog.debug(“request.url=\(request.url), request.allHTTPHeaderFields=\(request.allHTTPHeaderFields),request.httpMethod=\(request.httpMethod),reqUserAgent=\(reqUserAgent)”) //request.allHTTPHeaderFields=Optional([“Accept”: “text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8”, “User-Agent”: “Mozilla/5.0 (iPhone; CPU iPhone OS 11_1 like Mac OS X) AppleWebKit/604.3.1 (KHTML, like Gecko) Mobile/15B5066e”, “Upgrade-Insecure-Requests”: “1”]),request.httpMethod=Optional(“GET”),reqUserAgent=Optional(“Mozilla/5.0 (iPhone; CPU iPhone OS 11_1 like Mac OS X) AppleWebKit/604.3.1 (KHTML, like Gecko) Mobile/15B5066e”) let appName = webView.stringByEvaluatingJavaScript(from: “navigator.appName”) let naviUserAgent = webView.stringByEvaluatingJavaScript(from: “navigator.userAgent”) gLog.debug(“appName=\(appName ?? “”), naviUserAgent=\(naviUserAgent ?? “”)”) //appName=Netscape, curUserAgent=Mozilla/5.0 (iPhone; CPU iPhone OS 11_1 like Mac OS X) AppleWebKit/604.3.1 (KHTML, like Gecko) Mobile/15B5066e |
而换上:
UserDefaults.standard.register(defaults: [“UserAgent”: “fle”]) // UserDefaults.standard.register(defaults: [“User-Agent”: “fle”]) |
倒的确可以获得user agent是fle了:
webView(_:shouldStartLoadWith:navigationType:) > request.url=Optional(http://x.x.x.x/skrDev/src/report/charts.html), request.allHTTPHeaderFields=Optional([“Accept”: “text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8”, “User-Agent”: “fle”, “Upgrade-Insecure-Requests”: “1”]),request.httpMethod=Optional(“GET”),reqUserAgent=Optional(“fle”) |
但是最后在:
jsContext.evaluateScript执行url后,还是出错:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)
相关代码:
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool{ // let reqUserAgent = request.value(forHTTPHeaderField: “UserAgent”) let reqUserAgent = request.value(forHTTPHeaderField: “User-Agent”) gLog.debug(“request.url=\(request.url), request.allHTTPHeaderFields=\(request.allHTTPHeaderFields),request.httpMethod=\(request.httpMethod),reqUserAgent=\(reqUserAgent)”) //request.allHTTPHeaderFields=Optional([“Accept”: “text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8”, “User-Agent”: “Mozilla/5.0 (iPhone; CPU iPhone OS 11_1 like Mac OS X) AppleWebKit/604.3.1 (KHTML, like Gecko) Mobile/15B5066e”, “Upgrade-Insecure-Requests”: “1”]),request.httpMethod=Optional(“GET”),reqUserAgent=Optional(“Mozilla/5.0 (iPhone; CPU iPhone OS 11_1 like Mac OS X) AppleWebKit/604.3.1 (KHTML, like Gecko) Mobile/15B5066e”) let appName = webView.stringByEvaluatingJavaScript(from: “navigator.appName”) let naviUserAgent = webView.stringByEvaluatingJavaScript(from: “navigator.userAgent”) gLog.debug(“appName=\(appName ?? “”), naviUserAgent=\(naviUserAgent ?? “”)”) //appName=Netscape, curUserAgent=Mozilla/5.0 (iPhone; CPU iPhone OS 11_1 like Mac OS X) AppleWebKit/604.3.1 (KHTML, like Gecko) Mobile/15B5066e self.jsContext = webView.value(forKeyPath: “documentView.webView.mainFrame.javaScriptContext”) as! JSContext let model = AppHost() model.controller = self model.jsContext = self.jsContext // 这一步是将SwiftJavaScriptModel模型注入到JS中,在JS就可以通过WebViewJavascriptBridge调用我们暴露的方法了。 self.jsContext.setObject(model, forKeyedSubscript: “AppHost” as (NSCopying & NSObjectProtocol)!) // 注册到网络Html页面 请设置允许Http请求 //let url = “http://101.200.55.24/src/report/charts.html”;; let url = NSURL(string: RURL + “src/report/charts.html”); self.jsContext.evaluateScript(try? String(contentsOf: url! as URL, encoding: String.Encoding.utf8)) return true } |
所以此处问题变成:
如何在UIWebView,在为了和JS通讯,而用的documentView.webView.mainFrame.javaScriptContext的jsContext和evaluateScript中,传递对应的自定义的user-agent
即,希望在
self.jsContext.evaluateScript(try? String(contentsOf: url! as URL, encoding: String.Encoding.utf8))
之前,能想办法加上自定义的header
此处,也想要去直接在shouldStartLoadWith中设置webView.request,结果其是只读的,没法setValue。
ios javaScriptContext custom header
iOS中UIWebView与WKWebView、JavaScript与OC交互、Cookie管理看我就够(上) | Dark Angel
documentView.webView.mainFrame.javaScriptContext user-agent
UIWebView shouldStartLoadWith custom user-agent
ios – UIWebView User-Agent is not properly set for custom value – Stack Overflow
ios – Change User-Agent – Stack Overflow
UIWebView SwiftJavaScriptDelegate custom user-agent
UIWebView Swift JavaScript Delegate custom user-agent
ios – How can I set the “User-Agent” header of a UIWebView in Swift – Stack Overflow
现在问题是:
虽然给了webview设置了user-agent
但是当把documentView.webView.mainFrame.javaScriptContext设置给了JSContext后,
JSContext去通过evaluateScript执行url,打开url的,所以没了之前自定义的user-agent
所以此处需要去把JSContext的evaluateScrip中,添加自定义的user-agent
ios javaScriptContext custom user-agent
ios JSContext custom user-agent
iOS UIWebView 修改user-agent – 月若无涯的专栏 – CSDN博客
ios evaluateScript add user-agent
JSContext evaluateScript add user-agent
How to set user-agent in python-webkit – Stack Overflow
Objective-C/Swift与JavaScript交互 | 孟跃平的技术博客
JSContext open url add header
JSContext evaluateScript url add header
javascript – window.open with headers – Stack Overflow
JSContext evaluateScript url
evaluateScript(_:) – JSContext | Apple Developer Documentation
evaluateScript(_:withSourceURL:) – JSContext | Apple Developer Documentation
iOS开发 – Swift使用JavaScriptCore与JS交互 – 马燕龙个人博客
JSContext evaluateScript withSourceURL
JSContext evaluateScript user-agent
JSContext evaluateScript change headers
试试:
self.jsContext.evaluateScript(“navigator.userAgent = \”fle\””)
不行。
iOS JSContext evaluateScript url
JavaScriptCore和Objective-C – 简书
去和服务器后台配合调试,发现iOS中通过:
self.jsContext.evaluateScript
去打开url时,默认的user-agent是:
“GET /skrDev/src/report/charts.html HTTP/1.1” 403 169 “-” “SRTDev/20170825 CFNetwork/811.4.18 Darwin/16.7.0” “-“ |
去搜:
UIWebView default user-agent
ios UIWebView default user-agent
ios UIWebView JSContext default user-agent
ios JSContext default user-agent
但是还是找不到,当UIWebView中,通过JSContext的evaluateScript打开url时,默认的user-agent是什么。
算了。
【总结】
此处,Xcode9,swift 3中,可以通过:
1.去全局的设置固定的User-Agent的值:
UserDefaults.standard.register(defaults: [“UserAgent”: “fle”])
注意:key是UserAgent,而不是User-Agent
2.单个UIWebView的实例的User-Agent:
同时可以对于单个UIWebView的示例,可以通过:
let request = NSMutableURLRequest(url: url! as URL)
request.setValue(“fle”, forHTTPHeaderField: “User-Agent”)
self.webView.loadRequest(request as URLRequest)
去设置User-Agent的值。
3.无法修改JSContext的evaluateScript打开的url时的User-Agent
但是对于:shouldStartLoadWith中的UIWebView获得的JSContext的evaluateScript去打开url的话:
则此处默认的User-Agent是
SRTDev/20170825 CFNetwork/811.4.18 Darwin/16.7.0
看起来是:
App 名称/时间 网络库名称/版本? 内核/版本?
而找不到办法,无法手动设置此时的User-Agent的。
【后记】
后来又遇到其他的问题:
在iOS模拟器中测试时,是可以正常访问后台的其他web页面的
但是在真机中测试,结果却无法正常访问内容了。
只能显示出异常的页面,无法获得内部用户数据,只有html页面内容。
看起来是:
缺少了token,所以获取不到用户的数据。
然后去让后台配合测试,发现真机中,(内部Webview去)访问其他web页面时,user-agent还是普通的apple的值,所以继续去改为:
给app初始化的部分就去全局添加
func resetGlobalValues(){ gLog.info(“”) UserDefaults.standard.register(defaults: [“UserAgent”: APP_USER_AGENT]) } |
然后后续的webview去访问(经过后台配置用fiddler抓包可以确认)user-agent都是希望的SRT了:
OPTIONS /v1/skr/report/daily/board HTTP/1.1Host: 123.206.101.36:9090Connection: keep-aliveAccept-Language: zh-cnAccess-Control-Request-Method: GETAccept-Encoding: gzip, deflateAccept: */*Origin: http://123.206.101.36Content-Length: 0Access-Control-Request-Headers: authorizationConnection: keep-aliveUser-Agent: SRTReferer: http://x.x.x.x/skrDev/src/report/charts.html |
然后页面才能正常显示。
附上:
其他两种情况:
(1)iOS中用Alamofire网络库去调用api接口时:
User-Agent:是SRTDev/1.1.0 (com.csvw.fleDev; build:20171017; iOS 11.0.3) Alamofire/4.5.1
GET /v1/skr/task/common/organization?pid=SKR04-01-01 HTTP/1.1 Host: x.x.x.x:9090 Content-Type: application/json; charset=UTF-8 Connection: keep-alive Connection: keep-alive Accept: */* User-Agent: SRTDev/1.1.0 (com.csvw.fleDev; build:20171017; iOS 11.0.3) Alamofire/4.5.1 Accept-Language: zh-Hans-CN;q=1.0, en-CN;q=0.9, zh-Hant-CN;q=0.8 Authorization: Bearer 662ijrcmmhfn9hmpnjjr4je34t Accept-Encoding: gzip;q=1.0, compress;q=0.5 |
以及:
(2)webview中JSContext(调用evaluateScript)打开url时:
User-Agent是SRTDev/20171017 CFNetwork/887 Darwin/17.0.0
GET /skrDev/src/report/retail.html?t=1508231105061 HTTP/1.1 Host: 123.206.101.36 Connection: keep-alive Accept: */* User-Agent: SRTDev/20171017 CFNetwork/887 Darwin/17.0.0 Accept-Language: zh-cn Accept-Encoding: gzip, deflate Connection: keep-alive |
【后记2】
后来,为了配合后台改个bug:
后台的html页面是根据当前的user-agent判断是否是iPhone Plus机型而决定是否将报表显示高度减去顶部导航栏,
但是前面的做法,把正常的移动端的user-agent信息去掉了,(变成了”SRT”了)所以无法检测出iPhone机型了。
所以参考:
ios – How can I set the “User-Agent” header of a UIWebView in Swift – Stack Overflow
UIWebView 和 WKWebView 修改自定义UserAgent – Swift迷
再去改为:
在原有User-agent值的基础上,额外追加此处需要的”SRT”
func customAppUserAgent(){ // UserDefaults.standard.register(defaults: [“UserAgent”: APP_USER_AGENT]) let webView = UIWebView(frame: CGRect.zero) let curUserAgent = webView.stringByEvaluatingJavaScript(from: “navigator.userAgent”)! //”Mozilla/5.0 (iPhone; CPU iPhone OS 11_1 like Mac OS X) AppleWebKit/604.3.1 (KHTML, like Gecko) Mobile/15B5066e” UserDefaults.standard.register(defaults: [“UserAgent”: curUserAgent + ” \(APP_USER_AGENT)”]) UserDefaults.standard.synchronize() } |
即可实现:
即可以识别user-agent中是否有特殊的我们此处自己定义的SRT
又可以保留之前已有的user-agent-》从而可以判断出iPhone的机型-》页面可以额外去做适配工作了。