web/request.py
branchstable
changeset 7855 54283a5b7afc
parent 7793 8a330017ca4d
child 7858 f91255a3b2c2
equal deleted inserted replaced
7854:d95a76df33a9 7855:54283a5b7afc
    17 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
    17 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
    18 """abstract class for http request"""
    18 """abstract class for http request"""
    19 
    19 
    20 __docformat__ = "restructuredtext en"
    20 __docformat__ = "restructuredtext en"
    21 
    21 
    22 import Cookie
       
    23 import hashlib
    22 import hashlib
    24 import time
    23 import time
    25 import random
    24 import random
    26 import base64
    25 import base64
       
    26 from Cookie import SimpleCookie
       
    27 from calendar import timegm
    27 from datetime import date
    28 from datetime import date
    28 from urlparse import urlsplit
    29 from urlparse import urlsplit
    29 from itertools import count
    30 from itertools import count
    30 from warnings import warn
    31 from warnings import warn
    31 
    32 
    40 from cubicweb.uilib import remove_html_tags, js
    41 from cubicweb.uilib import remove_html_tags, js
    41 from cubicweb.utils import SizeConstrainedList, HTMLHead, make_uid
    42 from cubicweb.utils import SizeConstrainedList, HTMLHead, make_uid
    42 from cubicweb.view import STRICT_DOCTYPE, TRANSITIONAL_DOCTYPE_NOEXT
    43 from cubicweb.view import STRICT_DOCTYPE, TRANSITIONAL_DOCTYPE_NOEXT
    43 from cubicweb.web import (INTERNAL_FIELD_VALUE, LOGGER, NothingToEdit,
    44 from cubicweb.web import (INTERNAL_FIELD_VALUE, LOGGER, NothingToEdit,
    44                           RequestError, StatusResponse)
    45                           RequestError, StatusResponse)
    45 from cubicweb.web.http_headers import Headers
    46 from cubicweb.web.httpcache import GMTOFFSET
       
    47 from cubicweb.web.http_headers import Headers, Cookie
    46 
    48 
    47 _MARKER = object()
    49 _MARKER = object()
    48 
    50 
    49 def build_cb_uid(seed):
    51 def build_cb_uid(seed):
    50     sha = hashlib.sha1('%s%s%s' % (time.time(), seed, random.random()))
    52     sha = hashlib.sha1('%s%s%s' % (time.time(), seed, random.random()))
   516         else:
   518         else:
   517             return self.header_authorization()
   519             return self.header_authorization()
   518 
   520 
   519     def get_cookie(self):
   521     def get_cookie(self):
   520         """retrieve request cookies, returns an empty cookie if not found"""
   522         """retrieve request cookies, returns an empty cookie if not found"""
       
   523         # XXX use http_headers implementation
   521         try:
   524         try:
   522             return Cookie.SimpleCookie(self.get_header('Cookie'))
   525             return SimpleCookie(self.get_header('Cookie'))
   523         except KeyError:
   526         except KeyError:
   524             return Cookie.SimpleCookie()
   527             return SimpleCookie()
   525 
   528 
   526     def set_cookie(self, cookie, key, maxage=300, expires=None):
   529     def set_cookie(self, name, value, maxage=300, expires=None, secure=False):
   527         """set / update a cookie key
   530         """set / update a cookie
   528 
   531 
   529         by default, cookie will be available for the next 5 minutes.
   532         by default, cookie will be available for the next 5 minutes.
   530         Give maxage = None to have a "session" cookie expiring when the
   533         Give maxage = None to have a "session" cookie expiring when the
   531         client close its browser
   534         client close its browser
   532         """
   535         """
   533         morsel = cookie[key]
   536         if isinstance(name, SimpleCookie):
   534         if maxage is not None:
   537             warn('[3.13] set_cookie now takes name and value as two first '
   535             morsel['Max-Age'] = maxage
   538                  'argument, not anymore cookie object and name',
   536         if expires:
   539                  DeprecationWarning, stacklevel=2)
   537             morsel['expires'] = expires.strftime('%a, %d %b %Y %H:%M:%S %z')
   540             secure = name[value]['secure']
       
   541             name, value = value, name[value].value
       
   542         if maxage: # don't check is None, 0 may be specified
       
   543             expires = maxage + time.time()
       
   544             assert expires is None, 'both max age and expires cant be specified'
       
   545         elif expires:
       
   546             expires = timegm((expires + GMTOFFSET).timetuple())
       
   547         else:
       
   548             expires = None
   538         # make sure cookie is set on the correct path
   549         # make sure cookie is set on the correct path
   539         morsel['path'] = self.base_url_path()
   550         cookie = Cookie(name, value, self.base_url_path(), expires=expires,
   540         self.add_header('Set-Cookie', morsel.OutputString())
   551                         secure=secure)
   541 
   552         self.headers_out.addHeader('Set-cookie', cookie)
   542     def remove_cookie(self, cookie, key):
   553 
       
   554     def remove_cookie(self, name, bwcompat=None):
   543         """remove a cookie by expiring it"""
   555         """remove a cookie by expiring it"""
   544         self.set_cookie(cookie, key, maxage=0, expires=date(1970, 1, 1))
   556         if bwcompat is not None:
       
   557             warn('[3.13] remove_cookie now take only a name as argument',
       
   558                  DeprecationWarning, stacklevel=2)
       
   559             name = bwcompat
       
   560         self.set_cookie(key, '', maxage=0, expires=date(1970, 1, 1))
   545 
   561 
   546     def set_content_type(self, content_type, filename=None, encoding=None):
   562     def set_content_type(self, content_type, filename=None, encoding=None):
   547         """set output content type for this request. An optional filename
   563         """set output content type for this request. An optional filename
   548         may be given
   564         may be given
   549         """
   565         """