Re: Cannot have multiple Set-Cookie headers in response

Jacob Smullyan <[email protected]>
Newsgroups gmane.comp.web.skunkweb
Message-ID <[email protected]>
I've checked in a fix to SkunkWeb/Services/httpd/protocol.py.
Attached are two diffs, against CVS and against 3.4b5.

js


On Sat, Nov 22, 2003 at 11:16:54AM -0500, Jacob Smullyan wrote:
> I've verified that the problem is with httpd.  Here is the same page
> (which puts two cookies in the response), first with mod_skunkweb,
> then with httpd:
> 
> # wget -q -O- -s http://localhost/cookietest.html
> HTTP/1.1 200 OK
> Date: Sat, 22 Nov 2003 16:11:48 GMT
> Server: Apache/2.0.48 (Gentoo/Linux) mod_ssl/2.0.48 OpenSSL/0.9.6k DAV/2 SVN/0.31.0 SkunkWeb/3.4b5
> Etag: mNmJNYtGMbTH2rUrZKTrWw==
> Set-Cookie: a=4;
> Set-Cookie: b=4;
> Content-Length: 13
> Keep-Alive: timeout=15, max=100
> Connection: Keep-Alive
> Content-Type: text/html; charset=ISO-8859-1
> 
> 
> 
> cookie set.
> 
> 
> # wget -q -O- -s http://localhost:8080/cookietest.html
> HTTP/1.0 200 OK
> Content-Length: 13
> Etag: mNmJNYtGMbTH2rUrZKTrWw==
> Date: Sat, 22 Nov 2003 16:12:52 GMT
> Set-Cookie: b=4;
> Content-Type: text/html
> Server: SkunkWeb 3.4b5
> 
> 
> 
> cookie set.
> 
> 
> Fix will follow shortly.
> 
> js
> 
> On Sat, Nov 22, 2003 at 08:23:49AM -0500, Jacob Smullyan wrote:
> > On Fri, Nov 21, 2003 at 10:37:46PM -0800, Dan Chow wrote:
> > > I'm new to skunkweb and have been building my website with it.  Skunkweb
> > > is pretty cool, but I ran into a problem that I saw that someone had
> > > posted and then said it might be resolved. But I still see that behavior.
> > > I'm using Skunkweb 3.4b5 with python 2.3.2 on a redhat 9.0 linux box.  The
> > > problem I am seeing is that if I try to set multiple cookies in a single
> > > response, my browser (mozilla1.5) shows that only one is set.  Also,
> > > when I use tcptrace, I only see the second cookie being sent over the
> > > wire.  My test is the following:
> > > 
> > > foo.html:
> > > =========
> > > <:component /en/foo.pycomp connection=`CONNECTION`:>
> > > <html>
> > > Cookies sent
> > > </html>
> > > 
> > > foo.pycomp:
> > > ===========
> > > # put in two cookies and see which is set
> > > connection.responseCookie["cookie1"] = "test1"
> > > connection.responseCookie["cookie2"] = "test2"
> > > 
> > > foo.html calls foo.pycomp which sets two session cookies.  And returns
> > > some html.  I get back the page, but only one cookie is set.
> > > 
> > > I've looked at Cookie.py and that doesn't seem to be the problem
> > > Also invoking skunkweb's
> > > HTTPConnection.response method in lib/Services/web/protocol.py returns
> > > both cookies in the response, so I am at a loss as to what is happening.
> > 
> > Thanks for bringing this to my attention.  If it has been brought up
> > before, it went by me completely, or I'd have fixed it.  
> > 
> > I believe you must be using the httpd service and that that is where
> > the bug lies.  If you use apache/mod_skunkweb, I think you'll get both
> > Set-Cookie lines.
> > 
> > The bug is that httpd currently takes the response headers and turns
> > them back into a dictionary, discarding duplicate keys (see
> > httpd.protocol._getHeaderDict).  This is just plain wrong, obviously,
> > so I'll try to get a fix out later today. 
> > 
> > js
> 
>
DIFF_CVS (text/plain, 1.3 KB)
Index: protocol.py
===================================================================
RCS file: /cvsroot/skunkweb/skunkweb/SkunkWeb/Services/httpd/protocol.py,v
retrieving revision 1.11
diff -c -r1.11 protocol.py
*** protocol.py	8 Sep 2003 00:49:20 -0000	1.11
--- protocol.py	22 Nov 2003 16:35:23 -0000
***************
*** 471,479 ****
          if not server:
              respp['server'] = 'SkunkWeb %s' % Configuration.SkunkWebVersion
          resl = ["%s %s" % (httpVersion, status)]
!         for k,v in respp.items():
!             resl.append("%s: %s" % (self._fixHeader(k), v))
!         return "\r\n".join(resl)+"\r\n\r\n"+respp.fp.read()
          
      def marshalException(self, exc_text, sessionDict):
          res=RequestFailed(constants.WEB_JOB, exc_text, sessionDict)
--- 471,481 ----
          if not server:
              respp['server'] = 'SkunkWeb %s' % Configuration.SkunkWebVersion
          resl = ["%s %s" % (httpVersion, status)]
!         for k in respp.keys():
!             kf=self._fixHeader(k)
!             for v in respp.getheaders(k):
!                 resl.append("%s: %s" % (kf, v))
!         return "%s\r\n\r\n%s" % ("\r\n".join(resl), respp.fp.read())
          
      def marshalException(self, exc_text, sessionDict):
          res=RequestFailed(constants.WEB_JOB, exc_text, sessionDict)
DIFF_34b5 (text/plain, 2.8 KB)
Index: protocol.py
===================================================================
RCS file: /cvsroot/skunkweb/skunkweb/SkunkWeb/Services/httpd/protocol.py,v
retrieving revision 1.10
retrieving revision 1.12
diff -c -r1.10 -r1.12
*** protocol.py	7 Jun 2003 20:50:06 -0000	1.10
--- protocol.py	22 Nov 2003 16:38:09 -0000	1.12
***************
*** 5,11 ****
  #      Public License or the SkunkWeb License, as specified in the
  #      README file.
  #   
! # $Id: protocol.py,v 1.10 2003/06/07 20:50:06 smulloni Exp $
  # Time-stamp: <01/05/04 13:27:08 smulloni>
  ########################################################################
  
--- 5,11 ----
  #      Public License or the SkunkWeb License, as specified in the
  #      README file.
  #   
! # $Id: protocol.py,v 1.12 2003/11/22 16:38:09 smulloni Exp $
  # Time-stamp: <01/05/04 13:27:08 smulloni>
  ########################################################################
  
***************
*** 17,22 ****
--- 17,23 ----
  import exceptions
  import re
  import socket
+ from urllib import unquote
  
  ##NEW
  import rfc822
***************
*** 197,203 ****
                #'AUTH_TYPE' : '',
                # this may need to be fudged later too
                # (for index documents, for instance)
!               'SCRIPT_NAME' : match.group('path'), 
                'QUERY_STRING' : match.group('query') or '',
                'REMOTE_ADDR' : peeraddress,
                'REMOTE_PORT' : peerport }
--- 198,204 ----
                #'AUTH_TYPE' : '',
                # this may need to be fudged later too
                # (for index documents, for instance)
!               'SCRIPT_NAME' : unquote(match.group('path')), 
                'QUERY_STRING' : match.group('query') or '',
                'REMOTE_ADDR' : peeraddress,
                'REMOTE_PORT' : peerport }
***************
*** 470,478 ****
          if not server:
              respp['server'] = 'SkunkWeb %s' % Configuration.SkunkWebVersion
          resl = ["%s %s" % (httpVersion, status)]
!         for k,v in respp.items():
!             resl.append("%s: %s" % (self._fixHeader(k), v))
!         return "\r\n".join(resl)+"\r\n\r\n"+respp.fp.read()
          
      def marshalException(self, exc_text, sessionDict):
          res=RequestFailed(constants.WEB_JOB, exc_text, sessionDict)
--- 471,481 ----
          if not server:
              respp['server'] = 'SkunkWeb %s' % Configuration.SkunkWebVersion
          resl = ["%s %s" % (httpVersion, status)]
!         for k in respp.keys():
!             kf=self._fixHeader(k)
!             for v in respp.getheaders(k):
!                 resl.append("%s: %s" % (kf, v))
!         return "%s\r\n\r\n%s" % ("\r\n".join(resl), respp.fp.read())
          
      def marshalException(self, exc_text, sessionDict):
          res=RequestFailed(constants.WEB_JOB, exc_text, sessionDict)
signature.asc (application/pgp-signature, 189 B)
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (GNU/Linux)

iD8DBQE/v5KEuqamFyFXXLIRAhO0AJ90GXCtrFG6b2zV0FEDU3gNG02+2wCfUu6E
bL+7el9b6BlzkwXL/m6gu4g=
=+Gdw
-----END PGP SIGNATURE-----
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.