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

时间:2016-12-14 11:51:23

标签: r hash character-encoding rcurl digest-authentication

由于它与访问特定API有关,因此不可能为此提供可重现的示例 - 提前道歉。我试图通过R访问爱丁堡边缘节日API。documentation说如下:

  

验证

     

对API的所有请求都需要访问密钥,并且可以   通过注册获得。这个键,结合签名   如下所述,需要获得对API的任何访问权限。如果你这样做   不提供访问密钥,或提供无效密钥或签名,   服务器将返回HTTP 403错误。

     

您的秘密令牌用于计算每个签名的正确签名   API请求,绝不能透露。一旦发布,它永远不会   向后或向前传播。 API服务器保存您的副本   秘密令牌,用于检查您是否已签署每个请求   正确。

     

您使用HMAC-SHA1算法计算签名:

     
      
  • 构建完整的API请求网址,包括您的访问密钥,但不包括服务器域 - 例如/events?festival=book&key=12345。看到   关于URL编码的说明。

  •   
  • 使用sha1算法和您的秘密令牌作为密钥计算网址的hmac哈希值。

  •   
  • 将十六进制编码的哈希值附加到您的网址作为签名参数

  •   
     

查询中的网址编码

     

您应该在对任何参数进行网址编码后计算签名 -   例如,要搜索标题“布朗夫人”,你首先要建立   网址/events?title=Mrs%20Brown&key=12345,然后签署此字符串   并附上签名。

     

签名编码

     

某些语言 - 尤其是C# - 默认使用UTF-16编码哈希值。   确保您的签名以纯ASCII十六进制编码,否则不会   有效的。

到目前为止我所尝试的内容如下:

    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 <- 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中,并将“save with encoding”设置为ASCII,我尝试使用encoding = "ASCII"获取身份验证。

顺便提一下,当我将最终的网址粘贴到浏览器中时,我收到以下错误:

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

2 个答案:

答案 0 :(得分:1)

这是服务器错误。它应该明白

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)

答案 1 :(得分:0)

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

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

我改为

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

然后我还必须指向jsonlite:::的内部函数。现在它工作正常。