Re: [patch] hacking HTTP::Daemon to handle CONNECT properly

Gisle Aas (gisle@activestate.com)
04 Mar 2001 22:49:13 -0800


merlyn@stonehenge.com (Randal L. Schwartz) writes:

> HTTP::Daemon 1.22 ->get_request passes the URL-like string following
> the method to make a relative based URL.  For "CONNECT" methods, this
> is wrong, since no scheme is present and a hostname:port combo can
> sometimes look like a scheme:hostname combo.

Agree.  RFC 2068 says:

| Request-Line   = Method SP Request-URI SP HTTP-Version CRLF
| Request-URI    = "*" | absoluteURI | abs_path | authority

...

| The authority form is only used by the CONNECT method (section 9.9).

...

| 9.9 CONNECT
|
|   This specification reserves the method name CONNECT for use with a
|   proxy that can dynamically switch to being a tunnel (e.g. SSL
|   tunneling [44]).

> My patch is a bit of a hack, adding in the "telnet:" scheme when
> CONNECT is used, but it seems to work nicely with the proxy server I'm
> creating.

My only concern with using telnet is that it make the port default to
23 if no port is specified.  The 'authority' production seems to allow
that.  It might be better to simply reuse 'http'.  Is there any real
spec for how CONNECT is supposed to work and what should happen when
port is missing?

> The non-upward compatibility warning is that you must now call
> $request->url->host_port to get the host/port string for CONNECT,
> rather than calling $request->url and using the entire string.  Since
> I'm probably one of three people in the world doing this, I think it's
> probably safe to just document that. :)

I agree that the risk with this patch should be acceptable.  Do you
want to resend it with a doc update.

Regards,
Gisle

> Here's the patch:
> 
> --- /usr/lib/perl5/site_perl/5.005/HTTP/Daemon.pm	Thu Jan  4 13:43:10 2001
> +++ Daemon.pm	Sun Mar  4 13:50:22 2001
> @@ -253,7 +253,11 @@
>  	return;
>      }
>      my $proto = $3 || "HTTP/0.9";
> -    my $r = HTTP::Request->new($1, $HTTP::URI_CLASS->new($2, $self->daemon->url));
> +    my $r = 
> +      HTTP::Request->new($1,
> +			 $1 eq "CONNECT" ?
> +			 $HTTP::URI_CLASS->new("telnet://$2") :
> +			 $HTTP::URI_CLASS->new($2, $self->daemon->url));
>      $r->protocol($proto);
>      ${*$self}{'httpd_client_proto'} = $proto = _http_version($proto);