From scaekenberghe at common-lisp.net Wed Jun 9 09:02:08 2004 From: scaekenberghe at common-lisp.net (Sven Van Caekenberghe) Date: Wed, 09 Jun 2004 02:02:08 -0700 Subject: [s-xml-rpc-cvs] CVS update: Module imported: public_html Message-ID: Update of /project/s-xml-rpc/cvsroot/public_html In directory common-lisp.net:/tmp/cvs-serv20456 Log Message: Project Creation Status: Vendor Tag: svc Release Tags: start N public_html/index.html N public_html/style.css No conflicts created by this import Date: Wed Jun 9 02:02:08 2004 Author: scaekenberghe New module public_html added From scaekenberghe at common-lisp.net Wed Jun 9 09:02:41 2004 From: scaekenberghe at common-lisp.net (Sven Van Caekenberghe) Date: Wed, 09 Jun 2004 02:02:41 -0700 Subject: [s-xml-rpc-cvs] CVS update: Module imported: s-xml-rpc Message-ID: Update of /project/s-xml-rpc/cvsroot/s-xml-rpc In directory common-lisp.net:/tmp/cvs-serv20900 Log Message: Project Creation Status: Vendor Tag: svc Release Tags: start N s-xml-rpc/Makefile N s-xml-rpc/s-xml-rpc.asd N s-xml-rpc/src/aserve.lisp N s-xml-rpc/src/base64.lisp N s-xml-rpc/src/package.lisp N s-xml-rpc/src/sysdeps.lisp N s-xml-rpc/src/validator1.lisp N s-xml-rpc/src/xml-rpc.lisp N s-xml-rpc/test/all-tests.lisp N s-xml-rpc/test/test-base64.lisp N s-xml-rpc/test/test-xml-rpc.lisp N s-xml-rpc/test/test.b64 No conflicts created by this import Date: Wed Jun 9 02:02:41 2004 Author: scaekenberghe New module s-xml-rpc added From rschlatte at common-lisp.net Sun Jun 13 14:14:47 2004 From: rschlatte at common-lisp.net (Rudi Schlatte) Date: Sun, 13 Jun 2004 07:14:47 -0700 Subject: [s-xml-rpc-cvs] CVS update: s-xml-rpc/src/xml-rpc.lisp s-xml-rpc/src/package.lisp Message-ID: Update of /project/s-xml-rpc/cvsroot/s-xml-rpc/src In directory common-lisp.net:/tmp/cvs-serv21201/src Modified Files: xml-rpc.lisp package.lisp Log Message: * src/package.lisp (s-xml-rpc-exports): New package -- don't export the whole common-lisp package by default ;) * src/xml-rpc.lisp (*xml-rpc-package*): ... use it. * src/xml-rpc.lisp (|system.listMethods|) (|system.methodSignature|, |system.methodHelp|): Added introspection methods, to be imported in *xml-rpc-package*. * src/package.lisp (s-xml-rpc): ... export them. * src/xml-rpc.lisp: Some indentation frobs. Date: Sun Jun 13 07:14:47 2004 Author: rschlatte Index: s-xml-rpc/src/xml-rpc.lisp diff -u s-xml-rpc/src/xml-rpc.lisp:1.1.1.1 s-xml-rpc/src/xml-rpc.lisp:1.2 --- s-xml-rpc/src/xml-rpc.lisp:1.1.1.1 Wed Jun 9 02:02:40 2004 +++ s-xml-rpc/src/xml-rpc.lisp Sun Jun 13 07:14:47 2004 @@ -1,6 +1,6 @@ ;;;; -*- mode: lisp -*- ;;;; -;;;; $Id: xml-rpc.lisp,v 1.1.1.1 2004/06/09 09:02:40 scaekenberghe Exp $ +;;;; $Id: xml-rpc.lisp,v 1.2 2004/06/13 14:14:47 rschlatte Exp $ ;;;; ;;;; This is a Common Lisp implementation of the XML-RPC protocol, ;;;; as documented on the website http://www.xmlrpc.com @@ -121,7 +121,7 @@ (let ((pair (assoc member (xml-rpc-struct-alist struct)))) (if pair (rplacd pair value) - (push (cons member value) (xml-rpc-struct-alist struct))) + (push (cons member value) (xml-rpc-struct-alist struct))) value)) (defun xml-rpc-struct (&rest args) @@ -130,9 +130,9 @@ (error "~s must contain an even number of elements" args)) (let (alist) (loop - (if (null args) - (return) - (push (cons (pop args) (pop args)) alist))) + (if (null args) + (return) + (push (cons (pop args) (pop args)) alist))) (make-xml-rpc-struct :alist alist))) (defun xml-rpc-struct-equal (struct1 struct2) @@ -145,7 +145,7 @@ (unless (equal (get-xml-rpc-struct-member struct2 (car assoc)) (cdr assoc)) (return-from xml-rpc-struct-equal nil))) - nil)) + nil)) ;;; encoding support @@ -204,6 +204,9 @@ "Encode an XML-RPC call with name and args as an XML string" (with-output-to-string (stream) (princ "" stream) + ;; Spec says: The string may only contain identifier characters, + ;; upper and lower-case A-Z, the numeric characters, 0-9, + ;; underscore, dot, colon and slash. (format stream "~a" (string name)) ; assuming name contains no special characters (when args (encode-xml-rpc-args args stream)) @@ -299,7 +302,7 @@ (defparameter *xml-rpc-proxy-port* nil "When not null, an integer specifying the XML-RPC proxy port to use") -(defparameter *xml-rpc-package* *package* +(defparameter *xml-rpc-package* (find-package :s-xml-rpc-exports) "Package for XML-RPC callable functions") (defparameter *xml-rpc-authorization* nil @@ -316,13 +319,13 @@ (defun tokens (string &key (start 0) (separators (list #\space #\return #\linefeed #\tab))) (if (= start (length string)) '() - (let ((p (position-if #'(lambda (char) (find char separators)) string :start start))) - (if p - (if (= p start) - (tokens string :start (1+ start) :separators separators) - (cons (subseq string start p) - (tokens string :start (1+ p) :separators separators))) - (list (subseq string start)))))) + (let ((p (position-if #'(lambda (char) (find char separators)) string :start start))) + (if p + (if (= p start) + (tokens string :start (1+ start) :separators separators) + (cons (subseq string start p) + (tokens string :start (1+ p) :separators separators))) + (list (subseq string start)))))) (defun format-header (stream headers) (mapc #'(lambda (header) @@ -334,18 +337,18 @@ (defun debug-stream (in) (if *xml-rpc-debug* (make-echo-stream in *standard-output*) - in)) + in)) ;;; client API (defun xml-rpc-call (encoded &key - (url *xml-rpc-url*) - (agent *xml-rpc-agent*) - (host *xml-rpc-host*) - (port *xml-rpc-port*) - (authorization *xml-rpc-authorization*) - (proxy-host *xml-rpc-proxy-host*) - (proxy-port *xml-rpc-proxy-port*)) + (url *xml-rpc-url*) + (agent *xml-rpc-agent*) + (host *xml-rpc-host*) + (port *xml-rpc-port*) + (authorization *xml-rpc-authorization*) + (proxy-host *xml-rpc-proxy-host*) + (proxy-port *xml-rpc-proxy-port*)) "Execute an already encoded XML-RPC call and return the decoded result" (let ((uri (if proxy-host (format nil "http://~a:~d~a" host port url) url))) (with-open-socket-stream (connection (if proxy-host proxy-host host) @@ -375,7 +378,7 @@ (let ((result (decode-xml-rpc (debug-stream connection)))) (if (typep result 'xml-rpc-fault) (error result) - (car result)))))) + (car result)))))) (defun call-xml-rpc-server (server-keywords name &rest args) "Encode and execute an XML-RPC call with name and args, using the list of server-keywords" @@ -401,18 +404,64 @@ :port port :url url)))) + ;;; server API +(defparameter +xml-rpc-method-characters+ + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.:/") + +(defun valid-xml-rpc-method-name-p (method-name) + (not (find-if-not (lambda (c) (find c +xml-rpc-method-characters+)) + method-name))) + +(defun find-xml-rpc-method (method-name) + "Looks for a method with the given name in *xml-rpc-package*, + except that colons in the name get converted to hyphens." + (let ((sym (find-symbol method-name *xml-rpc-package*))) + (if (fboundp sym) sym nil))) + +;;; Introspection methods from http://xmlrpc.usefulinc.com/doc/reserved.html +;;; To be imported in *xml-rpc-package*. + +(defun |system.listMethods| () + "List the methods that are available on this server." + (let ((result nil)) + (do-symbols (sym *xml-rpc-package* (sort result #'string-lessp)) + (when (and (fboundp sym) (valid-xml-rpc-method-name-p (symbol-name sym))) + (push (symbol-name sym) result))))) + +(defun |system.methodSignature| (method-name) + "Dummy system.methodSignature implementation. There's no way + to get (and no concept of) required argument types in Lisp, so + this function always returns nil or errors." + (let ((method (find-xml-rpc-method method-name))) + (if method + ;; http://xmlrpc.usefulinc.com/doc/sysmethodsig.html says to + ;; return a non-array if the signature is not available + nil + (error "Method ~A not found." method-name)))) + +(defun |system.methodHelp| (method-name) + "Returns the function documentation for the given method." + (let ((method (find-xml-rpc-method method-name))) + (if method + (or (documentation method 'function) "") + (error "Method ~A not found." method-name)))) + (defun execute-xml-rpc-call (method-name &rest arguments) - "Intern method-name in *xml-rpc-package* and apply that function on arguments" - (apply (intern method-name *xml-rpc-package*) - arguments)) + "Execute method METHOD-NAME on ARGUMENTS, or raise an error if + no such method exists in *XML-RPC-PACKAGE*" + (let ((method (find-xml-rpc-method method-name))) + (if method + (apply method arguments) + (error "Method ~A not found." method-name)))) (defvar *xml-rpc-call-hook* 'execute-xml-rpc-call "A function to execute the xml-rpc call and return the result, accepting a method-name string and a optional argument list") (defun handle-xml-rpc-call (in id) - "Handle an actual calll, reading XML from in and writing XML to in" + "Handle an actual call, reading XML from in and returning the + XML-encoded result." (handler-bind ((error #'(lambda (c) (format-debug (or *xml-rpc-debug-stream* t) "~a call failed with ~a~%" id c) (return-from handle-xml-rpc-call @@ -428,7 +477,7 @@ (defun xml-rpc-implementation-version () "Identify ourselves" (concatenate 'string - "$Id: xml-rpc.lisp,v 1.1.1.1 2004/06/09 09:02:40 scaekenberghe Exp $" + "$Id: xml-rpc.lisp,v 1.2 2004/06/13 14:14:47 rschlatte Exp $" " " (lisp-implementation-type) " " @@ -461,12 +510,12 @@ ("Content-Length: ~d" ,(length xml)))) (princ xml connection) (format-debug (or *xml-rpc-debug-stream* t) "~d sending ~a~%" id xml))) - (progn - (format-header connection - `(("HTTP/1.0 400 Bad Request") - ("Server: ~a" ,agent) - ("Connection: close"))) - (format-debug (or *xml-rpc-debug-stream* t) "~d got a bad request~%" id))) + (progn + (format-header connection + `(("HTTP/1.0 400 Bad Request") + ("Server: ~a" ,agent) + ("Connection: close"))) + (format-debug (or *xml-rpc-debug-stream* t) "~d got a bad request~%" id))) (force-output connection) (close connection)))) Index: s-xml-rpc/src/package.lisp diff -u s-xml-rpc/src/package.lisp:1.1.1.1 s-xml-rpc/src/package.lisp:1.2 --- s-xml-rpc/src/package.lisp:1.1.1.1 Wed Jun 9 02:02:39 2004 +++ s-xml-rpc/src/package.lisp Sun Jun 13 07:14:47 2004 @@ -1,6 +1,6 @@ ;;;; -*- mode: lisp -*- ;;;; -;;;; $Id: package.lisp,v 1.1.1.1 2004/06/09 09:02:39 scaekenberghe Exp $ +;;;; $Id: package.lisp,v 1.2 2004/06/13 14:14:47 rschlatte Exp $ ;;;; ;;;; S-XML-RPC package definition ;;;; @@ -34,7 +34,14 @@ #:*xml-rpc-proxy-host* #:*xml-rpc-proxy-port* #:*xml-rpc-authorization* #:*xml-rpc-debug* #:*xml-rpc-debug-stream* #:*xml-rpc-package* #:*xml-rpc-call-hook* - #:execute-xml-rpc-call #:stop-server) + #:execute-xml-rpc-call #:stop-server + #:|system.listMethods| #:|system.methodSignature| #:|system.methodHelp|) (:documentation "An implementation of the standard XML-RPC protocol for both client and server")) + +(defpackage s-xml-rpc-exports + (:use) + (:import-from :s-xml-rpc #:|system.listMethods| #:|system.methodSignature| + #:|system.methodHelp|) + (:documentation "This package contains the functions callable via xml-rpc.")) ;;;; eof From rschlatte at common-lisp.net Sun Jun 13 14:14:47 2004 From: rschlatte at common-lisp.net (Rudi Schlatte) Date: Sun, 13 Jun 2004 07:14:47 -0700 Subject: [s-xml-rpc-cvs] CVS update: s-xml-rpc/ChangeLog Message-ID: Update of /project/s-xml-rpc/cvsroot/s-xml-rpc In directory common-lisp.net:/tmp/cvs-serv21201 Added Files: ChangeLog Log Message: * src/package.lisp (s-xml-rpc-exports): New package -- don't export the whole common-lisp package by default ;) * src/xml-rpc.lisp (*xml-rpc-package*): ... use it. * src/xml-rpc.lisp (|system.listMethods|) (|system.methodSignature|, |system.methodHelp|): Added introspection methods, to be imported in *xml-rpc-package*. * src/package.lisp (s-xml-rpc): ... export them. * src/xml-rpc.lisp: Some indentation frobs. Date: Sun Jun 13 07:14:47 2004 Author: rschlatte From rschlatte at common-lisp.net Sun Jun 13 16:12:04 2004 From: rschlatte at common-lisp.net (Rudi Schlatte) Date: Sun, 13 Jun 2004 09:12:04 -0700 Subject: [s-xml-rpc-cvs] CVS update: s-xml-rpc/ChangeLog Message-ID: Update of /project/s-xml-rpc/cvsroot/s-xml-rpc In directory common-lisp.net:/tmp/cvs-serv8306 Modified Files: ChangeLog Log Message: Implement system.multicall Date: Sun Jun 13 09:12:04 2004 Author: rschlatte Index: s-xml-rpc/ChangeLog diff -u s-xml-rpc/ChangeLog:1.1 s-xml-rpc/ChangeLog:1.2 --- s-xml-rpc/ChangeLog:1.1 Sun Jun 13 07:14:47 2004 +++ s-xml-rpc/ChangeLog Sun Jun 13 09:12:04 2004 @@ -1,5 +1,12 @@ 2004-06-13 Rudi Schlatte + * src/xml-rpc.lisp (xml-literal): new datatype for unescaped + strings (used by system.multicall to pass back encoded fault structs) + (encode-xml-rpc-value): handle it. + (encode-xml-rpc-fault-value, encode-xml-rpc-fault): separate + encoding of fault and methodResponse for system.multicall + (do-one-multicall, |system.multicall|): Implement system.multicall. + * src/package.lisp (s-xml-rpc-exports): New package -- don't export the whole common-lisp package by default ;) @@ -9,7 +16,8 @@ (|system.methodSignature|, |system.methodHelp|): Added introspection methods, to be imported in *xml-rpc-package*. - * src/package.lisp (s-xml-rpc): ... export them. + * src/package.lisp (s-xml-rpc): ... export them, and also + |system.multicall| * src/xml-rpc.lisp: Some indentation frobs. From rschlatte at common-lisp.net Sun Jun 13 16:12:04 2004 From: rschlatte at common-lisp.net (Rudi Schlatte) Date: Sun, 13 Jun 2004 09:12:04 -0700 Subject: [s-xml-rpc-cvs] CVS update: s-xml-rpc/src/xml-rpc.lisp s-xml-rpc/src/package.lisp Message-ID: Update of /project/s-xml-rpc/cvsroot/s-xml-rpc/src In directory common-lisp.net:/tmp/cvs-serv8306/src Modified Files: xml-rpc.lisp package.lisp Log Message: Implement system.multicall Date: Sun Jun 13 09:12:04 2004 Author: rschlatte Index: s-xml-rpc/src/xml-rpc.lisp diff -u s-xml-rpc/src/xml-rpc.lisp:1.2 s-xml-rpc/src/xml-rpc.lisp:1.3 --- s-xml-rpc/src/xml-rpc.lisp:1.2 Sun Jun 13 07:14:47 2004 +++ s-xml-rpc/src/xml-rpc.lisp Sun Jun 13 09:12:03 2004 @@ -1,6 +1,6 @@ ;;;; -*- mode: lisp -*- ;;;; -;;;; $Id: xml-rpc.lisp,v 1.2 2004/06/13 14:14:47 rschlatte Exp $ +;;;; $Id: xml-rpc.lisp,v 1.3 2004/06/13 16:12:03 rschlatte Exp $ ;;;; ;;;; This is a Common Lisp implementation of the XML-RPC protocol, ;;;; as documented on the website http://www.xmlrpc.com @@ -97,6 +97,29 @@ "Create a new XML-RPC-TIME struct with the universal time specified, defaulting to now" (make-xml-rpc-time :universal-time universal-time)) +;;; a wrapper for literal strings, where escaping #\< and #\& is not +;;; desired + +(defstruct (xml-literal (:print-function print-xml-literal)) + "A wrapper around a Common Lisp string that will be sent over + the wire unescaped" + content) + +(setf (documentation 'xml-literal-p 'function) + "Return T when the argument is an unescaped xml string" + (documentation 'xml-literal-content 'function) + "Return the content of a literal xml string") + +(defun print-xml-literal (xml-literal stream depth) + (declare (ignore depth)) + (format stream + "#" + (xml-literal-content xml-literal))) + +(defun xml-literal (content) + "Create a new XML-LITERAL struct with the specified content." + (make-xml-literal :content content)) + ;;; an extra datatype for xml-rpc structures (associative maps) (defstruct (xml-rpc-struct (:print-function print-xml-rpc-struct)) @@ -186,6 +209,8 @@ (princ "" stream) (universal-time->iso8601 (xml-rpc-time-universal-time arg) stream) (princ "" stream)) + ((xml-literal-p arg) + (princ (xml-literal-content arg) stream)) ((or (listp arg) (vectorp arg)) (encode-xml-rpc-array arg stream)) ((xml-rpc-struct-p arg) (encode-xml-rpc-struct arg stream)) ;; add generic method call @@ -218,14 +243,21 @@ (encode-xml-rpc-args (list value) stream) (princ "" stream))) -(defun encode-xml-rpc-fault (fault-string &optional (fault-code 0)) +(defun encode-xml-rpc-fault-value (fault-string &optional (fault-code 0)) + ;; for system.multicall (with-output-to-string (stream) - (princ "" stream) + (princ "" stream) (format stream "faultCode~d" fault-code) (princ "faultString" stream) (print-string-xml fault-string stream) (princ "" stream) - (princ "" stream))) + (princ "" stream))) + +(defun encode-xml-rpc-fault (fault-string &optional (fault-code 0)) + (with-output-to-string (stream) + (princ "" stream) + (princ (encode-xml-rpc-fault-value fault-string fault-code) stream) + (princ "" stream))) ;;; decoding support @@ -290,10 +322,10 @@ (lisp-implementation-version)) "String specifying the default XML-RPC agent to include in server responses") -(defparameter *xml-rpc-debug* nil +(defvar *xml-rpc-debug* nil "When T the XML-RPC client and server part will be more verbose about their protocol") -(defparameter *xml-rpc-debug-stream* nil +(defvar *xml-rpc-debug-stream* nil "When not nil it specifies where debugging output should be written to") (defparameter *xml-rpc-proxy-host* nil @@ -407,6 +439,9 @@ ;;; server API +(defvar *xml-rpc-call-hook* 'execute-xml-rpc-call + "A function to execute the xml-rpc call and return the result, accepting a method-name string and a optional argument list") + (defparameter +xml-rpc-method-characters+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.:/") @@ -438,7 +473,7 @@ (if method ;; http://xmlrpc.usefulinc.com/doc/sysmethodsig.html says to ;; return a non-array if the signature is not available - nil + "n/a" (error "Method ~A not found." method-name)))) (defun |system.methodHelp| (method-name) @@ -448,6 +483,27 @@ (or (documentation method 'function) "") (error "Method ~A not found." method-name)))) +(defun do-one-multicall (call-struct) + (let ((name (get-xml-rpc-struct-member call-struct :|methodName|)) + (params (get-xml-rpc-struct-member call-struct :|params|))) + (handler-bind + ((error #'(lambda (c) + (format-debug + (or *xml-rpc-debug-stream* t) + "A call in a system.multicall failed with ~a~%" c) + (return-from do-one-multicall + (xml-literal + (encode-xml-rpc-fault-value (format nil "~a" c))))))) + (format-debug (or *xml-rpc-debug-stream* t) + "system.multicall calling ~a with ~s~%" name params) + (let ((result (apply *xml-rpc-call-hook* name params))) + (list result))))) + +(defun |system.multicall| (calls) + "Implement system.multicall; see http://www.xmlrpc.com/discuss/msgReader$1208 + for the specification." + (mapcar #'do-one-multicall calls)) + (defun execute-xml-rpc-call (method-name &rest arguments) "Execute method METHOD-NAME on ARGUMENTS, or raise an error if no such method exists in *XML-RPC-PACKAGE*" @@ -456,9 +512,6 @@ (apply method arguments) (error "Method ~A not found." method-name)))) -(defvar *xml-rpc-call-hook* 'execute-xml-rpc-call - "A function to execute the xml-rpc call and return the result, accepting a method-name string and a optional argument list") - (defun handle-xml-rpc-call (in id) "Handle an actual call, reading XML from in and returning the XML-encoded result." @@ -477,7 +530,7 @@ (defun xml-rpc-implementation-version () "Identify ourselves" (concatenate 'string - "$Id: xml-rpc.lisp,v 1.2 2004/06/13 14:14:47 rschlatte Exp $" + "$Id: xml-rpc.lisp,v 1.3 2004/06/13 16:12:03 rschlatte Exp $" " " (lisp-implementation-type) " " Index: s-xml-rpc/src/package.lisp diff -u s-xml-rpc/src/package.lisp:1.2 s-xml-rpc/src/package.lisp:1.3 --- s-xml-rpc/src/package.lisp:1.2 Sun Jun 13 07:14:47 2004 +++ s-xml-rpc/src/package.lisp Sun Jun 13 09:12:03 2004 @@ -1,6 +1,6 @@ ;;;; -*- mode: lisp -*- ;;;; -;;;; $Id: package.lisp,v 1.2 2004/06/13 14:14:47 rschlatte Exp $ +;;;; $Id: package.lisp,v 1.3 2004/06/13 16:12:03 rschlatte Exp $ ;;;; ;;;; S-XML-RPC package definition ;;;; @@ -35,13 +35,14 @@ #:*xml-rpc-debug* #:*xml-rpc-debug-stream* #:*xml-rpc-package* #:*xml-rpc-call-hook* #:execute-xml-rpc-call #:stop-server - #:|system.listMethods| #:|system.methodSignature| #:|system.methodHelp|) + #:|system.listMethods| #:|system.methodSignature| #:|system.methodHelp| + #:|system.multicall|) (:documentation "An implementation of the standard XML-RPC protocol for both client and server")) (defpackage s-xml-rpc-exports (:use) (:import-from :s-xml-rpc #:|system.listMethods| #:|system.methodSignature| - #:|system.methodHelp|) + #:|system.methodHelp| #:|system.multicall|) (:documentation "This package contains the functions callable via xml-rpc.")) ;;;; eof From rschlatte at common-lisp.net Sun Jun 13 17:02:14 2004 From: rschlatte at common-lisp.net (Rudi Schlatte) Date: Sun, 13 Jun 2004 10:02:14 -0700 Subject: [s-xml-rpc-cvs] CVS update: public_html/index.html Message-ID: Update of /project/s-xml-rpc/cvsroot/public_html In directory common-lisp.net:/tmp/cvs-serv4833 Modified Files: index.html Log Message: Update documentation: by default, almost nothing is exported now. Show how to make common-lisp available, like before. Date: Sun Jun 13 10:02:14 2004 Author: rschlatte Index: public_html/index.html diff -u public_html/index.html:1.1.1.1 public_html/index.html:1.2 --- public_html/index.html:1.1.1.1 Wed Jun 9 02:02:08 2004 +++ public_html/index.html Sun Jun 13 10:02:14 2004 @@ -66,7 +66,7 @@ The function xml-rpc-aserve:xml-rpc-call-aserve does the same thing, but uses the (portable) aserve HTTP client API for the networking.

- Unit tests throughout the source code (marked by #+unit-test and usually wrapped inside an assert) can serve as (executable) examples. A more complicated example is the server and client implementation of some tests in validator1.lisp. Remember that XML-RPC method (function) names are case-sensitive, as are the names of XML-RPC structure members. + The unit tests in the subdirectory test can serve as (executable) examples. A more complicated example is the server and client implementation of some tests in validator1.lisp. Remember that XML-RPC method (function) names are case-sensitive, as are the names of XML-RPC structure members.

@@ -74,26 +74,42 @@

Only a single function call is needed to get the server up and running: -

? (start-xml-rpc-server :port 8080)
- From now on, your lisp image becomes an XML-RPC server, listening for HTTP requests on port 8080. - By default each function in your lisp image becomes available remotely, provided its signature is compatible. - The is not very secure, but it is easy and powerful. - You should customize this behavior for production usage. +
? (start-xml-rpc-server :port 8080)
From now on, your + lisp image becomes an XML-RPC server, listening for HTTP + requests on port 8080. By default the + functions system.listMethods, system.methodSignature, + system.methodHelp and system.multicall are + available. You can export additional functions from the server + by importing symbols in the package contained + in *xml-rpc-package* (by default, this is the package + S-XML-RPC-EXPORTS). (use-package :common-lisp + :s-xml-rpc-exports) makes all of Common Lisp available via + xml-rpc. +

+

In more detail, this is what happens:

  • The XML-RPC call arrives as XML encoded characters in the body of an HTTP POST request
  • The characters received are parsed by the XML parser and decoded on the fly (using a SAX-like interface) following XML-RPC semantics into a a string method name and a possibly empty list of Lisp objects that are the arguments
  • The value of *xml-rpc-call-hook* is applied on the string method name and optional argument list
  • -
  • The default value of *xml-rpc-call-hook* is execute-xml-rpc-call which interns the method name in the package *xml-rpc-package* (whose default value is the XML-RPC package itself) and applies the function bound to that name to the argument list (if any)
  • +
  • The default value of *xml-rpc-call-hook* + is execute-xml-rpc-call which looks for a function + with the given name in the package *xml-rpc-package* + (whose default value is the XML-RPC-EXPORTS package) and + applies the function bound to that name to the argument list + (if any)
  • The result is encoded as an XML-RPC result and returned to the client
  • -
  • If anything goes wrong in any of these steps, a Lisp condition is thrown which is catched and then encoded as an XML-RPC fault and returned to the client
  • +
  • If anything goes wrong in any of these steps, a Lisp + condition is thrown which is caught and then encoded as an XML-RPC fault and returned to the client
- Customization points are *xml-rpc-package* or *xml-rpc-call-hook*. + Customization points are *xml-rpc-package* and *xml-rpc-call-hook*. Setting the variable xml-rpc::*xml-rpc-debug* to t makes the server more verbose. Note that XML-RPC method names are case sensitive: for example, clients have specify "LISP-IMPLEMENTATION-TYPE" for the corresponding Lisp function; a server has to define a function named |login| if his clients look for an implementation of "login".

-AppleScript can make client-side XML-RPC calls. So provided you have your lisp XML-RPC server running, you can have lisp to the math like this: + AppleScript can make client-side XML-RPC calls. So provided you + have your lisp XML-RPC server running and have imported + in + XML-RPC-EXPORTS, you can have lisp do the math like this:

tell application "http://localhost:8080/RPC2"
   set call_result to call xmlrpc {method name:"+", parameters:{10, 20, 30}}
 end tell
@@ -220,7 +236,7 @@
       The code in the package "S-BASE64" is an implementation of Base64 encoding and decoding (part of RFC 1521). Encoding takes bytes (a binary stream or a byte array) and produces characters (a character stream or a string). Decoding goes the other way.
     

-

CVS version $Id: index.html,v 1.1.1.1 2004/06/09 09:02:08 scaekenberghe Exp $

+

CVS version $Id: index.html,v 1.2 2004/06/13 17:02:14 rschlatte Exp $