[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Chicken-users] http egg and the Host request-header field
From: |
Drew Hess |
Subject: |
[Chicken-users] http egg and the Host request-header field |
Date: |
Sun, 22 Feb 2009 14:02:22 -0800 |
User-agent: |
Gnus/5.11 (Gnus v5.11) Emacs/22.3 (darwin) |
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)) ))
pgpcsTCyyEEFi.pgp
Description: PGP signature
- [Chicken-users] http egg and the Host request-header field,
Drew Hess <=