Hi, The HTTP/1.1 spec states that in the Host request-header field, the port designation is optional if the default port is used for the request. Chicken Scheme's http egg always sends the port, but some petulant web servers don't like that.
Here are a couple of examples. Each of the examples demonstrates communication with a URL "shortening" service, ala TinyURL. The request headers shown here in my examples are what the http egg sends when you do something like this: (http:send-request (http:make-request 'HEAD "http://grf.me/Xs3")) In this first example, grf.me responds that the URL doesn't exist: % telnet grf.me 80 Trying 209.67.188.9... Connected to grf.me. Escape character is '^]'. HEAD /Xs3 HTTP/1.0 Host: grf.me:80 Content-Length: 0 HTTP/1.1 404 Not Found Cache-Control: private Content-Length: 5165 Content-Type: text/html; charset=utf-8 Server: Microsoft-IIS/7.0 X-AspNet-Version: 2.0.50727 X-Powered-By: ASP.NET Date: Sun, 22 Feb 2009 21:37:54 GMT Connection: close Connection closed by foreign host. But when you send the Host header without the port, it works fine: % telnet grf.me 80 Trying 209.67.188.9... Connected to grf.me. Escape character is '^]'. HEAD /Xs3 HTTP/1.0 Host: grf.me Content-Length: 0 HTTP/1.1 301 Moved Permanently Cache-Control: private Content-Length: 0 Location: http://inthegraph.com/grfme/index/Xs3 Server: Microsoft-IIS/7.0 X-AspNet-Version: 2.0.50727 X-Powered-By: UrlRewriter.NET 2.0.0 X-Powered-By: ASP.NET Date: Sun, 22 Feb 2009 21:40:42 GMT Connection: close Connection closed by foreign host. The results are the same for GET requests, and for HTTP/1.1 requests. In the second example, ping.fm responds with a redirect, but it redirects to the same URL, which causes an infinite loop if you're trying to follow redirections to the terminal URL: % telnet ping.fm 80 Trying 69.44.44.70... Connected to ping.fm. Escape character is '^]'. HEAD /LqHrn HTTP/1.0 Host: ping.fm:80 Content-Length: 0 HTTP/1.1 301 Moved Permanently Date: Sun, 22 Feb 2009 21:32:18 GMT Server: Apache Location: http://ping.fm/LqHrn Connection: close Content-Type: text/html; charset=iso-8859-1 Connection closed by foreign host. Here it is without the port: telnet ping.fm 80 Trying 69.44.44.70... Connected to ping.fm. Escape character is '^]'. HEAD /LqHrn HTTP/1.0 Host: ping.fm Content-Length: 0 HTTP/1.1 301 Moved Permanently Date: Sun, 22 Feb 2009 21:42:06 GMT Server: Apache Location: http://www.technologyreview.com/computing/22194/ Content-Type: text/html; charset=UTF-8 ^C Connection closed by foreign host. That gives the proper Location. Because the http egg always applies the port to the Host header, there's no workaround for these broken web apps. Attached is a patch for http so that it elides the port when it's the default. thanks! d
diff -urN http/http-client.scm http-dhess/http-client.scm
--- http/http-client.scm 2009-02-06 12:16:19.000000000 -0800
+++ http-dhess/http-client.scm 2009-02-22 13:20:50.000000000 -0800
@@ -195,6 +195,10 @@
(display (car fragments))
(loop (cdr fragments) #t)))))
+(define (default-port? serv port)
+ (or (and (string=? serv "http") (= port 80))
+ (and (string=? serv "https") (= port 443))))
+
(define (http:send-request req . more)
(let-optionals more ([in #f]
[out #f] )
@@ -224,8 +228,11 @@
(if (= port 80) "" (conc ":" port))
path " " proto "\r\n"))
(set! result (string-append method " " path " " proto
- "\r\nHost: " host ":"
- (->string port) "\r\n")))
+ "\r\nHost: " host
+ (if (default-port? serv port)
+ ""
+ (conc ":" port))
+ "\r\n")))
(for-each
(lambda (a)
(set! result (sprintf "~A~A: ~A\r\n" result (car a) (cdr a)) ))
pgpf0HZNBhwvu.pgp
Description: PGP signature
_______________________________________________ Chicken-users mailing list [email protected] http://lists.nongnu.org/mailman/listinfo/chicken-users
