5
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Rubyのnet/httpにおけるヘッダフィールド名の大文字小文字の扱い

Posted at

net/httpについて

RubyのプログラムでWebAPIを叩く時などに、標準で含まれているnet/httpライブラリを使うことがあると思います。もしくは利用しているHTTPのライブラリが内部でnet/httpを使っていることも多いでしょう。

net/httpにおいてHTTPリクエストにヘッダフィールドを追加する場合、[]=もしくはadd_fieldを使います。

req = Net::HTTP::Get.new('/some_path')
req['X-My-Header'] = 'some_value'

なお、一般的によく使われるフィールドにはcontent_type=のように専用のメソッドが用意されています。HTTPヘッダに関するメソッドはNet::HTTPHeaderモジュールで定義されています。

大文字小文字の扱い

[]=のリファレンスでは、「key(ヘッダフィールド名)は大文字小文字を区別しません。」と書かれています。

実際にこのメソッドのソースコードを読んでみましょう。

def []=(key, val)
  unless val
    @header.delete key.downcase
    return val
  end
  @header[key.downcase] = [val]
end

ヘッダフィールド名は、内部的にはdowncaseメソッドを使って全て小文字に直されています。これはinitializeadd_fieldについても同様です。

では送信時にパケットに含まれる文字列も全て小文字なのか?というと、そうではありません。送信時に、each_capitalizedなる処理が挟まれます。具体的にフィールド名にどのような文字列操作が掛かるのか、というのはここに記載されています

name.to_s.split(/-/).map {|s| s.capitalize }.join('-')

これはヘッダフィールド名の記載方法として慣用化されている、User-AgentIf-Modified-Sinceのような形式に直すということです。

HTTPのRFCでは

現在有効なHTTP/1.1のRFCはRFC7230~7235です。その中でヘッダフィールド名に関しては、case-insensitiveであると記載されています。これを遵守しているサーバであれば、大文字小文字はどのように記載していても区別なく解釈してくれるはずです。

上記のnet/httpの実装はRFCが遵守されていることを前提に、内部的な表記を統一することでプログラマが大文字小文字を意識しなくてすむようにしているのだと思います。

送信時に一手間加えているのは、単に慣用に倣っただけなのか、それ以上の強い理由が何かあるのか、詳しくはわかりません。ただ調べた限りでは、主要なWebブラウザはだいたいこの慣用に従っているようなので、とりあえず合わせておけば安心と言えるかもしれません。

case-sensitiveなサーバの場合

ところで、なぜこんなことを調べたかというと、RFCの記載に則らず大文字小文字を区別するAPIを叩く機会があったからです。そのAPIは以下のようなヘッダフィールド名(仮)を要求していました。

X-ABC-Token: token_value

これをnet/httpで送信しようとしても、セット時の表記にかかわらず内部のキー名はx-abc-tokenとなり、送信時はX-Abc-Tokenとして送信されます。残念ながらそのAPIを提供するサーバは、このフィールドを解釈してくれませんでした。以下はWiresharkで表示したパケットの中身です。

header1.png

このようなサーバを相手にする際は、素直にnet/httpではなく他のHTTPライブラリを使いましょう。ただし、net/httpに依存していて、ここの処理が丸々使われているライブラリだと結局解決されないので注意です。各種HTTPライブラリの依存関係については、この図がわかりやすいです。

net/httpに依存していないHTTPClientは、この問題を解消することができました。以下はHTTPClientを用いた場合のパケットです。

header2.png

元はといえばサーバ側のAPI実装がイマイチなことに起因しているので、同じような問題に当たる人がいるのかはわかりませんが…色々調べて勉強にもなったので、書き残しておきます。

5
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?