Ruby http ライブラリで予期しない文字エンコーディングが発生するのはなぜですか? (カーブ、エクスコン vs シェルアウト)

概要

外部リクエスト ライブラリ (curb、excon) から応答本文を ascii-8bit として取得していますが、utf-8 が期待されています。

私の Ruby 環境はデフォルトで utf-8 エンコーディングに設定されています。

Encoding.default_external
=> #<Encoding:UTF-8>
Encoding.default_internal
=> #<Encoding:UTF-8>

このリクエストでは URL や (明らかに) 認証トークンを明らかにすることはできませんが、curl にシェルアウトすると有効な utf-8 レスポンスが得られます。

text = `curl -H "Authorization: Bearer #{token}" "#{url}"`
text[28782..28786]
=> "Maté,"
text.encoding
=> #<Encoding:UTF-8>

しかし、Ruby ライブラリのいずれかを使用すると、異なる結果が得られます

縁石:

curl = Curl::Easy.new(url)
curl.headers["Authorization"] = "Bearer #{client.auth_token}"
curl.http_get
body = curl.body_str
body[28782..28786]
=> "Mat\xC3\xA9"
body.encoding
=> #<Encoding:ASCII-8BIT>

エクスコン:

connection = Excon.new(url, headers: {"Authorization" => "Bearer #{token}"})
response = connection.get
response_body = response.body
response_body[28782..28786]
=> "Mat\xC3\xA9"
response_body.encoding
=> #<Encoding:ASCII-8BIT>

これにより、応答データを他の外部サービスに保存するときに問題が発生します。この場合、通話の終わりにforce_encoding(“utf-8”)を単に叩き込むだけで済むことはわかっていますが、これは応急処置のように思えます。そこで私の質問は、これらの http ライブラリの応答はどのようにして ascii-8bit として解釈されるのでしょうか、またそれをシステム的に変更するにはどうすればよいでしょうか?

解決策

ここで問題が発生していることを残念に思います。私は excon の主な開発者および保守者なので、少なくともあなたの質問のその部分について話すことができます。

HTTP/1.1 は多くの場合バイトカウントを重視しているため、マルチバイト文字などについて心配することなく、ASCII を使用することが簡単な方法でした。

そうは言っても、応答が UTF-8 であると確信できる場合 (コンテンツ タイプ ヘッダーにその旨が示されているかどうかが良い指標となります)、強制的に「UTF-8」エンコードにするのが安全/合理的であると思います。この状況で私ならそうするだろう、少なくとも試してみる価値はあると思います。

これに関して、絆創膏のように感じたり、長期的な解決策として合理的ではないと感じたりするような特別な懸念はありますか?