2016-12-14 8 views
1

Невозможно предоставить воспроизводимый пример для этого, поскольку он связан с доступом к определенному API - извинения заранее. Я пытаюсь получить доступ к эдинбург бахрома фестивалями API через Р. documentation говорит следующее:Доступ API, Хеширующий запрос, возможно, связанный с кодировкой символов

Authentication

An access key is required for all requests to the API and can be obtained by registration. This key, combined with the signature explained below, is required to get any access to the API. If you do not provide an access key, or provide an invalid key or signature, the server will return an HTTP 403 error.

Your secret token is used to calculate the correct signature for each API request and must never be disclosed. Once issued, it is never transmitted back or forward. The API server holds a copy of your secret token, which it uses to check that you have signed each request correctly.

You calculate the signature using the HMAC-SHA1 algorithm:

  • Build the full API request URL, including your access key but excluding the server domain - eg /events?festival=book&key=12345 . See the note below on URL encoding.

  • Calculate the hmac hash of the url using the sha1 algorithm and your secret token as the key.

  • Append the hex-encoded hash to your url as the signature parameter

URL encoding in queries

You should calculate the signature after URL-encoding any parameters - for example, to search for the title "Mrs Brown" you would first build the URL /events?title=Mrs%20Brown&key=12345 and then sign this string and append the signature.

Signature encoding

Some languages - notably C# - default to encoding hashes in UTF-16. Ensure your signature is encoded in plain ASCII hex or it will not be valid.

То, что я пытался до сих пор ниже:

library(digest) 
    library(jsonlite) 
    source("authentication.R") # credentials stored here 

создать строку запроса

query <- paste0('/events?festival=demofringe&size=20&from=1&key=', API_KEY) 

создать хешированный запрос

sig <- hmac(SECRET_SIGNING_KEY, query, algo="sha1") 

создать окончательный URL

url <- paste0('https://api.edinburghfestivalcity.com', query, '&signature=', sig) 

представить в API

results <- fromJSON(url) 

и я получаю ошибку:

Error in open.connection(con, "rb") : HTTP error 417. 

я не уверен, что подпись ASCII кодируются как в документации. Кто-нибудь знает, как отладить эту ситуацию? Я попробовал iconv(), чтобы попытаться преобразовать кодировку, и когда я вызываю Encoding() на объект символа, он возвращает "unknown". Я также попытался сохранить оба файла в RStudio с «сохранить с кодировкой», установленным в ASCII, и я попытался найти аутентификацию с помощью encoding = "ASCII".

Кстати, когда я вставляю конечный URL в браузере, я получаю следующее сообщение об ошибке:

Invalid Accept header value. ['application/json', 'application/json;ver=2.0'] are supported 
+0

Возможно, вы забыли между & = 1 и ключом? Это не должно быть 'query <- paste0 ('/ events? Festival = demofringe & size = 20 & from = 1 & key =', API_KEY)' –

+0

благодарим вас за обнаружение этой ошибки. Я исправил это, и теперь я получаю ошибку «Ошибка в open.connection (con,« rb »): ошибка HTTP 417.'. Я отредактирую вопрос, чтобы отразить это изменение. – roman

+0

Добро пожаловать. Мы все сделали эти опечатки. –

ответ

1

Это ошибка сервера. Он должен понимать, что

Accept: application/json, text/*, */* 

Соответствует application/json. Обратите внимание, что вместо изменения jsonlite, beter вручную извлекает форму ответа сервера, а затем передает его jsonlite.

library(httr) 
library(jsonlite) 
req <- GET(your_url, accept("application/json") 
json <- content(req, as = 'text') 
data <- fromJSON(json) 
+0

спасибо! отлично работает – roman

0

В конце концов, я решил эту проблему путем редактирования функции jsonlite::fromJSON(). а именно линия

curl::handle_setheaders(h, Accept = "application/json, text/*, */*") 

я изменил

curl::handle_setheaders(h, Accept = "application/json") 

тогда я также должен был указывать на внутренние функции с jsonlite:::. Теперь он работает нормально.