Update of /project/cl-soap/cvsroot/cl-soap/src
In directory common-lisp.net:/tmp/cvs-serv23294/src
Modified Files:
http-client.lisp
Log Message:
added https support for lispworks
Date: Thu Sep 15 15:30:44 2005
Author: scaekenberghe
Index: cl-soap/src/http-client.lisp
diff -u cl-soap/src/http-client.lisp:1.4 cl-soap/src/http-client.lisp:1.5
--- cl-soap/src/http-client.lisp:1.4 Wed Sep 14 09:30:02 2005
+++ cl-soap/src/http-client.lisp Thu Sep 15 15:30:44 2005
@@ -1,6 +1,6 @@
;;;; -*- mode: lisp -*-
;;;;
-;;;; $Id: http-client.lisp,v 1.4 2005/09/14 07:30:02 scaekenberghe Exp $
+;;;; $Id: http-client.lisp,v 1.5 2005/09/15 13:30:44 scaekenberghe Exp $
;;;;
;;;; A basic HTTP client, somewhat API compatible with portableaserve's do-http-request
;;;; Copied from another project (basic authorization support removed)
@@ -21,10 +21,14 @@
(defclass http-client-state ()
((data :initform nil)))
-(defvar *default-http-client-state* (make-instance 'http-client-state))
+(defun make-http-client-state ()
+ "Make a new HTTP client state object to hold open (keepalive) connections"
+ (make-instance 'http-client-state))
+
+(defvar *default-http-client-state* (make-http-client-state))
(defclass http-server-state ()
- ((host-port :accessor get-host-port :initarg :host-port)
+ ((scheme-host-port :accessor get-scheme-host-port :initarg :scheme-host-port)
(socket :accessor get-socket :initarg :socket :initform nil)))
;; low level output
@@ -99,16 +103,17 @@
;; connection / server state management
-(defmethod get-http-server-state ((http-client-state http-client-state) host-port)
+(defmethod get-http-server-state ((http-client-state http-client-state) scheme-host-port)
(with-slots (data)
http-client-state
- (let ((server-state (find host-port data :key #'get-host-port :test #'string-equal)))
+ (let ((server-state (find scheme-host-port data :key #'get-scheme-host-port :test #'string-equal)))
(unless server-state
- (push (setf server-state (make-instance 'http-server-state :host-port host-port))
+ (push (setf server-state (make-instance 'http-server-state :scheme-host-port scheme-host-port))
data))
server-state)))
(defmethod close-all-connections ((http-client-state http-client-state) &key abort)
+ "Close all open connections in http-client-state (optionaly aborting them)"
(with-slots (data)
http-client-state
(dolist (http-server-state data)
@@ -116,30 +121,36 @@
(when connection
(ignore-errors (close connection :abort abort)))))))
-(defun open-socket-stream (host port)
- #+lispworks (comm:open-tcp-stream host port)
- #+openmcl (ccl:make-socket :remote-host host :remote-port port)
- #+clisp (socket:socket-connect port host)
- #+cmu (sys:make-fd-stream (ext:connect-to-inet-socket host port) :input t :output t :buffering :none)
- #+sbcl (let ((socket (make-instance 'sb-bsd-sockets:inet-socket :type :stream :protocol :tcp)))
- (sb-bsd-sockets:socket-connect socket
- (car
- (sb-bsd-sockets:host-ent-addresses
- (sb-bsd-sockets:get-host-by-name host)))
- port)
- (sb-bsd-sockets:socket-make-stream socket :element-type 'character :input t :output t :buffering :none)))
+(defun open-socket-stream (scheme host port)
+ #+lispworks (ecase scheme
+ (:http (comm:open-tcp-stream host port))
+ (:https (comm:open-tcp-stream host port :ssl-ctx t)))
+ #+openmcl (when (eql scheme :http)
+ (ccl:make-socket :remote-host host :remote-port port))
+ #+clisp (when (eql scheme :http)
+ (socket:socket-connect port host))
+ #+cmu (when (eql scheme :http)
+ (sys:make-fd-stream (ext:connect-to-inet-socket host port) :input t :output t :buffering :none))
+ #+sbcl (when (eql scheme :http)
+ (let ((socket (make-instance 'sb-bsd-sockets:inet-socket :type :stream :protocol :tcp)))
+ (sb-bsd-sockets:socket-connect socket
+ (car
+ (sb-bsd-sockets:host-ent-addresses
+ (sb-bsd-sockets:get-host-by-name host)))
+ port)
+ (sb-bsd-sockets:socket-make-stream socket :element-type 'character :input t :output t :buffering :none))))
-(defun get-open-connection (host port state &key force-new)
+(defun get-open-connection (scheme host port state &key force-new)
(if state
- (let* ((host-port (format nil "~a:~d" host port))
- (server-state (get-http-server-state state host-port))
+ (let* ((scheme-host-port (format nil "~a://~a:~d" scheme host port))
+ (server-state (get-http-server-state state scheme-host-port))
(connection (get-socket server-state)))
(if (and connection (open-stream-p connection) (not force-new))
(values connection :keep-alive)
(progn
(when connection (ignore-errors (close connection)))
- (values (setf (get-socket server-state) (open-socket-stream host port)) :new))))
- (values (open-socket-stream host port) :new)))
+ (values (setf (get-socket server-state) (open-socket-stream scheme host port)) :new))))
+ (values (open-socket-stream scheme host port) :new)))
;; high level HTTP protocol
@@ -167,7 +178,9 @@
content content-type
headers)
"Write an HTTP request, full header and body, to stream"
- (format-http-request-line stream "~a ~a~@[?~a~] HTTP/1.1" method (puri:uri-path uri) (puri:uri-query uri))
+ (format-http-request-line stream
+ "~a ~a~@[?~a~] HTTP/1.1"
+ method (if (puri:uri-path uri) (puri:uri-path uri) "/") (puri:uri-query uri))
(format-http-request-line stream "Host: ~a:~d" (puri:uri-host uri) (puri:uri-port uri))
(format-http-request-line stream "User-Agent: ~a" *http-client-agent*)
(format-http-request-line stream "Accept: ~a" *http-client-accept*)
@@ -206,11 +219,15 @@
(declare (ignore proxy))
(assert (member method '(:get :put :post :delete :head)))
(setf uri (puri:parse-uri uri))
- (let* ((host (puri:uri-host uri))
- (port (or (puri:uri-port uri) (setf (puri:uri-port uri) 80))))
+ (let* ((scheme (puri:uri-scheme uri))
+ (host (puri:uri-host uri))
+ (port (or (puri:uri-port uri)
+ (setf (puri:uri-port uri) (ecase scheme
+ (:http 80)
+ (:https 443))))))
(multiple-value-bind (connection keep-alive)
;; state could hold an open (kept alive) connection to host:port
- (get-open-connection host port state)
+ (get-open-connection scheme host port state)
(flet ((execute-request-response ()
(values-list `(,@(multiple-value-list
(do-one-request-response connection uri method
@@ -225,7 +242,7 @@
((or stream-error #+lispworks comm:socket-error) ()
(when keep-alive
(setf keep-alive :new
- connection (get-open-connection host port state :force-new t))
+ connection (get-open-connection scheme host port state :force-new t))
(execute-request-response))))
(unless state (close connection)))))))