我正在使用 TVMLKit 开发 Apple TV 应用程序。我的应用程序的 JavaScript 代码尝试使用 XMLHttpRequest
向服务器发送 HTTP 请求。服务器需要一个特定的用户代理,所以我尝试了这个:
var request = new XMLHttpRequest();
request.open("GET", url, true);
request.setRequestHeader("User-Agent", "MyApp");
request.send();
服务器收到不同的 User-Agent header :
User-Agent: <Projectname>/1 CFNetwork/758.1.6 Darwin/15.0.0
如果我将 header 名称更改为不同的名称,它会显示在请求 header 中。我猜 Apple 正在发送请求之前替换 User-Agent 字段。有办法避免这种情况吗?
最佳答案
在花了两天时间调查这个问题后,我找到了解决方案,方法是快速创建 native GET
和 POST
方法,最终将它们暴露给 javascript。这不是最佳解决方案,但我仍然想分享它。也许它可以帮助某人。
它是如何工作的
首先我们需要安装Alamofire图书馆。我们将使用它来创建请求。
Readme on github has all instructions you need to install it
安装Alamofire后我们需要将它导入AppDelegate.swift
import Alamofire
然后我们需要在应用程序 Controller (AppDelegate.swift
) 中创建函数,它将方法暴露给 javascript
func appController(appController: TVApplicationController, evaluateAppJavaScriptInContext jsContext: JSContext)
{
let requests = [String : AnyObject]()
let get: @convention(block) (String, String, [String : String]?) -> Void = { (cId:String, url:String, headers:[String : String]?) in
Alamofire.request(.GET, url, headers: headers)
.responseString { response in
jsContext.evaluateScript("requests." + cId + "(" + response.result.value! + ")")
}
}
let post: @convention(block) (String, String, [String : AnyObject]?, [String : String]?) -> Void = { (cId:String, url:String, parameters:[String : AnyObject]?, headers:[String : String]?) in
Alamofire.request(.POST, url, parameters: parameters, headers: headers)
.responseString { response in
jsContext.evaluateScript("requests." + cId + "(" + response.result.value! + ")")
}
}
jsContext.setObject(requests, forKeyedSubscript: "requests");
jsContext.setObject(unsafeBitCast(get, AnyObject.self), forKeyedSubscript: "nativeGET");
jsContext.setObject(unsafeBitCast(post, AnyObject.self), forKeyedSubscript: "nativePOST");
}
Full code of
AppDelegate.swift
you can find here
一切就绪!现在我们可以从 javascript 访问 nativeGET
和 nativePOST
函数。
最后一件事是发出请求和检索响应。我不明白如何在 swift 中执行回调,所以我使用了 jsonp
方法,使用运行时生成的函数并将它们的名称传递给 native 函数。
这是它在 javascript 中的样子
export function get(url, headers = {}) {
return new Promise((resolve) => {
const cId = `get${Date.now()}`;
requests[cId] = response => {
delete requests[cId];
resolve(response);
}
nativeGET(cId, url, headers);
});
}
export function post(url, parameters = {}, headers = {}) {
return new Promise((resolve) => {
const cId = `post${Date.now()}`;
requests[cId] = response => {
delete requests[cId];
resolve(response);
}
nativePOST(cId, url, parameters, headers);
});
}
The code above is written in ES6 and you'll need to include
Promise
polifill in your TVJS app.
现在我们可以发出 GET
和 POST
请求,应用我们需要的任何 header
post('http://example.com/', {
login: 'xxx',
password: 'yyy'
}, {
'User-Agent': 'My custom User-Agent'
})
关于tvos - 在 TVML 应用程序中更改 XMLHttpRequest 的用户代理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33701867/