(module protocol mzscheme
(require (planet "xml.ss" ("jim" "webit.plt" 1 3))
(planet "xxexpr.ss" ("lshift" "xxexpr.plt" 1))
(lib "url.ss" "net")
(lib "ssax.ss" "ssax")
"base.ss"
"serialise.ss")
(provide encode-xmlrpc-call
write-xmlrpc-call
make-xmlrpc-call
read-xmlrpc-response
decode-xmlrpc-response)
(define (http-200? headers)
(if (regexp-match #rx"^HTTP/[0-9]*\\.[0-9]* 200" headers)
#t
#f))
(define (encode-xmlrpc-call method-name . args)
`(methodCall
(methodName ,method-name)
(params
,@(map (lambda (val)
`(param ,(serialise val)))
args))))
(define (write-xmlrpc-call call op)
(parameterize
((xml-double-quotes-mode #t))
(pretty-print-xxexpr (list '(*pi* xml (version "1.0"))
call) op)))
(define (make-xmlrpc-call url call)
(let ((op (open-output-bytes)))
(write-xmlrpc-call call op)
(post-impure-port url
(get-output-bytes op)
'("Content-Type: text/xml"
"User-Agent: PLT Scheme"))))
(define (read-xmlrpc-response ip)
(let ((headers (purify-port ip)))
(unless (http-200? headers)
(raise-exn:xmlrpc "Server did not respond with an HTTP 200"))
(ssax:xml->sxml ip '())))
(define (decode-xmlrpc-response ip)
(let ((resp (read-xmlrpc-response ip)))
(xml-match (xml-document-content resp)
[(methodResponse (params (param ,value)))
(deserialise value)]
[(methodResponse (fault ,value))
(let ((h (deserialise value)))
(raise
(make-exn:xmlrpc:fault
(string->immutable-string
(hash-table-get h 'faultString))
(current-continuation-marks)
(hash-table-get h 'faultCode))))]
[,else
(raise-exn:xmlrpc
(format "Received invalid XMLRPC response ~a\n" else))])))
)