21.24. http.cookiejar --- HTTP クライアント用の Cookie 処理

ソースコード: Lib/http/cookiejar.py


http.cookiejar モジュールは HTTP クッキーの自動処理をおこなうクラスを定義します。これは小さなデータの断片 -- クッキー -- を要求する web サイトにアクセスする際に有用です。クッキーとは web サーバの HTTP レスポンスによってクライアントのマシンに設定され、のちの HTTP リクエストをおこなうさいにサーバに返されるものです。

標準的な Netscape クッキープロトコルおよび RFC 2965 で定義されているプロトコルの両方を処理できます。RFC 2965 の処理はデフォルトではオフになっています。 RFC 2109 のクッキーは Netscape クッキーとして解析され、のちに有効な 'ポリシー' に従って Netscapeまたは RFC 2965 クッキーとして処理されます。但し、インターネット上の大多数のクッキーは Netscapeクッキーです。 http.cookiejar はデファクトスタンダードの Netscape クッキープロトコル (これは元々 Netscape が策定した仕様とはかなり異なっています) に従うようになっており、RFC 2109 で導入された max-ageport などのクッキー属性にも注意を払います。

注釈

Set-CookieSet-Cookie2 ヘッダに現れる多種多様なパラメータの名前 (domainexpires など) は便宜上 属性 と呼ばれますが、ここでは Python の属性と区別するため、かわりに クッキー属性 と呼ぶことにします。

このモジュールは以下の例外を定義しています:

exception http.cookiejar.LoadError

この例外は FileCookieJar インスタンスがファイルからクッキーを読み込むのに失敗した場合に発生します。 LoadErrorOSError のサブクラスです。

バージョン 3.3 で変更: LoadError は IOError の代わりに OSError のサブクラスになりました。

以下のクラスが提供されています:

class http.cookiejar.CookieJar(policy=None)

policyCookiePolicy インターフェイスを実装するオブジェクトです。

CookieJar クラスには HTTP クッキーを保管します。これは HTTP リクエストに応じてクッキーを取り出し、それを HTTP レスポンスの中で返します。必要に応じて、 CookieJar インスタンスは保管されているクッキーを自動的に破棄します。このサブクラスは、クッキーをファイルやデータベースに格納したり取り出したりする操作をおこなう役割を負っています。

class http.cookiejar.FileCookieJar(filename, delayload=None, policy=None)

policyCookiePolicy インターフェイスを実装するオブジェクトです。これ以外の引数については、該当する属性の説明を参照してください。

FileCookieJar はディスク上のファイルからのクッキーの読み込み、もしくは書き込みをサポートします。実際には、 load() または revert() のどちらかのメソッドが呼ばれるまでクッキーは指定されたファイルからはロード されません 。このクラスのサブクラスは FileCookieJar のサブクラスと web ブラウザとの連携 節で説明します。

class http.cookiejar.CookiePolicy

このクラスは、あるクッキーをサーバから受け入れるべきか、そしてサーバに返すべきかを決定する役割を負っています。

class http.cookiejar.DefaultCookiePolicy(blocked_domains=None, allowed_domains=None, netscape=True, rfc2965=False, rfc2109_as_netscape=None, hide_cookie2=False, strict_domain=False, strict_rfc2965_unverifiable=True, strict_ns_unverifiable=False, strict_ns_domain=DefaultCookiePolicy.DomainLiberal, strict_ns_set_initial_dollar=False, strict_ns_set_path=False)

コンストラクタはキーワード引数しか取りません。 blocked_domains はドメイン名からなるシーケンスで、ここからは決してクッキーを受けとらないし、このドメインにクッキーを返すこともありません。 allowed_domainsNone でない場合、これはこのドメインのみからクッキーを受けとり、返すという指定になります。これ以外の引数については CookiePolicy および DefaultCookiePolicy オブジェクトの説明をごらんください。

DefaultCookiePolicy は Netscape および RFC 2965 クッキーの標準的な許可 / 拒絶のルールを実装しています。デフォルトでは、 RFC 2109 のクッキー (Set-Cookie の version クッキー属性が 1 で受けとられるもの) は RFC 2965 のルールで扱われます。しかし、RFC 2965 処理が無効に設定されているか rfc2109_as_netscapeTrue の場合、RFC 2109 クッキーは CookieJar インスタンスによって Cookie のインスタンスの version 属性を 0 に設定する事で Netscapeクッキーに「ダウングレード」されます。また DefaultCookiePolicy にはいくつかの細かいポリシー設定をおこなうパラメータが用意されています。

class http.cookiejar.Cookie

このクラスは Netscape クッキー、 RFC 2109 のクッキー、および RFC 2965 のクッキーを表現します。 http.cookiejar のユーザが自分で Cookie インスタンスを作成することは想定されていません。かわりに、必要に応じて CookieJar インスタンスの make_cookies() を呼ぶことになっています。

参考

urllib.request モジュール

クッキーの自動処理をおこない URL を開くモジュールです。

http.cookies モジュール

HTTP のクッキークラスで、基本的にはサーバサイドのコードで有用です。 http.cookiejar および http.cookies モジュールは互いに依存してはいません。

https://curl.haxx.se/rfc/cookie_spec.html

元祖 Netscape のクッキープロトコルの仕様です。今でもこれが主流のプロトコルですが、現在のメジャーなブラウザ (と http.cookiejar) が実装している「Netscape クッキープロトコル」は cookie_spec.html で述べられているものとおおまかにしか似ていません。

RFC 2109 - HTTP State Management Mechanism

RFC 2965 によって過去の遺物になりました。 Set-Cookie の version=1 で使います。

RFC 2965 - HTTP State Management Mechanism

Netscape プロトコルのバグを修正したものです。 Set-Cookie のかわりに Set-Cookie2 を使いますが、普及してはいません。

http://kristol.org/cookie/errata.html

RFC 2965 に対する未完の正誤表です。

RFC 2964 - Use of HTTP State Management

21.24.1. CookieJar および FileCookieJar オブジェクト

CookieJar オブジェクトは保管されている Cookie オブジェクトをひとつずつ取り出すための、イテレータ(iterator)・プロトコルをサポートしています。

CookieJar は以下のようなメソッドを持っています:

request に正しい Cookie ヘッダを追加します。

ポリシーが許すようであれば (CookieJarCookiePolicy インスタンスにある属性のうち、 rfc2965 および hide_cookie2 がそれぞれ真と偽であるような場合)、必要に応じて Cookie2 ヘッダも追加されます。

The request object (usually a urllib.request..Request instance) must support the methods get_full_url(), get_host(), get_type(), unverifiable(), has_header(), get_header(), header_items(), add_unredirected_header() and origin_req_host attribute as documented by urllib.request.

バージョン 3.3 で変更: request object needs origin_req_host attribute. Dependency on a deprecated method get_origin_req_host() has been removed.

CookieJar.extract_cookies(response, request)

HTTP response からクッキーを取り出し、ポリシーによって許可されていればこれを CookieJar 内に保管します。

CookieJarresponse 引数の中から許可されている Set-Cookie および Set-Cookie2 ヘッダを探しだし、適切に (CookiePolicy.set_ok() メソッドの承認におうじて) クッキーを保管します。

response オブジェクト (通常は urllib.request.urlopen() あるいはそれに類似する呼び出しによって得られます) は info() メソッドをサポートしている必要があります。これは email.message.Message メソッドのあるオブジェクトを返すものです。

request オブジェクト (通常は urllib.request.Request インスタンス) は urllib.request のドキュメントに記されているように、 get_full_url(), get_host(), unverifiable() メソッドおよび origin_req_host 属性をサポートしている必要があります。この request はそのクッキーの保存が許可されているかを検査するとともに、クッキー属性のデフォルト値を設定するのに使われます。

バージョン 3.3 で変更: request object needs origin_req_host attribute. Dependency on a deprecated method get_origin_req_host() has been removed.

CookieJar.set_policy(policy)

使用する CookiePolicy インスタンスを指定します。

CookieJar.make_cookies(response, request)

response オブジェクトから得られた Cookie オブジェクトからなるシーケンスを返します。

response および request 引数で要求されるインスタンスについては、 extract_cookies() の説明を参照してください。

ポリシーが許すのであれば、与えられた Cookie を設定します。

与えられた Cookie を、それが設定されるべきかどうかのポリシーのチェックを行わずに設定します。

CookieJar.clear([domain[, path[, name]]])

いくつかのクッキーを消去します。

引数なしで呼ばれた場合は、すべてのクッキーを消去します。引数がひとつ与えられた場合、その domain に属するクッキーのみを消去します。ふたつの引数が与えられた場合、指定された domain と URL path に属するクッキーのみを消去します。引数が 3つ与えられた場合、domain, path および name で指定されるクッキーが消去されます。

与えられた条件に一致するクッキーがない場合は KeyError を発生させます。

CookieJar.clear_session_cookies()

すべてのセッションクッキーを消去します。

保存されているクッキーのうち、 discard 属性が真になっているものすべてを消去します (通常これは max-age または expires のどちらのクッキー属性もないか、あるいは明示的に discard クッキー属性が指定されているものです)。対話的なブラウザの場合、セッションの終了はふつうブラウザのウィンドウを閉じることに相当します。

注意: ignore_discard 引数に真を指定しないかぎり、 save() メソッドはセッションクッキーは保存しません。

さらに FileCookieJar は以下のようなメソッドを実装しています:

FileCookieJar.save(filename=None, ignore_discard=False, ignore_expires=False)

クッキーをファイルに保存します。

この基底クラスは NotImplementedError を発生させます。サブクラスはこのメソッドを実装しないままにしておいてもかまいません。

filename はクッキーを保存するファイルの名前です。 filename が指定されない場合、 self.filename が使用されます (このデフォルト値は、それが存在する場合は、コンストラクタに渡されています)。 self.filenameNone の場合は ValueError が発生します。

ignore_discard : 破棄されるよう指示されていたクッキーでも保存します。ignore_expires : 期限の切れたクッキーでも保存します。

ここで指定されたファイルがもしすでに存在する場合は上書きされるため、以前にあったクッキーはすべて消去されます。保存したクッキーはあとで load() または revert() メソッドを使って復元することができます。

FileCookieJar.load(filename=None, ignore_discard=False, ignore_expires=False)

ファイルからクッキーを読み込みます。

それまでのクッキーは新しいものに上書きされない限り残ります。

ここでの引数の値は save() と同じです。

名前のついたファイルはこのクラスがわかるやり方で指定する必要があります。さもないと LoadError が発生します。さらに、例えばファイルが存在しないような時に OSError が発生する場合があります。

バージョン 3.3 で変更: 以前は IOError が送出されました; それは現在 OSError のエイリアスです。

FileCookieJar.revert(filename=None, ignore_discard=False, ignore_expires=False)

すべてのクッキーを破棄し、保存されているファイルから読み込み直します。

revert()load() と同じ例外を発生させる事ができます。失敗した場合、オブジェクトの状態は変更されません。

FileCookieJar インスタンスは以下のような公開の属性をもっています:

FileCookieJar.filename

クッキーを保存するデフォルトのファイル名を指定します。この属性には代入することができます。

FileCookieJar.delayload

真であれば、クッキーを読み込むさいにディスクから遅延読み込みします。この属性には代入することができません。この情報は単なるヒントであり、 (ディスク上のクッキーが変わらない限りは) インスタンスのふるまいには影響を与えず、パフォーマンスのみに影響します。 CookieJar オブジェクトはこの値を無視することもあります。標準ライブラリに含まれている FileCookieJar クラスで遅延読み込みをおこなうものはありません。

21.24.2. FileCookieJar のサブクラスと web ブラウザとの連携

クッキーの読み書きのために、以下の CookieJar サブクラスが提供されています。

class http.cookiejar.MozillaCookieJar(filename, delayload=None, policy=None)

Mozilla の cookies.txt ファイル形式 (この形式はまた Lynx と Netscape ブラウザによっても使われています) でディスクにクッキーを読み書きするための FileCookieJar です。

注釈

このクラスは RFC 2965 クッキーに関する情報を失います。また、より新しいか、標準でない port などのクッキー属性についての情報も失います。

警告

もしクッキーの損失や欠損が望ましくない場合は、クッキーを保存する前にバックアップを取っておくようにしてください (ファイルへの読み込み / 保存をくり返すと微妙な変化が生じる場合があります)。

また、Mozilla の起動中にクッキーを保存すると、Mozilla によって内容が破壊されてしまうことにも注意してください。

class http.cookiejar.LWPCookieJar(filename, delayload=None, policy=None)

libwww-perl のライブラリである Set-Cookie3 ファイル形式でディスクにクッキーを読み書きするための FileCookieJar です。これはクッキーを人間に可読な形式で保存するのに向いています。

21.24.3. CookiePolicy オブジェクト

CookiePolicy インターフェイスを実装するオブジェクトは以下のようなメソッドを持っています:

CookiePolicy.set_ok(cookie, request)

クッキーがサーバから受け入れられるべきかどうかを表わす boolean 値を返します。

cookieCookie インスタンスです。 requestCookieJar.extract_cookies() の説明で定義されているインターフェイスを実装するオブジェクトです。

CookiePolicy.return_ok(cookie, request)

クッキーがサーバに返されるべきかどうかを表わす boolean 値を返します。

cookieCookie インスタンスです。 requestCookieJar.add_cookie_header() の説明で定義されているインターフェイスを実装するオブジェクトです。

CookiePolicy.domain_return_ok(domain, request)

与えられたクッキーのドメインに対して、そこにクッキーを返すべきでない場合には false を返します。

このメソッドは高速化のためのものです。これにより、すべてのクッキーをある特定のドメインに対してチェックする (これには多数のファイル読みこみを伴なう場合があります) 必要がなくなります。 domain_return_ok() および path_return_ok() の両方から true が返された場合、すべての決定は return_ok() に委ねられます。

もし、このクッキードメインに対して domain_return_ok() が true を返すと、つぎにそのクッキーのパス名に対して path_return_ok() が呼ばれます。そうでない場合、そのクッキードメインに対する path_return_ok() および return_ok() は決して呼ばれることはありません。 path_return_ok() が true を返すと、 return_ok() がその Cookie オブジェクト自身の全チェックのために呼ばれます。そうでない場合、そのクッキーパス名に対する return_ok() は決して呼ばれることはありません。

注意: domain_return_ok()request ドメインだけではなく、すべての cookie ドメインに対して呼ばれます。たとえば request ドメインが "www.example.com" だった場合、この関数は ".example.com" および "www.example.com" の両方に対して呼ばれることがあります。同じことは path_return_ok() にもいえます。

request 引数は return_ok() で説明されているとおりです。

CookiePolicy.path_return_ok(path, request)

与えられたクッキーのパス名に対して、そこにクッキーを返すべきでない場合には false を返します。

domain_return_ok() の説明を参照してください。

上のメソッドの実装にくわえて、 CookiePolicy インターフェイスの実装では以下の属性を設定する必要があります。これはどのプロトコルがどのように使われるべきかを示すもので、これらの属性にはすべて代入することが許されています。

CookiePolicy.netscape

Netscape プロトコルを実装していることを示します。

CookiePolicy.rfc2965

RFC 2965 プロトコルを実装していることを示します。

CookiePolicy.hide_cookie2

Cookie2 ヘッダをリクエストに含めないようにします (このヘッダが存在する場合、私たちは RFC 2965 クッキーを理解するということをサーバに示すことになります)。

もっとも有用な方法は、 DefaultCookiePolicy をサブクラス化した CookiePolicy クラスを定義して、いくつか (あるいはすべて) のメソッドをオーバーライドすることでしょう。 CookiePolicy 自体はどのようなクッキーも受け入れて設定を許可する「ポリシー無し」ポリシーとして使うこともできます (これが役に立つことはあまりありませんが)。

21.24.4. DefaultCookiePolicy オブジェクト

クッキーを受けつけ、またそれを返す際の標準的なルールを実装します。

RFC 2965 クッキーと Netscape クッキーの両方に対応しています。デフォルトでは、RFC 2965 の処理はオフになっています。

自分のポリシーを提供するいちばん簡単な方法は、このクラスを継承して、自分用の追加チェックの前にオーバーライドした元のメソッドを呼び出すことです:

import http.cookiejar
class MyCookiePolicy(http.cookiejar.DefaultCookiePolicy):
    def set_ok(self, cookie, request):
        if not http.cookiejar.DefaultCookiePolicy.set_ok(self, cookie, request):
            return False
        if i_dont_want_to_store_this_cookie(cookie):
            return False
        return True

CookiePolicy インターフェイスを実装するのに必要な機能に加えて、このクラスではクッキーを受けとったり設定したりするドメインを許可したり拒絶したりできるようになっています。ほかにも、 Netscape プロトコルのかなり緩い規則をややきつくするために、いくつかの厳密性のスイッチがついています (いくつかの良性クッキーをブロックする危険性もありますが)。

ドメインのブラックリスト機能やホワイトリスト機能も提供されています (デフォルトではオフになっています)。ブラックリストになく、(ホワイトリスト機能を使用している場合は) ホワイトリストにあるドメインのみがクッキーを設定したり返したりすることを許可されます。コンストラクタの引数 blocked_domains 、および blocked_domains()set_blocked_domains() メソッドを使ってください (allowed_domains に関しても同様の対応する引数とメソッドがあります)。ホワイトリストを設定した場合は、それを None にすることでホワイトリスト機能をオフにすることができます。

ブラックリストあるいはホワイトリスト中にあるドメインのうち、ドット (.) で始まっていないものは、正確にそれと一致するドメインのクッキーにしか適用されません。たとえばブラックリスト中のエントリ "example.com" は、"example.com" にはマッチしますが、"www.example.com" にはマッチしません。一方ドット (.) で始まっているドメインは、より特化されたドメインともマッチします。たとえば、".example.com" は、"www.example.com""www.coyote.example.com" の両方にマッチします (が、"example.com" 自身にはマッチしません)。IP アドレスは例外で、つねに正確に一致する必要があります。たとえば、かりに blocked_domains"192.168.1.2"".168.1.2" を含んでいたとして、192.168.1.2 はブロックされますが、193.168.1.2 はブロックされません。

DefaultCookiePolicy は以下のような追加メソッドを実装しています:

DefaultCookiePolicy.blocked_domains()

ブロックしているドメインのシーケンスを (タプルとして) 返します。

DefaultCookiePolicy.set_blocked_domains(blocked_domains)

ブロックするドメインを設定します。

DefaultCookiePolicy.is_blocked(domain)

domain がクッキーを授受しないブラックリストに載っているかどうかを返します。

DefaultCookiePolicy.allowed_domains()

None あるいは明示的に許可されているドメインを (タプルとして) 返します。

DefaultCookiePolicy.set_allowed_domains(allowed_domains)

許可するドメイン、あるいは None を設定します。

DefaultCookiePolicy.is_not_allowed(domain)

domain がクッキーを授受するホワイトリストに載っているかどうかを返します。

DefaultCookiePolicy インスタンスは以下の属性をもっています。これらはすべてコンストラクタから同じ名前の引数をつかって初期化することができ、代入してもかまいません。

DefaultCookiePolicy.rfc2109_as_netscape

真の場合、 CookieJar のインスタンスに RFC 2109 クッキー (即ち Set-Cookie ヘッダのクッキー属性 Version の値が 1 のクッキー) を Netscapeクッキーへ、 Cookie インスタンスの version 属性を 0 に設定する事でダウングレードするように要求します。デフォルトの値は None であり、この場合 RFC 2109 クッキーは RFC 2965 処理が無効に設定されている場合に限りダウングレードされます。それ故に RFC 2109 クッキーはデフォルトではダウングレードされます。

一般的な厳密性のスイッチ:

DefaultCookiePolicy.strict_domain

サイトに、国別コードとトップレベルドメインだけからなるドメイン名 (.co.uk, .gov.uk, .co.nz など) を設定させないようにします。これは完璧からはほど遠い実装であり、いつもうまくいくとは限りません!

RFC 2965 プロトコルの厳密性に関するスイッチ:

DefaultCookiePolicy.strict_rfc2965_unverifiable

検証不可能なトランザクション (通常これはリダイレクトか、別のサイトがホスティングしているイメージの読み込み要求です) に関する RFC 2965 の規則に従います。この値が偽の場合、検証可能性を基準にしてクッキーがブロックされることは 決して ありません

Netscape プロトコルの厳密性に関するスイッチ:

DefaultCookiePolicy.strict_ns_unverifiable

検証不可能なトランザクションに関する RFC 2965 の規則を Netscape クッキーに対しても適用します。

DefaultCookiePolicy.strict_ns_domain

Netscape クッキーに対するドメインマッチングの規則をどの程度厳しくするかを指示するフラグです。とりうる値については下の説明を見てください。

DefaultCookiePolicy.strict_ns_set_initial_dollar

Set-Cookie: ヘッダで、'$' で始まる名前のクッキーを無視します。

DefaultCookiePolicy.strict_ns_set_path

要求した URI にパスがマッチしないクッキーの設定を禁止します。

strict_ns_domain はいくつかのフラグの集合です。これはいくつかの値を or することで構成します (たとえば DomainStrictNoDots|DomainStrictNonDomain は両方のフラグが設定されていることになります)。

DefaultCookiePolicy.DomainStrictNoDots

クッキーを設定するさい、ホスト名のプレフィクスにドットが含まれるのを禁止します (例: www.foo.bar.com.bar.com のクッキーを設定することはできません、なぜなら www.foo はドットを含んでいるからです)。

DefaultCookiePolicy.DomainStrictNonDomain

domain クッキー属性を明示的に指定していないクッキーは、そのクッキーを設定したドメインと同一のドメインだけに返されます (例: example.com からのクッキーに domain クッキー属性がない場合、そのクッキーが spam.example.com に返されることはありません)。

DefaultCookiePolicy.DomainRFC2965Match

クッキーを設定するさい、 RFC 2965 の完全ドメインマッチングを要求します。

以下の属性は上記のフラグのうちもっともよく使われる組み合わせで、便宜をはかるために提供されています:

DefaultCookiePolicy.DomainLiberal

0 と同じです (つまり、上述の Netscape のドメイン厳密性フラグがすべてオフにされます)。

DefaultCookiePolicy.DomainStrict

DomainStrictNoDots|DomainStrictNonDomain と同じです。

21.24.6. 使用例

はじめに、もっとも一般的な http.cookiejar の使用例をあげます:

import http.cookiejar, urllib.request
cj = http.cookiejar.CookieJar()
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
r = opener.open("http://example.com/")

以下の例では、URL を開く際に Netscape や Mozilla または Lynx のクッキーを使う方法を示しています (クッキーファイルの位置は Unix/Netscape の慣例にしたがうものと仮定しています):

import os, http.cookiejar, urllib.request
cj = http.cookiejar.MozillaCookieJar()
cj.load(os.path.join(os.path.expanduser("~"), ".netscape", "cookies.txt"))
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
r = opener.open("http://example.com/")

つぎの例は DefaultCookiePolicy の使用例です。 RFC 2965 クッキーをオンにし、Netscape クッキーを設定したり返したりするドメインに対してより厳密な規則を適用します。そしていくつかのドメインからクッキーを設定あるいは返還するのをブロックしています:

import urllib.request
from http.cookiejar import CookieJar, DefaultCookiePolicy
policy = DefaultCookiePolicy(
    rfc2965=True, strict_ns_domain=Policy.DomainStrict,
    blocked_domains=["ads.net", ".ads.net"])
cj = CookieJar(policy)
opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cj))
r = opener.open("http://example.com/")