Twitter流API-Erlang客户端

Twitter流API-Erlang客户端,twitter,stream,erlang,client,Twitter,Stream,Erlang,Client,我是Erlang世界的新手,我正在尝试为Twitter流API编写一个客户端。我正在使用httpc:request发出POST请求,我经常收到401错误,我显然在发送请求的方式上做了一些错误。。。我所拥有的是这样的: fetch_data() -> Method = post, URL = "https://stream.twitter.com/1.1/statuses/filter.json", Headers = "Authorization: OAuth oa

我是Erlang世界的新手,我正在尝试为Twitter流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"}}
我对这些事件都很了解

如果您在这方面有任何帮助,我将不胜感激,因为这是Erlang的新产品,我已经花了很长时间来研究这一点。

您的代码有几个问题:

在Erlang中,您将参数编码为JSON主体,而在curl中,您将参数编码为form data application/x-www-form-urlencoded。twitterapi期望后者。事实上,您得到了401,因为OAuth签名不匹配,因为您在计算中包含了track=keyword参数,而Twitter的服务器在计算时没有JSON主体,这是应该的

您正在使用默认选项。这不适用于流式API,因为流永远不会结束。您需要在结果到达时对其进行处理。为此,需要将{sync,false}选项传递给。另请参见流和接收器选项

最终,虽然httpc最初可以访问Twitter流媒体API,但它对您需要围绕它开发的从Twitter流媒体API流媒体的代码没有什么价值。根据您的需要,您可能希望将其替换为直接构建在其上的简单客户端,特别是考虑到它可以解码HTTP数据包,剩下的就是HTTP块编码

例如,如果关键字很少,您可能会从httpc获得一个超时。此外,在没有httpc的情况下,更新关键字列表或代码可能更容易,而且不会停机

如果您不遵循OTP原则,或者更好地使用gen_fsm来实施重新连接策略,那么直接基于的流式客户端可以作为gen_服务器或简单流程来实现。你可以按以下步骤进行:

使用以下命令进行连接:指定希望套接字解码HTTP数据包,并且希望在被动模式下配置套接字

发送HTTP请求数据包最好是作为iolist,并带有二进制文件。它应该分布在几行上,用CRLF分隔\r\n,第一行是查询行GET/1.1/statuses/filter.json?。。。HTTP/1.1,然后是包含OAuth标头的标头。确保还包括主机:stream.twitter.com。以空行结束

接收HTTP响应。由于套接字处于被动模式,因此可以通过循环实现这一点,直到获得http_eoh end of Header为止。通过查看传输编码响应头,记下服务器是否向您发送分块数据

在活动模式下使用配置套接字,并指定要将数据包作为原始数据和二进制格式的数据。事实上,如果数据被分块,您可以继续在被动模式下使用套接字。您还可以逐行获取数据或以字符串形式获取数据。这是一个品味问题:raw是最安全的赌注,逐行检查缓冲区大小以防止长的JSON编码tweet被截断

使用Receive simple process(接收简单流程)或handle_info handler(如果您使用gen_服务器实现此功能),从Twitter接收数据,并将其作为消息发送到您的流程。如果数据是分块的,你首先会收到分块大小,然后是tweets和分块的结尾。准备好让推特传播到几个区块上,即保持某种缓冲。这里最好的方法是在此过程中进行最小解码,并将tweet发送到另一个过程,可能是二进制格式

您还应该处理Twitter关闭的错误和套接字。请确保遵守。

您的代码有几个问题:

在Erlang中,您将参数编码为JSON主体,而在curl中,您将参数编码为form data application/x-www-form-urlencoded。twitterapi期望后者。事实上,您得到了401,因为OAuth签名不匹配,因为您在计算中包含了track=keyword参数,而Twitter的服务器在计算时没有JSON主体,这是应该的

您正在使用默认选项。这不适用于流式API,因为流永远不会结束。您需要在结果到达时对其进行处理。为此,需要将{sync,false}选项传递给。另请参见流和接收器选项

最终,虽然httpc最初可以访问Twitter流媒体API,但它对您需要围绕它开发的从Twitter流媒体API流媒体的代码没有什么价值。根据您的需要,您可能希望将其替换为直接构建在其上的简单客户端,尤其是考虑到它可以 编码HTTP数据包剩下的是HTTP数据块编码

例如,如果关键字很少,您可能会从httpc获得一个超时。此外,在没有httpc的情况下,更新关键字列表或代码可能更容易,而且不会停机

如果您不遵循OTP原则,或者更好地使用gen_fsm来实施重新连接策略,那么直接基于的流式客户端可以作为gen_服务器或简单流程来实现。你可以按以下步骤进行:

使用以下命令进行连接:指定希望套接字解码HTTP数据包,并且希望在被动模式下配置套接字

发送HTTP请求数据包最好是作为iolist,并带有二进制文件。它应该分布在几行上,用CRLF分隔\r\n,第一行是查询行GET/1.1/statuses/filter.json?。。。HTTP/1.1,然后是包含OAuth标头的标头。确保还包括主机:stream.twitter.com。以空行结束

接收HTTP响应。由于套接字处于被动模式,因此可以通过循环实现这一点,直到获得http_eoh end of Header为止。通过查看传输编码响应头,记下服务器是否向您发送分块数据

在活动模式下使用配置套接字,并指定要将数据包作为原始数据和二进制格式的数据。事实上,如果数据被分块,您可以继续在被动模式下使用套接字。您还可以逐行获取数据或以字符串形式获取数据。这是一个品味问题:raw是最安全的赌注,逐行检查缓冲区大小以防止长的JSON编码tweet被截断

使用Receive simple process(接收简单流程)或handle_info handler(如果您使用gen_服务器实现此功能),从Twitter接收数据,并将其作为消息发送到您的流程。如果数据是分块的,你首先会收到分块大小,然后是tweets和分块的结尾。准备好让推特传播到几个区块上,即保持某种缓冲。这里最好的方法是在此过程中进行最小解码,并将tweet发送到另一个过程,可能是二进制格式


您还应该处理Twitter关闭的错误和套接字。确保您遵循。

我使用oauth:get/6连接到状态/sample的流,您可以使用oauth:post连接到过滤流。我使用oauth:get/6连接到状态/sample的流,您可以使用oauth:post连接到过滤流。我已经成功地使用erlang oauth库连接到twitter的流,erlang oauth似乎使用了httpc:。你能解释一下为什么你说httpc不能工作吗?你是对的,httpc将在异步模式下工作。我相应地更新了答案。@PaulGuyot谢谢你的帮助。我现在已经成功地打开了stream.twitter.com的一个套接字,看起来这个部分工作得很好。但是,我在以正确的方式通过套接字发送请求时遇到了问题。我尝试过ssl:sendSSLSocket,POST/1.1/statuses/filter.json?oauth_consumer_key=XXX…,ssl:sendSSLSocket,POST%2F1.1%2Fstatuses%2Ffilter.json%26oauth_consumer_key%3DXXX和其他格式,但我似乎做不正确。如何通过套接字发送头文件?谢谢你的帮助@阿康苏,谢谢你的参与。您是否有一个关于如何使用erlang oauth实现这一点的简短示例?我似乎找不到一个很好的例子,我只能看到关于如何完成OAuth部分的例子,但看不到关于如何发出请求的例子。Thanks@PaulGuyot您能给我指出一个在流式客户端中使用ssl的示例代码吗?我还在构建一个twitter流消费者,对我来说,httpc似乎没有什么价值。我已经成功地使用erlang oauth库连接到twitter流,而erlang oauth似乎使用了httpc:。你能解释一下为什么你说httpc不能工作吗?你是对的,httpc将在异步模式下工作。我相应地更新了答案。@PaulGuyot谢谢你的帮助。我现在已经成功地打开了stream.twitter.com的一个套接字,看起来这个部分工作得很好。但是,我在以正确的方式通过套接字发送请求时遇到了问题。我尝试过ssl:sendSSLSocket,POST/1.1/statuses/filter.json?oauth_consumer_key=XXX…,ssl:sendSSLSocket,POST%2F1.1%2Fstatuses%2Ffilter.json%26oauth_consumer_key%3DXXX和其他格式,但我似乎做不正确。如何通过套接字发送头文件?谢谢你的帮助@阿康苏,谢谢你的参与。您是否有一个关于如何使用erlang oauth实现这一点的简短示例?我似乎找不到一个很好的例子,我只能看到关于如何完成OAuth部分的例子,但看不到关于如何发出请求的例子。Thanks@PaulGuyot您能给我指出一个在流式客户端中使用ssl的示例代码吗?我还建立了一个twitter流消费者,对我来说 httpc似乎也没有增加多少价值。
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