Ticket #14770: django_ticket_14770.diff

File django_ticket_14770.diff, 9.8 KB (added by Paul McLanahan, 14 years ago)
  • django/http/__init__.py

     
    3737class Http404(Exception):
    3838    pass
    3939
    40 class HttpRequest(object):
     40
     41class HttpBase(object):
     42    """
     43    A common base class for HttpRequest and HttpResponse objects.
     44    """
     45   
     46    def set_cookie(self, key, value='', max_age=None, expires=None, path='/',
     47                   domain=None, secure=False):
     48        """
     49        Sets a cookie.
     50   
     51        ``expires`` can be a string in the correct format or a
     52        ``datetime.datetime`` object in UTC. If ``expires`` is a datetime
     53        object then ``max_age`` will be calculated.
     54        """
     55        # needed because WSGIRequest and ModPythonRequest don't call the
     56        # __init__ of their superclass
     57        if not hasattr(self, 'cookies'):   
     58            self.cookies = CompatCookie()
     59        self.cookies[key] = value
     60        if expires is not None:
     61            if isinstance(expires, datetime.datetime):
     62                delta = expires - expires.utcnow()
     63                # Add one second so the date matches exactly (a fraction of
     64                # time gets lost between converting to a timedelta and
     65                # then the date string).
     66                delta = delta + datetime.timedelta(seconds=1)
     67                # Just set max_age - the max_age logic will set expires.
     68                expires = None
     69                max_age = max(0, delta.days * 86400 + delta.seconds)
     70            else:
     71                self.cookies[key]['expires'] = expires
     72        if max_age is not None:
     73            self.cookies[key]['max-age'] = max_age
     74            # IE requires expires, so set it if hasn't been already.
     75            if not expires:
     76                self.cookies[key]['expires'] = cookie_date(time.time() +
     77                                                           max_age)
     78        if path is not None:
     79            self.cookies[key]['path'] = path
     80        if domain is not None:
     81            self.cookies[key]['domain'] = domain
     82        if secure:
     83            self.cookies[key]['secure'] = True
     84   
     85    def delete_cookie(self, key, path='/', domain=None):
     86        self.set_cookie(key, max_age=0, path=path, domain=domain,
     87                        expires='Thu, 01-Jan-1970 00:00:00 GMT')
     88
     89
     90class HttpRequest(HttpBase):
    4191    """A basic HTTP request."""
    4292
    4393    # The encoding used in GET/POST dicts. None means use default setting.
     
    4999        self.path = ''
    50100        self.path_info = ''
    51101        self.method = None
     102        self.cookies = CompatCookie()
    52103
    53104    def __repr__(self):
    54105        return '<HttpRequest\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' % \
     
    386437class BadHeaderError(ValueError):
    387438    pass
    388439
    389 class HttpResponse(object):
     440class HttpResponse(HttpBase):
    390441    """A basic HTTP response, with content and dictionary-accessed headers."""
    391442
    392443    status_code = 200
     
    461512    def get(self, header, alternate):
    462513        return self._headers.get(header.lower(), (None, alternate))[1]
    463514
    464     def set_cookie(self, key, value='', max_age=None, expires=None, path='/',
    465                    domain=None, secure=False):
    466         """
    467         Sets a cookie.
    468 
    469         ``expires`` can be a string in the correct format or a
    470         ``datetime.datetime`` object in UTC. If ``expires`` is a datetime
    471         object then ``max_age`` will be calculated.
    472         """
    473         self.cookies[key] = value
    474         if expires is not None:
    475             if isinstance(expires, datetime.datetime):
    476                 delta = expires - expires.utcnow()
    477                 # Add one second so the date matches exactly (a fraction of
    478                 # time gets lost between converting to a timedelta and
    479                 # then the date string).
    480                 delta = delta + datetime.timedelta(seconds=1)
    481                 # Just set max_age - the max_age logic will set expires.
    482                 expires = None
    483                 max_age = max(0, delta.days * 86400 + delta.seconds)
    484             else:
    485                 self.cookies[key]['expires'] = expires
    486         if max_age is not None:
    487             self.cookies[key]['max-age'] = max_age
    488             # IE requires expires, so set it if hasn't been already.
    489             if not expires:
    490                 self.cookies[key]['expires'] = cookie_date(time.time() +
    491                                                            max_age)
    492         if path is not None:
    493             self.cookies[key]['path'] = path
    494         if domain is not None:
    495             self.cookies[key]['domain'] = domain
    496         if secure:
    497             self.cookies[key]['secure'] = True
    498 
    499     def delete_cookie(self, key, path='/', domain=None):
    500         self.set_cookie(key, max_age=0, path=path, domain=domain,
    501                         expires='Thu, 01-Jan-1970 00:00:00 GMT')
    502 
    503515    def _get_content(self):
    504516        if self.has_header('Content-Encoding'):
    505517            return ''.join(self._container)
     
    604616        return unicode(s, encoding, 'replace')
    605617    else:
    606618        return s
    607 
  • django/http/utils.py

     
    8282
    8383    return response
    8484
     85def set_request_cookies(request, response):
     86    """
     87    Copy the cookies that were set via the request object to the
     88    response object where they'll be sent to the browser.
     89    """
     90    if hasattr(request, 'cookies'):
     91        response.cookies.update(request.cookies)
     92
     93    return response
     94
  • django/core/handlers/base.py

     
    1616        http.conditional_content_removal,
    1717        http.fix_IE_for_attach,
    1818        http.fix_IE_for_vary,
     19        http.set_request_cookies,
    1920    ]
    2021
    2122    def __init__(self):
  • tests/regressiontests/requests/views.py

     
     1from django.http import HttpResponse
     2
     3
     4def testing(request):
     5    request.set_cookie('name', 'Inigo Montoya')
     6    response = HttpResponse()
     7    response.set_cookie('job', 'revenge')
     8    return response
     9
     10def test_who_wins(request):
     11    request.set_cookie('name', 'Bender Bending Rodriquez')
     12    response = HttpResponse()
     13    response.set_cookie('name', 'Zoidberg')
     14    return response
     15
     16def delete_cookies(request):
     17    request.delete_cookie('name')
     18    response = HttpResponse()
     19    response.delete_cookie('job')
     20    return response
  • tests/regressiontests/requests/tests.py

     
    44
    55from django.core.handlers.modpython import ModPythonRequest
    66from django.core.handlers.wsgi import WSGIRequest, LimitedStream
     7from django.core.urlresolvers import reverse
    78from django.http import HttpRequest, HttpResponse, parse_cookie
     9from django.test import TestCase
    810from django.utils import unittest
    911from django.utils.http import cookie_date
    1012
     
    147149    def test_read_by_lines(self):
    148150        request = WSGIRequest({'REQUEST_METHOD': 'POST', 'wsgi.input': StringIO('name=value')})
    149151        self.assertEqual(list(request), ['name=value'])
     152
     153
     154class RequestCookiesTests(TestCase):
     155    urls = "regressiontests.requests.urls"
     156   
     157    def test_setting_cookie(self):
     158        res = self.client.get(reverse('cookies_testing'))
     159        self.assertEqual('Inigo Montoya', self.client.cookies['name'].value)
     160        self.assertEqual('revenge', self.client.cookies['job'].value)
     161   
     162    def test_delete_cookies(self):
     163        self.test_setting_cookie()
     164        self.client.get(reverse('cookies_delete'))
     165        self.assertEqual('', self.client.cookies['name'].value)
     166        self.assertEqual('', self.client.cookies['job'].value)
     167   
     168    def test_who_wins(self):
     169        self.client.get(reverse('cookies_who_wins'))
     170        self.assertEqual('Bender Bending Rodriquez', self.client.cookies['name'].value)
  • tests/regressiontests/requests/urls.py

     
     1from django.conf.urls.defaults import *
     2from django.http import HttpResponse
     3
     4from views import *
     5
     6
     7urlpatterns = patterns('',
     8    url(r'^testing/$', testing, name="cookies_testing"),
     9    url(r'^delete_cookies/$', delete_cookies, name="cookies_delete"),
     10    url(r'^test_who_wins/$', test_who_wins, name="cookies_who_wins"),
     11)
     12 No newline at end of file
  • docs/ref/request-response.txt

     
    299299        for element in ET.iterparse(request):
    300300            process(element)
    301301
     302.. method:: HttpRequest.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None)
    302303
     304    .. versionadded:: 1.3
     305   
     306    This method behaves identically to :meth:`HttpResponse.set_cookie()`.
     307   
     308    .. note:: Cookies set via ``reqeust.set_cookie()`` will overwrite ones with
     309        the same ``key`` which were set in the same request-response cycle via
     310        ``response.set_cookie()``.
     311
     312.. method:: HttpRequest.delete_cookie(key, path='/', domain=None)
     313
     314    .. versionadded:: 1.3
     315   
     316    This method behaves identically to :meth:`HttpResponse.delete_cookie()`.
     317
     318
    303319QueryDict objects
    304320-----------------
    305321
Back to Top