我尝试使用Angular' $ http进行HTTP GET调用。我已经写了这样的通用函数,
function doGETRequest(url, params) {
return $http({
method: 'GET',
url: baseURL + url,
headers: {
'Authorization': 'Bearer ' + access_token
},
params: params
});
}
我想创建一个这样的网址,
https://content.googleapis.com/drive/v2/about?fields=quotaBytesTotal%2CquotaBytesUsed%2CrootFolderId%2Cuser
但我不能为我的生活弄清楚查询参数部分。到目前为止,我尝试了以下内容:
doGETRequest('/about', {fields:'user,quotaBytesTotal,quotaBytesUsed,rootFolderId'})
doGETRequest('/about', {fields:['user','quotaBytesTotal','quotaBytesUsed','rootFolderId']})
doGETRequest('/about', {fields:encodeURIComponent('user,quotaBytesTotal,quotaBytesUsed,rootFolderId')})
它适用于第二个,但它将其解析为https://content.googleapis.com/drive/v2/about?fields=user&fields=quotaBytesTotal&fields=quotaBytesUsed&fields=rootFolderId
,Google只发送第一个查询的响应并忽略其余的(如预期的那样)。
所以问题是如何在查询参数中传递逗号分隔值?我是否必须手动编写URL编码值?这不是打败了一个params领域的目的吗?
答案 0 :(得分:0)
好吧,对于那些偶然发现同样问题的人,我找到了解决这个问题的两种方法。
首先,正如@ kiro112在评论中建议的那样,我直接在URL中写了params。由于$ http不会对网址进行编码,因此它无法正常工作。所以代码就像
doGETRequest('/about?fields='+encodeURIComponent("user,quotaBytesTotal,quotaBytesUsed,rootFolderId"))
我们必须摆脱params
方法中的doGetRequest()
部分。就我个人而言,我不喜欢这个,因为它的目的是让params参与$ http。
第二个方法覆盖默认$httpParamSerializer
并提供我们自己的。要做到这一点,doGetRequest()
方法必须像这样修改,
function doGETRequest(url, params) {
return $http({
method: 'GET',
url: baseURL + url,
headers: {
'Authorization': 'Bearer ' +access_token
},
params: params,
paramSerializer: function (value){
return Object.keys(value)+'='+encodeURIComponent(Object.values(value));
}
});
}
这里发生的是,我们不会对params进行角度编码。让我来告诉你为什么。根据{{3}},angular只会像这样进行编码,
{'foo': 'bar'}
会产生foo=bar
{'foo': Date.now()}
会产生foo=2015-04-01T09%3A50%3A49.262Z
(toISOString()
和Date对象的编码表示形式){'foo': ['bar', 'baz']}
会产生foo=bar&foo=baz
(每个数组元素的重复键){'foo': {'bar':'baz'}}
会生成foo=%7B%22bar%22%3A%22baz%22%7D"
(对象的字符串化和编码表示)虽然我们需要{'foo':['bar', 'baz']}
行中的某些内容,但会产生foo=bar%2Cbaz
。所以我们覆盖paramSerializer
并编写我们自己的序列化器。
就使用通用方法而言,第二种方法对我来说看起来更清晰。但是,我仍在寻找更好的选择。