Twitter stream API - Erlang client



我在Erlang世界中很陌生,我正在尝试为Twitter Stream API编写一个客户端。我正在使用 httpc:request 发出 POST 请求,但我不断收到 401 错误,我发送请求的方式显然做错了......我拥有的看起来像这样:

fetch_data() ->
    Method = post,
    URL = "https://stream.twitter.com/1.1/statuses/filter.json",
    Headers = "Authorization: OAuth oauth_consumer_key="XXX", oauth_nonce="XXX", oauth_signature="XXX%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="XXX", oauth_token="XXX-XXXXX", oauth_version="1.0"",
    ContentType = "application/json",
    Body = "{"track":"keyword"}",
    HTTPOptions = [],
    Options = [],
    R = httpc:request(Method, {URL, Headers, ContentType, Body}, HTTPOptions, Options),
    R.

在这一点上,我相信签名没有问题,因为当尝试使用 curl 访问 API 时,相同的签名工作得很好。我猜我提出请求的方式存在一些问题。

我得到的响应是,按照上面演示的方式提出的请求是:

{ok,{{"HTTP/1.1",401,"Unauthorized"},
 [{"cache-control","must-revalidate,no-cache,no-store"},
  {"connection","close"},
  {"www-authenticate","Basic realm="Firehose""},
  {"content-length","1243"},
  {"content-type","text/html"}],
 "<html>n<head>n<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>n<title>Error 401 Unauthorized</title>n</head>n<body>n<h2>HTTP ERROR: 401</h2>n<p>Problem accessing '/1.1/statuses/filter.json'. Reason:n<pre>    Unauthorized</pre>n                                                n                                                n                                                n                                                n                                                n                                                n                                                n                                                n                                                n                                                n                                                n                                                n                                                n                                                n                                                n                                                n                                                n                                                n                                                n                                                n</body>n</html>n"}}

尝试使用 curl 时,我正在使用这个:

curl --request 'POST' 'https://stream.twitter.com/1.1/statuses/filter.json' --data 'track=keyword' --header 'Authorization: OAuth oauth_consumer_key="XXX", oauth_nonce="XXX", oauth_signature="XXX%3D", oauth_signature_method="HMAC-SHA1", oauth_timestamp="XXX", oauth_token="XXX-XXXX", oauth_version="1.0"' --verbose

我把事件搞得很顺利。

任何这方面的帮助将不胜感激,Erlang 是新的,我已经在这个问题上拔头发了很长一段时间。

您的代码存在几个问题

    在 Erlang 中,您将参数编码为
  1. JSON 主体,而使用 curl 中,您将参数编码为表单数据 (application/x-www-form-urlencoded (。Twitter API期待后者。事实上,你会得到一个401,因为OAuth签名不匹配,因为你在计算中包含track=keyword参数,而Twitter的服务器在没有JSON正文的情况下计算它,因为它应该按照OAuth RFC。

  2. 您正在使用带有默认选项的httpc。这不适用于流式处理 API,因为流式处理永远不会结束。您需要在结果到达时对其进行处理。为此,您需要将{sync, false}选项传递给 httpc .另请参阅streamreceiver选项。

最终,虽然httpc最初可以访问Twitter流媒体API,但它对你需要围绕它开发的代码几乎没有价值,以便从Twitter API进行流式传输。根据您的需求,您可能希望将其替换为直接构建在ssl上的简单客户端,特别是考虑到它可以解码HTTP数据包(留给您的是HTTP块编码(。

例如,如果您的关键字很少见,则可能会因httpc .此外,更新关键字列表或代码可能会更容易,而不会停机而无需httpc

直接基于 ssl 的流客户端可以作为gen_server实现(如果您不遵循 OTP 原则,则可以实现一个简单的过程(,甚至可以更好地实现重新连接策略gen_fsm。您可以按以下步骤操作:

    使用 ssl:connect/3,4 进行连接,指定您希望套接字
  • 使用 {packet, http_bin} 解码 HTTP 数据包,并且您希望将套接字配置为被动模式 {active, false}

  • 使用 ssl:send/2,3 发送 HTTP 请求数据包(最好作为 iolist,带有二进制文件(。它应该分布在用CRLF(rn(分隔的几行上,首先是查询行(GET /1.1/statuses/filter.json?... HTTP/1.1(,然后是包括OAuth标头的标头。确保也包括Host: stream.twitter.com。以空行结尾。

  • 接收 HTTP 响应。您可以使用循环来实现这一点(因为套接字处于被动模式(,调用ssl:recv/2,3直到您获得http_eoh(标头末尾(。通过查看Transfer-Encoding响应标头,记下服务器是否会向您发送分块数据。

  • 使用 ssl:setopts/2 在主动模式下配置套接字,并指定您希望数据包为原始数据包,数据为二进制格式。事实上,如果数据被分块,您可以继续在被动模式下使用套接字。您还可以逐行获取数据或以字符串形式获取数据。这是一个品味问题:raw 是最安全的选择,逐行要求您检查缓冲区大小以防止截断长 JSON 编码的推文。

  • 从 Twitter 接收数据作为发送到您的进程的消息,可以使用 receive(简单流程(或handle_info处理程序(如果您使用 gen_server 实现了这一点(。如果数据被分块,您将首先收到块大小,然后是推文和块的末尾(参见RFC 2616(。准备好让推文分布在几个块上(即维护某种缓冲区(。这里最好的是在此过程中进行最少的解码,并将推文发送到另一个进程,可能采用二进制格式。

您还应该处理错误和 Twitter 关闭的套接字。确保你遵循 Twitter 的重新连接指南。

相关内容

  • 没有找到相关文章

最新更新