:mod:`http.cookies` --- HTTP state management ============================================= .. module:: http.cookies :synopsis: Support for HTTP state management (cookies). .. moduleauthor:: Timothy O'Malley .. sectionauthor:: Moshe Zadka **Source code:** :source:`Lib/http/cookies.py` -------------- The :mod:`http.cookies` module defines classes for abstracting the concept of cookies, an HTTP state management mechanism. It supports both simple string-only cookies, and provides an abstraction for having any serializable data-type as cookie value. The module formerly strictly applied the parsing rules described in the :rfc:`2109` and :rfc:`2068` specifications. It has since been discovered that MSIE 3.0x didn't follow the character rules outlined in those specs; many current-day browsers and servers have also relaxed parsing rules when it comes to cookie handling. As a result, this module now uses parsing rules that are a bit less strict than they once were. The character set, :data:`string.ascii_letters`, :data:`string.digits` and ``!#$%&'*+-.^_`|~:`` denote the set of valid characters allowed by this module in a cookie name (as :attr:`~Morsel.key`). .. versionchanged:: 3.3 Allowed ':' as a valid cookie name character. .. note:: On encountering an invalid cookie, :exc:`CookieError` is raised, so if your cookie data comes from a browser you should always prepare for invalid data and catch :exc:`CookieError` on parsing. .. exception:: CookieError Exception failing because of :rfc:`2109` invalidity: incorrect attributes, incorrect :mailheader:`Set-Cookie` header, etc. .. class:: BaseCookie([input]) This class is a dictionary-like object whose keys are strings and whose values are :class:`Morsel` instances. Note that upon setting a key to a value, the value is first converted to a :class:`Morsel` containing the key and the value. If *input* is given, it is passed to the :meth:`load` method. .. class:: SimpleCookie([input]) This class derives from :class:`BaseCookie` and overrides :meth:`~BaseCookie.value_decode` and :meth:`~BaseCookie.value_encode`. :class:`!SimpleCookie` supports strings as cookie values. When setting the value, :class:`!SimpleCookie` calls the builtin :func:`str` to convert the value to a string. Values received from HTTP are kept as strings. .. seealso:: Module :mod:`http.cookiejar` HTTP cookie handling for web *clients*. The :mod:`http.cookiejar` and :mod:`http.cookies` modules do not depend on each other. :rfc:`2109` - HTTP State Management Mechanism This is the state management specification implemented by this module. .. _cookie-objects: Cookie Objects -------------- .. method:: BaseCookie.value_decode(val) Return a tuple ``(real_value, coded_value)`` from a string representation. ``real_value`` can be any type. This method does no decoding in :class:`BaseCookie` --- it exists so it can be overridden. .. method:: BaseCookie.value_encode(val) Return a tuple ``(real_value, coded_value)``. *val* can be any type, but ``coded_value`` will always be converted to a string. This method does no encoding in :class:`BaseCookie` --- it exists so it can be overridden. In general, it should be the case that :meth:`value_encode` and :meth:`value_decode` are inverses on the range of *value_decode*. .. method:: BaseCookie.output(attrs=None, header='Set-Cookie:', sep='\r\n') Return a string representation suitable to be sent as HTTP headers. *attrs* and *header* are sent to each :class:`Morsel`'s :meth:`output` method. *sep* is used to join the headers together, and is by default the combination ``'\r\n'`` (CRLF). .. method:: BaseCookie.js_output(attrs=None) Return an embeddable JavaScript snippet, which, if run on a browser which supports JavaScript, will act the same as if the HTTP headers was sent. The meaning for *attrs* is the same as in :meth:`output`. .. method:: BaseCookie.load(rawdata) If *rawdata* is a string, parse it as an ``HTTP_COOKIE`` and add the values found there as :class:`Morsel`\ s. If it is a dictionary, it is equivalent to:: for k, v in rawdata.items(): cookie[k] = v .. _morsel-objects: Morsel Objects -------------- .. class:: Morsel Abstract a key/value pair, which has some :rfc:`2109` attributes. Morsels are dictionary-like objects, whose set of keys is constant --- the valid :rfc:`2109` attributes, which are: .. attribute:: expires path comment domain max-age secure version httponly samesite The attribute :attr:`httponly` specifies that the cookie is only transferred in HTTP requests, and is not accessible through JavaScript. This is intended to mitigate some forms of cross-site scripting. The attribute :attr:`samesite` specifies that the browser is not allowed to send the cookie along with cross-site requests. This helps to mitigate CSRF attacks. Valid values for this attribute are "Strict" and "Lax". The keys are case-insensitive and their default value is ``''``. .. versionchanged:: 3.5 :meth:`!__eq__` now takes :attr:`~Morsel.key` and :attr:`~Morsel.value` into account. .. versionchanged:: 3.7 Attributes :attr:`~Morsel.key`, :attr:`~Morsel.value` and :attr:`~Morsel.coded_value` are read-only. Use :meth:`~Morsel.set` for setting them. .. versionchanged:: 3.8 Added support for the :attr:`samesite` attribute. .. attribute:: Morsel.value The value of the cookie. .. attribute:: Morsel.coded_value The encoded value of the cookie --- this is what should be sent. .. attribute:: Morsel.key The name of the cookie. .. method:: Morsel.set(key, value, coded_value) Set the *key*, *value* and *coded_value* attributes. .. method:: Morsel.isReservedKey(K) Whether *K* is a member of the set of keys of a :class:`Morsel`. .. method:: Morsel.output(attrs=None, header='Set-Cookie:') Return a string representation of the Morsel, suitable to be sent as an HTTP header. By default, all the attributes are included, unless *attrs* is given, in which case it should be a list of attributes to use. *header* is by default ``"Set-Cookie:"``. .. method:: Morsel.js_output(attrs=None) Return an embeddable JavaScript snippet, which, if run on a browser which supports JavaScript, will act the same as if the HTTP header was sent. The meaning for *attrs* is the same as in :meth:`output`. .. method:: Morsel.OutputString(attrs=None) Return a string representing the Morsel, without any surrounding HTTP or JavaScript. The meaning for *attrs* is the same as in :meth:`output`. .. method:: Morsel.update(values) Update the values in the Morsel dictionary with the values in the dictionary *values*. Raise an error if any of the keys in the *values* dict is not a valid :rfc:`2109` attribute. .. versionchanged:: 3.5 an error is raised for invalid keys. .. method:: Morsel.copy(value) Return a shallow copy of the Morsel object. .. versionchanged:: 3.5 return a Morsel object instead of a dict. .. method:: Morsel.setdefault(key, value=None) Raise an error if key is not a valid :rfc:`2109` attribute, otherwise behave the same as :meth:`dict.setdefault`. .. _cookie-example: Example ------- The following example demonstrates how to use the :mod:`http.cookies` module. .. doctest:: :options: +NORMALIZE_WHITESPACE >>> from http import cookies >>> C = cookies.SimpleCookie() >>> C["fig"] = "newton" >>> C["sugar"] = "wafer" >>> print(C) # generate HTTP headers Set-Cookie: fig=newton Set-Cookie: sugar=wafer >>> print(C.output()) # same thing Set-Cookie: fig=newton Set-Cookie: sugar=wafer >>> C = cookies.SimpleCookie() >>> C["rocky"] = "road" >>> C["rocky"]["path"] = "/cookie" >>> print(C.output(header="Cookie:")) Cookie: rocky=road; Path=/cookie >>> print(C.output(attrs=[], header="Cookie:")) Cookie: rocky=road >>> C = cookies.SimpleCookie() >>> C.load("chips=ahoy; vienna=finger") # load from a string (HTTP header) >>> print(C) Set-Cookie: chips=ahoy Set-Cookie: vienna=finger >>> C = cookies.SimpleCookie() >>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=\\012;";') >>> print(C) Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=\012;" >>> C = cookies.SimpleCookie() >>> C["oreo"] = "doublestuff" >>> C["oreo"]["path"] = "/" >>> print(C) Set-Cookie: oreo=doublestuff; Path=/ >>> C = cookies.SimpleCookie() >>> C["twix"] = "none for you" >>> C["twix"].value 'none for you' >>> C = cookies.SimpleCookie() >>> C["number"] = 7 # equivalent to C["number"] = str(7) >>> C["string"] = "seven" >>> C["number"].value '7' >>> C["string"].value 'seven' >>> print(C) Set-Cookie: number=7 Set-Cookie: string=seven