在TVML应用程序中为XMLHttpRequest更改用户代理 [英] Change User-Agent for XMLHttpRequest in TVML app

查看:128
本文介绍了在TVML应用程序中为XMLHttpRequest更改用户代理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用TVMLKit开发Apple TV应用程序.我的应用程序的JavaScript代码尝试使用XMLHttpRequest向服务器发送HTTP请求.服务器期望使用特定的用户代理,因此我尝试了以下操作:

I'm working on an Apple TV app using TVMLKit. My app's JavaScript code tries to send an HTTP request to a server using XMLHttpRequest. The server is expecting a specific user agent, so I tried this:

var request = new XMLHttpRequest();
request.open("GET", url, true);
request.setRequestHeader("User-Agent", "MyApp");
request.send();

服务器收到另一个User-Agent标头:

The server receives a different User-Agent header:

User-Agent: <Projectname>/1 CFNetwork/758.1.6 Darwin/15.0.0

如果我将标题名称更改为其他名称,它将显示在请求标题中.我猜苹果在发送请求之前正在替换User-Agent字段.有办法防止这种情况吗?

If I change the header name to something different, it shows up in the request headers. I guess Apple is replacing the User-Agent field right before sending the request. Is there a way to prevent this?

推荐答案

花了两天的时间研究这个问题之后,我才提出了创建本机GETPOST方法的解决方案,并迅速将其暴露给javascript.这不是最佳解决方案,但我仍然想分享.也许可以帮助某人.

After spending two days on investigating this question I've came to solution with creating native GET and POST methods in swift end exposing them to javascript. This isn't best solution but still I want to share it. Maybe it could help someone.

这里是如何工作的

首先,我们需要安装 Alamofire 库.我们将使用它来创建请求.

First we need to install Alamofire library. We will use it for creating requests.

github上的自述文件包含安装它所需的所有说明

Readme on github has all instructions you need to install it

安装Alamofire之后,我们需要将其导入AppDelegate.swift

After installing Alamofire we need to import it in AppDelegate.swift

import Alamofire

然后,我们需要在应用控制器(AppDelegate.swift)中创建函数,以将方法公开给javascript

Then we need to create function in app controller (AppDelegate.swift) that will expose methods to 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");
}

AppDelegate.swift的完整代码,您可以找到

Full code of AppDelegate.swift you can find here

都准备好了!现在,我们可以从javascript中访问nativeGETnativePOST函数.

All set! Now we have access to nativeGET and nativePOST functions from javascript.

最后一件事是发出请求并检索响应.我还不了解如何快速执行回调执行,因此我使用了jsonp方法,该方法使用运行时生成的函数并将其名称传递给本机函数.

The last thing is to make requests and retrieve responses. I haven't understand how to make callback executions in swift so I've used jsonp approach using runtime generated functions and passing their names to native functions.

这是它在javascript中的外观

Here how it looks in 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);
    });
}

上面的代码是用ES6编写的,您需要在TVJS应用程序中包含Promise polifill.

The code above is written in ES6 and you'll need to include Promise polifill in your TVJS app.

现在我们可以使用所需的任何标头发出GETPOST请求

Now we can make GET and POST requests applying any header we need

post('http://example.com/', {
    login: 'xxx', 
    password: 'yyy'
}, {
    'User-Agent': 'My custom User-Agent'
})

这篇关于在TVML应用程序中为XMLHttpRequest更改用户代理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆