1

私は 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 の新機能であり、私はかなり長い間この問題について頭を悩ませてきました。

4

1 に答える 1

5

コードにはいくつかの問題があります

  1. Erlang ではパラメーターを JSON 本体としてエンコードcurlしますが、 ではパラメーターをフォーム データ ( application/x-www-form-urlencoded) としてエンコードします。Twitter API は後者を想定しています。実際、 OAuth RFCtrack=keywordに従って、Twitter のサーバーが JSON 本文なしで計算するときにパラメーターを計算に含めたため、OAuth 署名が一致しないため、401 が返されます。

  2. httpcデフォルトのオプションで使用しています。ストリームが終了しないため、これはストリーミング API では機能しません。結果が到着したら、結果を処理する必要があります。このためには、 {sync, false}オプションをに渡す必要がありますhttpc。オプションも参照してくださいstreamreceiver

最終的には、httpc最初は Twitter ストリーミング API にアクセスできますが、Twitter API からストリーミングするために開発する必要があるコードにはほとんど価値がありません。必要に応じて、特に HTTP パケットをデコードできることを考慮して、直接構築された単純なクライアントに置き換えたいと思うかもしれませんssl(あとは HTTP チャンク エンコーディングです)。

たとえば、キーワードがまれな場合、からタイムアウトが発生する可能性がありますhttpc。さらに、キーワードのリストやコードをダウンタイムなしで更新する方が簡単かもしれませんhttpc

に直接基づくストリーミング クライアントsslは、 (または、OTP の原則に従っていない場合は単純なプロセス) として実装するか、再接続戦略を実装gen_serverするためにさらに適切に実装できます。gen_fsm次のように進めることができます。

  • ssl:connect/3,4ソケットで HTTP パケットをデコードし、{packet, http_bin}ソケットをパッシブ モードで構成することを指定して接続します{active, false}

  • を使用して HTTP 要求パケットを送信します (できれば、バイナリを含む iolist として) ssl:send/2,3。CRLF ( \r\n) で区切られた複数の行に広がります。最初にクエリ行 ( 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 として指定し、データをバイナリ形式で指定します。実際、データがチャンクされている場合は、ソケットをパッシブ モードで使用し続けることができます。データを行ごとに取得することも、データを文字列として取得することもできます。これは好みの問題です。raw が最も安全な方法です。行ごとにバッファ サイズをチェックして、JSON でエンコードされた長いツイートが切り捨てられないようにする必要があります。

  • プロセスに送信されるメッセージとして Twitter からデータを受信しreceiveます。データがチャンク化されている場合、最初にチャンク サイズを受け取り、次にツイートとチャンクの最後を受け取ります ( RFC 2616を参照)。つぶやきが複数のチャンクに分散するように準備してください (つまり、ある種のバッファーを維持します)。ここでの最良の方法は、このプロセスで最小限のデコードを行い、ツイートを別のプロセスに (おそらくバイナリ形式で) 送信することです。handle_infogen_server

また、Twitter によって閉じられるエラーとソケットも処理する必要があります。再接続に関する Twitter のガイドラインに従っていることを確認してください。

于 2013-09-28T12:06:50.057 に答える