Package: guile Version: 2.0.3 Tags: patch On 6 November 2011 13:49, R. P. Dillon <rpdil...@gmail.com> wrote: > (use-modules (web request) (web response) (web uri) (rnrs bytevectors)) > (define port (socket PF_INET SOCK_STREAM 0)) > (define address (addrinfo:addr (car (getaddrinfo "www.google.com" "http")))) > (connect port address) > (define request (build-request (build-uri 'http #:host "www.google.com"))) > (write-request request port) > (define response (read-response port)) > (read-response ...) consistently fails with Google: > web/http.scm:754:6: In procedure parse-asctime-date: > web/http.scm:754:6: Throw to key `bad-header' with args `(date "-1")'. > The expiration is set to -1 in the headers, and this seems to cause a > problem for the web libraries in Guile. > This same request seems to work well for my own domain (killring.org).
This is definitely a bug on Guile's part, HTTP/1.1 permits such values for "Expires" headers [1], treating them as though they were a date in the past: HTTP/1.1 clients and caches MUST treat other invalid date formats, especially including the value "0", as in the past (i.e., "already expired"). [1] http://tools.ietf.org/html/rfc2616#section-14.21 Attached patch permits non-date values for "Expires", leaving them as strings (preferable, as such responses can be transparently forwarded to other clients). The staleness of a response could be determined quite crudely, e.g. (define (response-stale? r) (let ((expires (response-expires r))) (and expires (or (not (date? expires)) ;; Indicates already expired. (time<=? (date->time-utc expires) (current-time)))))) This approach completely ignores the recommended way of determining whether a response has expired. See section 13.2.4 of the RFC for calculations involving various factors such as the time that a request was sent, "Cache-Control" directives, etc. Regards Daniel
From dcbcd94db89a8e73ebc3089a860575bbeb8d1708 Mon Sep 17 00:00:00 2001 From: Daniel Hartwig <mand...@gmail.com> Date: Sun, 27 Nov 2011 18:25:55 +0800 Subject: [PATCH] Permit non-date values for "Expires" header. * module/web/http.scm ("Expires"): Permit non-date values. --- module/web/http.scm | 20 +++++++++++++++++++- test-suite/tests/web-http.test | 1 + 2 files changed, 20 insertions(+), 1 deletions(-) diff --git a/module/web/http.scm b/module/web/http.scm index dc742a1..5eb2e90 100644 --- a/module/web/http.scm +++ b/module/web/http.scm @@ -1500,7 +1500,25 @@ phrase\"." ;; Expires = HTTP-date ;; -(declare-date-header! "Expires") +;; ... +;; HTTP/1.1 clients and caches MUST treat other invalid date formats, +;; especially including the value "0", as in the past (i.e., "already +;; expired"). +;; +(declare-header! "Expires" + (lambda (str) + (or (false-if-exception (parse-date str)) + str)) + (lambda (val) + (or (string? val) (date? val))) + (lambda (val port) + (cond + ((string? val) + (display val port)) + ((date? val) + (write-date val port)) + (else + (bad-header-component 'expires val))))) ;; Last-Modified = HTTP-date ;; diff --git a/test-suite/tests/web-http.test b/test-suite/tests/web-http.test index b6abbf3..c881223 100644 --- a/test-suite/tests/web-http.test +++ b/test-suite/tests/web-http.test @@ -134,6 +134,7 @@ (pass-if-parse expires "Tue, 15 Nov 1994 08:12:31 GMT" (string->date "Tue, 15 Nov 1994 08:12:31 +0000" "~a, ~d ~b ~Y ~H:~M:~S ~z")) + (pass-if-parse expires "0" "0") (pass-if-parse last-modified "Tue, 15 Nov 1994 08:12:31 GMT" (string->date "Tue, 15 Nov 1994 08:12:31 +0000" "~a, ~d ~b ~Y ~H:~M:~S ~z"))) -- 1.7.2.5