Index: django/http/__init__.py
===================================================================
--- django/http/__init__.py	(revision 14693)
+++ django/http/__init__.py	(working copy)
@@ -37,7 +37,57 @@
 class Http404(Exception):
     pass
 
-class HttpRequest(object):
+
+class HttpBase(object):
+    """
+    A common base class for HttpRequest and HttpResponse objects.
+    """
+    
+    def set_cookie(self, key, value='', max_age=None, expires=None, path='/',
+                   domain=None, secure=False):
+        """
+        Sets a cookie.
+    
+        ``expires`` can be a string in the correct format or a
+        ``datetime.datetime`` object in UTC. If ``expires`` is a datetime
+        object then ``max_age`` will be calculated.
+        """
+        # needed because WSGIRequest and ModPythonRequest don't call the
+        # __init__ of their superclass
+        if not hasattr(self, 'cookies'):    
+            self.cookies = CompatCookie()
+        self.cookies[key] = value
+        if expires is not None:
+            if isinstance(expires, datetime.datetime):
+                delta = expires - expires.utcnow()
+                # Add one second so the date matches exactly (a fraction of
+                # time gets lost between converting to a timedelta and
+                # then the date string).
+                delta = delta + datetime.timedelta(seconds=1)
+                # Just set max_age - the max_age logic will set expires.
+                expires = None
+                max_age = max(0, delta.days * 86400 + delta.seconds)
+            else:
+                self.cookies[key]['expires'] = expires
+        if max_age is not None:
+            self.cookies[key]['max-age'] = max_age
+            # IE requires expires, so set it if hasn't been already.
+            if not expires:
+                self.cookies[key]['expires'] = cookie_date(time.time() +
+                                                           max_age)
+        if path is not None:
+            self.cookies[key]['path'] = path
+        if domain is not None:
+            self.cookies[key]['domain'] = domain
+        if secure:
+            self.cookies[key]['secure'] = True
+    
+    def delete_cookie(self, key, path='/', domain=None):
+        self.set_cookie(key, max_age=0, path=path, domain=domain,
+                        expires='Thu, 01-Jan-1970 00:00:00 GMT')
+
+
+class HttpRequest(HttpBase):
     """A basic HTTP request."""
 
     # The encoding used in GET/POST dicts. None means use default setting.
@@ -49,6 +99,7 @@
         self.path = ''
         self.path_info = ''
         self.method = None
+        self.cookies = CompatCookie()
 
     def __repr__(self):
         return '<HttpRequest\nGET:%s,\nPOST:%s,\nCOOKIES:%s,\nMETA:%s>' % \
@@ -386,7 +437,7 @@
 class BadHeaderError(ValueError):
     pass
 
-class HttpResponse(object):
+class HttpResponse(HttpBase):
     """A basic HTTP response, with content and dictionary-accessed headers."""
 
     status_code = 200
@@ -461,45 +512,6 @@
     def get(self, header, alternate):
         return self._headers.get(header.lower(), (None, alternate))[1]
 
-    def set_cookie(self, key, value='', max_age=None, expires=None, path='/',
-                   domain=None, secure=False):
-        """
-        Sets a cookie.
-
-        ``expires`` can be a string in the correct format or a
-        ``datetime.datetime`` object in UTC. If ``expires`` is a datetime
-        object then ``max_age`` will be calculated.
-        """
-        self.cookies[key] = value
-        if expires is not None:
-            if isinstance(expires, datetime.datetime):
-                delta = expires - expires.utcnow()
-                # Add one second so the date matches exactly (a fraction of
-                # time gets lost between converting to a timedelta and
-                # then the date string).
-                delta = delta + datetime.timedelta(seconds=1)
-                # Just set max_age - the max_age logic will set expires.
-                expires = None
-                max_age = max(0, delta.days * 86400 + delta.seconds)
-            else:
-                self.cookies[key]['expires'] = expires
-        if max_age is not None:
-            self.cookies[key]['max-age'] = max_age
-            # IE requires expires, so set it if hasn't been already.
-            if not expires:
-                self.cookies[key]['expires'] = cookie_date(time.time() +
-                                                           max_age)
-        if path is not None:
-            self.cookies[key]['path'] = path
-        if domain is not None:
-            self.cookies[key]['domain'] = domain
-        if secure:
-            self.cookies[key]['secure'] = True
-
-    def delete_cookie(self, key, path='/', domain=None):
-        self.set_cookie(key, max_age=0, path=path, domain=domain,
-                        expires='Thu, 01-Jan-1970 00:00:00 GMT')
-
     def _get_content(self):
         if self.has_header('Content-Encoding'):
             return ''.join(self._container)
@@ -604,4 +616,3 @@
         return unicode(s, encoding, 'replace')
     else:
         return s
-
Index: django/http/utils.py
===================================================================
--- django/http/utils.py	(revision 14693)
+++ django/http/utils.py	(working copy)
@@ -82,3 +82,13 @@
 
     return response
 
+def set_request_cookies(request, response):
+    """
+    Copy the cookies that were set via the request object to the 
+    response object where they'll be sent to the browser.
+    """
+    if hasattr(request, 'cookies'):
+        response.cookies.update(request.cookies)
+
+    return response
+
Index: django/core/handlers/base.py
===================================================================
--- django/core/handlers/base.py	(revision 14693)
+++ django/core/handlers/base.py	(working copy)
@@ -16,6 +16,7 @@
         http.conditional_content_removal,
         http.fix_IE_for_attach,
         http.fix_IE_for_vary,
+        http.set_request_cookies,
     ]
 
     def __init__(self):
Index: tests/regressiontests/requests/views.py
===================================================================
--- tests/regressiontests/requests/views.py	(revision 0)
+++ tests/regressiontests/requests/views.py	(revision 0)
@@ -0,0 +1,20 @@
+from django.http import HttpResponse
+
+
+def testing(request):
+    request.set_cookie('name', 'Inigo Montoya')
+    response = HttpResponse()
+    response.set_cookie('job', 'revenge')
+    return response
+
+def test_who_wins(request):
+    request.set_cookie('name', 'Bender Bending Rodriquez')
+    response = HttpResponse()
+    response.set_cookie('name', 'Zoidberg')
+    return response
+
+def delete_cookies(request):
+    request.delete_cookie('name')
+    response = HttpResponse()
+    response.delete_cookie('job')
+    return response
Index: tests/regressiontests/requests/tests.py
===================================================================
--- tests/regressiontests/requests/tests.py	(revision 14693)
+++ tests/regressiontests/requests/tests.py	(working copy)
@@ -4,7 +4,9 @@
 
 from django.core.handlers.modpython import ModPythonRequest
 from django.core.handlers.wsgi import WSGIRequest, LimitedStream
+from django.core.urlresolvers import reverse
 from django.http import HttpRequest, HttpResponse, parse_cookie
+from django.test import TestCase
 from django.utils import unittest
 from django.utils.http import cookie_date
 
@@ -147,3 +149,22 @@
     def test_read_by_lines(self):
         request = WSGIRequest({'REQUEST_METHOD': 'POST', 'wsgi.input': StringIO('name=value')})
         self.assertEqual(list(request), ['name=value'])
+
+
+class RequestCookiesTests(TestCase):
+    urls = "regressiontests.requests.urls"
+    
+    def test_setting_cookie(self):
+        res = self.client.get(reverse('cookies_testing'))
+        self.assertEqual('Inigo Montoya', self.client.cookies['name'].value)
+        self.assertEqual('revenge', self.client.cookies['job'].value)
+    
+    def test_delete_cookies(self):
+        self.test_setting_cookie()
+        self.client.get(reverse('cookies_delete'))
+        self.assertEqual('', self.client.cookies['name'].value)
+        self.assertEqual('', self.client.cookies['job'].value)
+    
+    def test_who_wins(self):
+        self.client.get(reverse('cookies_who_wins'))
+        self.assertEqual('Bender Bending Rodriquez', self.client.cookies['name'].value)
Index: tests/regressiontests/requests/urls.py
===================================================================
--- tests/regressiontests/requests/urls.py	(revision 0)
+++ tests/regressiontests/requests/urls.py	(revision 0)
@@ -0,0 +1,11 @@
+from django.conf.urls.defaults import *
+from django.http import HttpResponse
+
+from views import *
+
+
+urlpatterns = patterns('',
+    url(r'^testing/$', testing, name="cookies_testing"),
+    url(r'^delete_cookies/$', delete_cookies, name="cookies_delete"),
+    url(r'^test_who_wins/$', test_who_wins, name="cookies_who_wins"),
+)
\ No newline at end of file
Index: docs/ref/request-response.txt
===================================================================
--- docs/ref/request-response.txt	(revision 14693)
+++ docs/ref/request-response.txt	(working copy)
@@ -299,7 +299,23 @@
         for element in ET.iterparse(request):
             process(element)
 
+.. method:: HttpRequest.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None)
 
+    .. versionadded:: 1.3
+    
+    This method behaves identically to :meth:`HttpResponse.set_cookie()`.
+    
+    .. note:: Cookies set via ``reqeust.set_cookie()`` will overwrite ones with
+        the same ``key`` which were set in the same request-response cycle via
+        ``response.set_cookie()``.
+
+.. method:: HttpRequest.delete_cookie(key, path='/', domain=None)
+
+    .. versionadded:: 1.3
+    
+    This method behaves identically to :meth:`HttpResponse.delete_cookie()`.
+
+
 QueryDict objects
 -----------------
 
