(module server-core mzscheme
(require (lib "servlet.ss" "web-server")
(file "serialise.ss")
(file "protocol.ss")
(lib "response.ss" "web-server" "private" )
(lib "xml.ss" "xml"))
(provide (all-defined))
(define environment (make-hash-table))
(define (add-handler id fun)
(hash-table-put! environment id fun))
(define (handler-exists? id)
(hash-table-get environment id (lambda () #f)))
(define (invoke-handler name args)
(let* ([fun (hash-table-get environment name)]
[arity (procedure-arity fun)]
[arg-length (length args)])
(cond
[(= arity arg-length)
(let* ([result (apply fun args)]
[serialised-result (serialise result)])
(make-response serialised-result))]
[else
(make-handler-fault
(format "You invoked '~a' with ~a parameters; '~a' expects ~a."
name arg-length name arity)
101
)])
))
(define (make-response serialised-result)
(let* ([response `(methodResponse
(params
(param
,serialised-result)))]
[output (string->bytes/utf-8 (xexpr->string response))])
(make-response/full
200 "Okay" (current-seconds)
#"text/xml" '()
(list output))))
(define (make-handler-fault string code)
(let ([errorHash (make-hash-table)])
(hash-table-put!
errorHash 'faultString string)
(hash-table-put!
errorHash 'faultCode code)
`(methodResponse (fault ,(serialise errorHash)))))
(define (extract-xmlrpc-bindings request)
(bytes->string/utf-8 (request-post-data/raw request)))
(define (handle-xmlrpc-servlet-request* request)
(let ([call (decode-xmlrpc-call
(extract-xmlrpc-bindings request))])
(let ([name (rpc-call-name call)]
[args (rpc-call-args call)])
(if (handler-exists? name)
(invoke-handler name args)
(make-handler-fault
(format "No handler found on server for '~a'" name)
100)))))
)