2008/5/19 Edi Weitz <[EMAIL PROTECTED]>:
> On Mon, 19 May 2008 15:57:21 +0100, "Dave Lambert" <[EMAIL PROTECTED]> wrote:
>
>> I need to contact HTTPS servers through a proxy.  I've managed to
>> get this to work by having the http-request function issue an HTTP
>> CONNECT commmand in order to tunnel SSL through the proxy: the patch
>> is below (against 0.11.5).  On the downside, it only works for
>> Lispworks.

> Drakma's (limited) proxy functionality didn't work for you?

Drakma's HTTP proxy support is just great, but I also need to create an
HTTPS connection from behind a firewall.  This patch adds just that
HTTPS functionality.

There was a previous request for this on the mailing list:

http://common-lisp.net/pipermail/drakma-devel/2007-November/000212.html

> Is this based on some standard or does it cater to one specific
> server?

The approach is standard: Use the HTTP CONNECT method to get a tunnel
through the proxy, and then send SSL on the same connection.  It's
covered in HTTP 1.1:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.9

I've tested it on my local proxy, and a couple of HTTPS end points.

> Whatever email app you used ruined the patch.  Can you send it as an
> attachment or with another program?

That's a shame (it's Gmail).  Patch attached this time.

Cheers,
Dave
diff --git a/request.lisp b/request.lisp
index f56a113..eb779d5 100755
--- a/request.lisp
+++ b/request.lisp
@@ -416,7 +416,8 @@ LispWorks 5.0 or higher."
               (t
                (setq content (alist-to-url-encoded-string parameters external-format-out)
                      content-type "application/x-www-form-urlencoded")))))
-    (let (http-stream must-close done)
+    (let ((proxying-https? (and proxy (eq :https (puri:uri-scheme uri))))
+          http-stream raw-http-stream must-close done)
       (unwind-protect
           (progn
             (let ((host (or (and proxy (first proxy))
@@ -424,8 +425,8 @@ LispWorks 5.0 or higher."
                   (port (cond (proxy (second proxy))
                               ((uri-port uri))
                               (t (default-port uri))))
-                  (use-ssl (or force-ssl
-                               (eq (uri-scheme uri) :https))))
+                  (use-ssl (and (not proxying-https?)
+                                (or force-ssl (eq (uri-scheme uri) :https)))))
               #+(and :lispworks5.0 :mswindows
                      (not :lw-does-not-have-write-timeout))
               (when use-ssl
@@ -445,6 +446,7 @@ LispWorks 5.0 or higher."
                                     #-:lispworks
                                     (usocket:socket-stream
                                      (usocket:socket-connect host port :element-type 'octet))))
+              (setq raw-http-stream http-stream)
               (when (and use-ssl
                          ;; don't attach SSL to existing streams
                          (not stream))
@@ -473,6 +475,24 @@ LispWorks 5.0 or higher."
                        (format http-stream "~?~C~C" fmt args #\Return #\Linefeed))
                      (write-header (name value-fmt &rest value-args)
                        (write-http-line "~A: ~?" name value-fmt value-args)))
+              (when proxying-https?
+                ;; Setup a tunnel through the proxy server to the
+                ;; final destination.
+                (write-http-line "CONNECT ~A:~A HTTP/1.1" (puri:uri-host uri)
+                                 (or (puri:uri-port uri) 443))
+                (write-http-line "Host: ~A:~A" (puri:uri-host uri)
+                                 (or (puri:uri-port uri) 443))
+                (write-http-line "")
+                (force-output http-stream)
+                ;; Check we get a 200 response before proceeding.
+                (let ((line (read-status-line http-stream *header-stream*)))
+                  (unless (eq (second line) 200)
+                    (error "Unable to establish HTTPS tunnel through proxy.")))
+                ;; Got a connection. We have to read a blank line,
+                ;; turn on SSL, and then we can transmit.
+                (read-line* http-stream)
+                #+:lispworks
+                (comm:attach-ssl raw-http-stream :ssl-side :client))
               (when (and (not parameters-used-p)
                          parameters)
                 (setf (uri-query uri)
_______________________________________________
drakma-devel mailing list
drakma-devel@common-lisp.net
http://common-lisp.net/cgi-bin/mailman/listinfo/drakma-devel

Reply via email to