API访问,哈希查询,可能与字符编码有关

API access, Hashing query, possibly related to character encoding

不可能为此提供可重现的示例,因为它与访问特定 API 有关 - 提前致歉。我正在尝试通过 R 访问爱丁堡边缘节日 API。documentation 表示以下内容:

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() 时它 returns "unknown"。我还尝试将 "save with encoding" 设置为 ASCII 的两个文件保存在 RStudio 中,并且我尝试使用 encoding = "ASCII".

获取身份验证

顺便说一句,当我将最后的 url 粘贴到浏览器中时,出现以下错误:

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

最后,我通过编辑jsonlite::fromJSON()函数解决了这个问题。即行

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

我改成了

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

然后我还必须用 jsonlite::: 指向内部函数。现在可以正常使用了。

这是服务器错误。应该理解为

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

匹配 application/json。请注意,与其修改 jsonlite,不如从服务器手动检索响应,然后然后将其提供给 jsonlite。

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