;; Author: Alexandru Harsanyi <AlexHarsanyi@gmail.com>
;; Author: Thomas Fitzsimmons <fitzsim@fitzsim.org>
;; Created: December, 2009
-;; Version: 3.0.2
+;; Version: 3.1.1
;; Keywords: soap, web-services, comm, hypermedia
;; Package: soap-client
;; Homepage: https://github.com/alex-hhh/emacs-soap-client
(base64Binary
(unless (stringp value)
(error "Not a string value for base64Binary"))
- (base64-encode-string (encode-coding-string value 'utf-8)))
+ (base64-encode-string value))
(otherwise
(error "Don't know how to encode %s for type %s"
decimal byte float double duration)
(string-to-number (car contents)))
(boolean (string= (downcase (car contents)) "true"))
- (base64Binary (decode-coding-string (base64-decode-string (car contents)) 'utf-8))
+ (base64Binary (base64-decode-string (car contents)))
(anyType (soap-decode-any-type node))
(Array (soap-decode-array node))))))
(when messages
(error (mapconcat 'identity (nreverse messages) "; and: "))))
(cl-labels ((fail-with-message (format value)
- (push (format format value) messages)
- (throw 'invalid nil)))
+ (push (format format value) messages)
+ (throw 'invalid nil)))
(catch 'invalid
(let ((enumeration (soap-xs-simple-type-enumeration type)))
(when (and (> (length enumeration) 1)
`soap-xs-complex-type' objects."
(case (soap-xs-complex-type-indicator type)
(array
- (error "soap-encode-xs-complex-type arrays are handled elsewhere"))
+ (error "Arrays of type soap-encode-xs-complex-type are handled elsewhere"))
((sequence choice all nil)
(let ((type-list (list type)))
:type 'boolean
:group 'soap-client)
+(defun soap-find-port (wsdl service)
+ "Return the WSDL port having SERVICE name.
+Signal an error if not found."
+ (or (catch 'found
+ (dolist (p (soap-wsdl-ports wsdl))
+ (when (equal service (soap-element-name p))
+ (throw 'found p))))
+ (error "Unknown SOAP service: %s" service)))
+
+(defun soap-find-operation (port operation-name)
+ "Inside PORT, find OPERATION-NAME, a `soap-port-type'.
+Signal an error if not found."
+ (let* ((binding (soap-port-binding port))
+ (op (gethash operation-name (soap-binding-operations binding))))
+ (or op
+ (error "No operation %s for SOAP service %s"
+ operation-name (soap-element-name port)))))
+
+(defun soap-operation-arity (wsdl service operation-name)
+ "Return the number of arguments required by a soap operation.
+WSDL, SERVICE, OPERATION-NAME and PARAMETERS are as described in
+`soap-invoke'."
+ (let* ((port (soap-find-port wsdl service))
+ (op (soap-find-operation port operation-name))
+ (bop (soap-bound-operation-operation op)))
+ (length (soap-operation-parameter-order bop))))
+
(defun soap-invoke-internal (callback cbargs wsdl service operation-name
&rest parameters)
"Implement `soap-invoke' and `soap-invoke-async'.
CALLBACK RESPONSE CBARGS), where RESPONSE is the SOAP invocation result.
If CALLBACK is nil, operate synchronously. WSDL, SERVICE,
OPERATION-NAME and PARAMETERS are as described in `soap-invoke'."
- (let ((port (catch 'found
- (dolist (p (soap-wsdl-ports wsdl))
- (when (equal service (soap-element-name p))
- (throw 'found p))))))
- (unless port
- (error "Unknown SOAP service: %s" service))
-
- (let* ((binding (soap-port-binding port))
- (operation (gethash operation-name
- (soap-binding-operations binding))))
- (unless operation
- (error "No operation %s for SOAP service %s" operation-name service))
-
- (let ((url-request-method "POST")
- (url-package-name "soap-client.el")
- (url-package-version "1.0")
- (url-request-data
- ;; url-request-data expects a unibyte string already encoded...
- (encode-coding-string
- (soap-create-envelope operation parameters wsdl
- (soap-port-service-url port))
- 'utf-8))
- (url-mime-charset-string "utf-8;q=1, iso-8859-1;q=0.5")
- (url-http-attempt-keepalives t)
- (url-request-extra-headers
- (list
- (cons "SOAPAction"
- (concat "\"" (soap-bound-operation-soap-action
- operation) "\""))
- (cons "Content-Type"
- "text/xml; charset=utf-8"))))
- (if callback
- (url-retrieve
- (soap-port-service-url port)
- (lambda (status)
- (let ((data-buffer (current-buffer)))
- (unwind-protect
- (let ((error-status (plist-get status :error)))
- (if error-status
- (signal (car error-status) (cdr error-status))
- (apply callback
- (soap-parse-envelope
- (soap-parse-server-response)
- operation wsdl)
- cbargs)))
- ;; Ensure the url-retrieve buffer is not leaked.
- (and (buffer-live-p data-buffer)
- (kill-buffer data-buffer))))))
+ (let* ((port (soap-find-port wsdl service))
+ (operation (soap-find-operation port operation-name)))
+ (let ((url-request-method "POST")
+ (url-package-name "soap-client.el")
+ (url-package-version "1.0")
+ (url-request-data
+ ;; url-request-data expects a unibyte string already encoded...
+ (encode-coding-string
+ (soap-create-envelope operation parameters wsdl
+ (soap-port-service-url port))
+ 'utf-8))
+ (url-mime-charset-string "utf-8;q=1, iso-8859-1;q=0.5")
+ (url-http-attempt-keepalives t)
+ (url-request-extra-headers
+ (list
+ (cons "SOAPAction"
+ (concat "\"" (soap-bound-operation-soap-action
+ operation) "\""))
+ (cons "Content-Type"
+ "text/xml; charset=utf-8"))))
+ (if callback
+ (url-retrieve
+ (soap-port-service-url port)
+ (lambda (status)
+ (let ((data-buffer (current-buffer)))
+ (unwind-protect
+ (let ((error-status (plist-get status :error)))
+ (if error-status
+ (signal (car error-status) (cdr error-status))
+ (apply callback
+ (soap-parse-envelope
+ (soap-parse-server-response)
+ operation wsdl)
+ cbargs)))
+ ;; Ensure the url-retrieve buffer is not leaked.
+ (and (buffer-live-p data-buffer)
+ (kill-buffer data-buffer))))))
(let ((buffer (url-retrieve-synchronously
(soap-port-service-url port))))
(condition-case err
(error
(when soap-debug
(pop-to-buffer buffer))
- (error (error-message-string err))))))))))
+ (error (error-message-string err)))))))))
(defun soap-invoke (wsdl service operation-name &rest parameters)
"Invoke a SOAP operation and return the result.
NOTE: The SOAP service provider should document the available
operations and their parameters for the service. You can also
use the `soap-inspect' function to browse the available
-operations in a WSDL document."
+operations in a WSDL document.
+
+NOTE: `soap-invoke' base64-decodes xsd:base64Binary return values
+into unibyte strings; these byte-strings require further
+interpretation by the caller."
(apply #'soap-invoke-internal nil nil wsdl service operation-name parameters))
(defun soap-invoke-async (callback cbargs wsdl service operation-name