Ok, I think the attached patch has just about everything:
* exports *remove-duplicate-cookies-p*
* defaults *remove-duplicate-cookies-p* to T
* adds documentation referencing the RFC (available at
http://ryepup.unwashedmeme.com/blog/wp-content/uploads/2010/04/index.html)
Thanks,
Ryan
diff -ur -x '*.fasl' -x '.*' -x '*.patch' -x 'test*' -x '#*' -x 'sbcl*'
../drakma-1.1.0/cookies.lisp ./cookies.lisp
--- ../drakma-1.1.0/cookies.lisp 2009-12-01 17:06:56.000000000 -0500
+++ ./cookies.lisp 2010-04-07 11:26:32.000000000 -0400
@@ -258,6 +258,14 @@
(push (list (car name/value) (cdr name/value) parameters) result))))
(nreverse result)))
+(defvar *remove-duplicate-cookies-p* T
+ "Determines how duplicate cookies are handled. Valid values are:
+ * nil - duplicates will not be removed
+ * (T :KEEP-LAST) - for duplicates, only the last cookie value will be kept,
+ based on the order of the response header
+ * :KEEP-FIRST - for duplicates, only the first cookie value will be kept,
+ based on the order of the response header")
+
(defun get-cookies (headers uri)
"Returns a list of COOKIE objects corresponding to the
`Set-Cookie' header as found in HEADERS \(an alist as returned by
@@ -281,7 +289,13 @@
(parse-cookie-date expires))
:domain domain
:securep (not (not (parameter-present-p
"secure" parameters)))
- :http-only-p (not (not (parameter-present-p
"HttpOnly" parameters))))))
+ :http-only-p (not (not (parameter-present-p
"HttpOnly" parameters))))
+ into new-cookies
+ finally (return (ccase *remove-duplicate-cookies-p*
+ ((nil) new-cookies)
+ ((:keep-last t) (delete-duplicates new-cookies :test
#'cookie=))
+ (:keep-first (delete-duplicates new-cookies :test
#'cookie=
+ :from-end T))))))
(defun update-cookies (new-cookies cookie-jar)
"Updates the cookies in COOKIE-JAR by replacing those which are
diff -ur -x '*.fasl' -x '.*' -x '*.patch' -x 'test*' -x '#*' -x 'sbcl*'
../drakma-1.1.0/doc/index.html ./doc/index.html
--- ../drakma-1.1.0/doc/index.html 2009-12-01 17:44:55.000000000 -0500
+++ ./doc/index.html 2010-04-07 11:29:26.000000000 -0400
@@ -86,6 +86,7 @@
<li><a href="#delete-old-cookies"><code>delete-old-cookies</code></a>
<li><a
href="#*allow-dotless-cookie-domains-p*"><code>*allow-dotless-cookie-domains-p*</code></a>
<li><a
href="#*ignore-unparseable-cookie-dates-p*"><code>*ignore-unparseable-cookie-dates-p*</code></a>
+ <li><a
href="#*remove-duplicate-cookies-p*"><code>*remove-duplicate-cookies-p*</code></a>
</ol>
<li><a href="#headers">Headers</a>
<ol>
@@ -1323,6 +1324,59 @@
<!-- End of entry for *IGNORE-UNPARSEABLE-COOKIE-DATES-P* -->
+
+<!-- Entry for *REMOVE-DUPLICATE-COOKIES-P* -->
+
+<p><br>[Special variable]<br><a class=none
name='*remove-duplicate-cookies-p*'><b>*remove-duplicate-cookies-p*</b></a>
+<blockquote><br>
+Determines how duplicate cookies in the response are handled, defaults
+to <code>T</code>. Cookies are considered duplicate using
+<a href="#cookie="><code>COOKIE=</code></a>.
+
+Valid values are:
+<ul>
+ <li><code>NIL</code> - duplicates will not be removed</li>
+ <li><code>T</code> - for duplicates, only the last cookie value will
+ be kept, based on the order of the response header</li>
+ <li><code>:KEEP-LAST</code> - for duplicates, only the last cookie
+ value will be kept, based on the order of the response header</li>
+ <li><code>:KEEP-FIRST</code> - for duplicates, only the first cookie
+ value will be kept, based on the order of the response header</li>
+</ul>
+
+Misbehaving servers may send duplicate cookies back in the same
+<code>Set-Cookie</code> header:
+<pre>
+HTTP/1.1 200 OK
+Server: My-hand-rolled-server
+Date: Wed, 07 Apr 2010 15:12:30 GMT
+Connection: Close
+Content-Type: text/html
+Content-Length: 82
+Set-Cookie: a=1; Path=/; Secure, a=2; Path=/; Secure
+</pre>
+<p>
+In this case Drakma has to choose whether cookie "a" has the value
+"1" or "2". By default, Drakma will choose the last value specified,
+in this case "2".
+</p>
+<p>
+By default, Drakma conforms to <a
href="http://www.ietf.org/rfc/rfc2109.txt">RFC2109 HTTP State
+Management Mechanism</a>, section 4.3.3 Cookie Management:
+<blockquote><em>
+If a user agent receives a Set-Cookie response header whose NAME is
+the same as a pre-existing cookie, and whose Domain and Path
+attribute values exactly (string) match those of a pre-existing
+cookie, the new cookie supersedes the old.</em>
+</blockquote>
+</p>
+
+</blockquote>
+
+<!-- End of entry for *REMOVE-DUPLICATE-COOKIES-P* -->
+
+
+
<h4><a name="headers" class=none>Headers</a></h4>
This section assembles a couple of convenience functions which can be
diff -ur -x '*.fasl' -x '.*' -x '*.patch' -x 'test*' -x '#*' -x 'sbcl*'
../drakma-1.1.0/packages.lisp ./packages.lisp
--- ../drakma-1.1.0/packages.lisp 2009-02-09 09:53:01.000000000 -0500
+++ ./packages.lisp 2010-04-07 11:32:04.000000000 -0400
@@ -36,6 +36,7 @@
(:shadow :syntax-error :parameter-error)
(:export :*allow-dotless-cookie-domains-p*
:*body-format-function*
+ :*remove-duplicate-cookies-p*
:*drakma-default-external-format*
:*header-stream*
:*ignore-unparseable-cookie-dates-p*
_______________________________________________
drakma-devel mailing list
[email protected]
http://common-lisp.net/cgi-bin/mailman/listinfo/drakma-devel