Я пытаюсь выполнить вызов HTTP GET с помощью Angular $ http. Я написал такую общую функцию,
function doGETRequest(url, params) {
return $http({
method: 'GET',
url: baseURL + url,
headers: {
'Authorization': 'Bearer ' + access_token
},
params: params
});
}
Я хочу создать такой URL-адрес: 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-кодированные значения? Разве это не преследовало цель иметь поле параметров?
Хорошо, для тех, кто наткнулся на ту же проблему, что и я, я нашел два способа решения этого.
Во-первых, как предложил @kiro112 в комментариях, я пишу параметры непосредственно в URL-адресе. Поскольку $ http не кодирует URL-адрес, он будет работать. Таким образом, код будет чем-то вроде
doGETRequest('/about?fields='+encodeURIComponent("user,quotaBytesTotal,quotaBytesUsed,rootFolderId"))
и нам придется избавиться от части params
в doGetRequest()
. Лично мне не нравится этот, поскольку он превосходит цель иметь параметры в $ 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));
}
});
}
Что здесь происходит, мы не позволяем угловому кодированию параметров. Позвольте мне рассказать вам, почему. В соответствии с документами здесь угловые кодируют только так,
{'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
и пишем наш собственный сериализатор.
Второй подход выглядит намного более чистым для меня, поскольку речь идет об использовании общих методов. Тем не менее, я все еще смотрю на лучший вариант.