如何在Common Lisp中使用SOAP Web服务?

时间:2016-06-02 22:28:40

标签: web-services common-lisp

我在弄清楚是否有任何教程或示例文档可以解释如何做到这一点?我看到可以发出http请求的HTTP客户端Drakma但我实际上并不了解如何使用它来调用SOAP Web服务(如果可能的话)。任何指导都会非常感激。

2 个答案:

答案 0 :(得分:1)

有一个用于常见lisp cl-soap的soap客户端,但它似乎过时了,SOAP是通过HTTP实现的,因此使用drakma轻松调用soap服务可以轻松调用。我们也将使用:

clozure常见的lisp或你喜欢的实现,如SBCL quicklisp cl-ppcre;一个可移植的正则表达式库 plump;一个xml解析器

让我们从这里拨打肥皂服务http://www.webservicex.net/New/,轻松一个人可以:

http://www.webservicex.net/New/Home/ServiceDetail/56在这里你可以找到肥皂服务的原始请求仔细阅读

它在xml体内传递两个参数,然后发回一个xml。

肥皂服务,简单易用,是一种HTTP post方法,它发送XML并接收XML,让我们用drakma构建调用。

SOAP服务中的重要文件是WSDL,是服务的描述:

http://www.webservicex.net/globalweather.asmx?WSDL

让我们玩lisp:

;; preparing the xml soap

(defun create-body-for-request-get-weather-soap (city-name country-name)
  (format nil "~{~A~%~}" (list
                          "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                          "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"
                          "<soap:Body>"
                            "<GetWeather xmlns=\"http://www.webserviceX.NET\">"
                              (format nil "<CityName>~A</CityName>" city-name)
                              (format nil "<CountryName>~A</CountryName>" country-name)
                            "</GetWeather>"
                          "</soap:Body>"
                          "</soap:Envelope>")))

(defun send-soap-request (&key url soap-action soap-body)
  (let* ((response
          (drakma:http-request url
                               :method :post
                               :content-length t
                               :content-type "text/xml; charset=utf-8"
                               :additional-headers  `(("SOAPAction" . ,soap-action))
                               :content soap-body)))
    response))

(defparameter answer (send-soap-request
                      :url "http://www.webservicex.net/globalweather.asmx"
                      :soap-action "http://www.webserviceX.NET/GetWeather"
                      :soap-body (create-body-for-request-get-weather-soap "Valencia" "Spain")))



;;preparing the xml soap 1.2



(defun create-body-for-request-get-weather-soap12 (city-name country-name)
  (format nil "~{~A~%~}"
          (list "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
                "<soap12:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\">"
                  "<soap12:Body>"
                    "<GetWeather xmlns=\"http://www.webserviceX.NET\">"
                      (format nil "<CityName>~A</CityName>" city-name)
                      (format nil "<CountryName>~A</CountryName>" country-name)
                    "</GetWeather>"
                  "</soap12:Body>"
                "</soap12:Envelope>")))

(defun send-soap12-request (&key url soap-action soap-body)
  (let* ((response
          (drakma:http-request url
                               :method :post
                               :content-length t
                               :content-type "application/soap+xml; charset=utf-8"
                               :additional-headers  `(("SOAPAction" . ,soap-action))
                               :content soap-body)))
    response))



;; the call

(defparameter answer (send-soap12-request
                      :url "http://www.webservicex.net/globalweather.asmx"
                      :soap-action "http://www.webserviceX.NET/GetWeather"
                      :soap-body (create-body-for-request-get-weather-soap12 "Valencia" "Spain")))

(class-of answer) ;; I do not know if I have an error with the codification, but in this case seems
;;and error with utf-8 and utf-16, so it returns and array of unsignet bytes it seems ascii so I convert it with common lisp

(format nil "~{~A~}" (map 'list #'(lambda (value) (code-char value)) answer)) 

和答案:

没有价值

CL-USER> 
; No value; compiling (DEFUN CREATE-BODY-FOR-REQUEST-GET-WEATHER-SOAP ...)
; compiling (DEFUN SEND-SOAP-REQUEST ...)
CL-USER> answer

"<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><soap:Body><GetWeatherResponse xmlns=\"http://www.webserviceX.NET\"><GetWeatherResult>&lt;?xml version=\"1.0\" encoding=\"utf-16\"?&gt;
&lt;CurrentWeather&gt;
  &lt;Location&gt;Valencia / Aeropuerto, Spain (LEVC) 39-30N 000-28W 62M&lt;/Location&gt;
  &lt;Time&gt;Jun 07, 2016 - 06:30 AM EDT / 2016.06.07 1030 UTC&lt;/Time&gt;
  &lt;Wind&gt; from the E (080 degrees) at 9 MPH (8 KT) (direction variable):0&lt;/Wind&gt;
  &lt;Visibility&gt; greater than 7 mile(s):0&lt;/Visibility&gt;
  &lt;SkyConditions&gt; mostly clear&lt;/SkyConditions&gt;
  &lt;Temperature&gt; 78 F (26 C)&lt;/Temperature&gt;
  &lt;DewPoint&gt; 57 F (14 C)&lt;/DewPoint&gt;
  &lt;RelativeHumidity&gt; 47%&lt;/RelativeHumidity&gt;
  &lt;Pressure&gt; 30.18 in. Hg (1022 hPa)&lt;/Pressure&gt;
  &lt;Status&gt;Success&lt;/Status&gt;
&lt;/CurrentWeather&gt;</GetWeatherResult></GetWeatherResponse></soap:Body></soap:Envelope>"
; compiling (DEFUN CREATE-BODY-FOR-REQUEST-GET-WEATHER-SOAP12 ...)
; compiling (DEFUN SEND-SOAP12-REQUEST ...)
CL-USER> answer

#(60 63 120 109 108 32 118 101 114 115 105 111 110 61 34 49 46 48 34 32 101 110
  99 111 100 105 110 103 61 34 117 116 102 45 56 34 63 62 60 115 111 97 112 58
  69 110 118 101 108 111 112 101 32 120 109 108 110 115 58 115 111 97 112 61 34
  104 116 116 112 58 47 47 119 119 119 46 119 51 46 111 114 103 47 50 48 48 51
  47 48 53 47 115 111 97 112 45 101 110 118 101 108 111 112 101 34 32 120 109
  108 110 115 58 120 115 105 61 34 104 116 116 112 58 47 47 119 119 119 46 119
  51 46 111 114 103 47 50 48 48 49 47 88 77 76 83 99 104 101 109 97 45 105 110
  115 116 97 110 99 101 34 32 120 109 108 110 115 58 120 115 100 61 34 104 116
  116 112 58 47 47 119 119 119 46 119 51 46 111 114 103 47 50 48 48 49 47 88 77
  76 83 99 104 101 109 97 34 62 60 115 111 97 112 58 66 111 100 121 62 60 71
  101 116 87 101 97 116 104 101 114 82 101 115 112 111 110 115 101 32 120 109
  108 110 115 61 34 104 116 116 112 58 47 47 119 119 119 46 119 101 98 115 101
  114 118 105 99 101 88 46 78 69 84 34 62 60 71 101 116 87 101 97 116 104 101
  114 82 101 115 117 108 116 62 38 108 116 59 63 120 109 108 32 118 101 114 115
  105 111 110 61 34 49 46 48 34 32 101 110 99 111 100 105 110 103 61 34 117 116
  102 45 49 54 34 63 38 103 116 59 13 10 38 108 116 59 67 117 114 114 101 110
  116 87 101 97 116 104 101 114 38 103 116 59 13 10 32 32 38 108 116 59 76 111
  99 97 116 105 111 110 38 103 116 59 86 97 108 101 110 99 105 97 32 47 32 65
  101 114 111 112 117 101 114 116 111 44 32 83 112 97 105 110 32 40 76 69 86 67
  41 32 51 57 45 51 48 78 32 48 48 48 45 50 56 87 32 54 50 77 38 108 116 59 47
  76 111 99 97 116 105 111 110 38 103 116 59 13 10 32 32 38 108 116 59 84 105
  109 101 38 103 116 59 74 117 110 32 48 55 44 32 50 48 49 54 32 45 32 48 54 58
  51 48 32 65 77 32 69 68 84 32 47 32 50 48 49 54 46 48 54 46 48 55 32 49 48 51
  48 32 85 84 67 38 108 116 59 47 84 105 109 101 38 103 116 59 13 10 32 32 38
  108 116 59 87 105 110 100 38 103 116 59 32 102 114 111 109 32 116 104 101 32
  69 32 40 48 56 48 32 100 101 103 114 101 101 115 41 32 97 116 32 57 32 77 80
  72 32 40 56 32 75 84 41 32 40 100 105 114 101 99 116 105 111 110 32 118 97
  114 105 97 98 108 101 41 58 48 38 108 116 59 47 87 105 110 100 38 103 116 59
  13 10 32 32 38 108 116 59 86 105 115 105 98 105 108 105 116 121 38 103 116 59
  32 103 114 101 97 116 101 114 32 116 104 97 110 32 55 32 109 105 108 101 40
  115 41 58 48 38 108 116 59 47 86 105 115 105 98 105 108 105 116 121 38 103
  116 59 13 10 32 32 38 108 116 59 83 107 121 67 111 110 100 105 116 105 111
  110 115 38 103 116 59 32 109 111 115 116 108 121 32 99 108 101 97 114 38 108
  116 59 47 83 107 121 67 111 110 100 105 116 105 111 110 115 38 103 116 59 13
  10 32 32 38 108 116 59 84 101 109 112 101 114 97 116 117 114 101 38 103 116
  59 32 55 56 32 70 32 40 50 54 32 67 41 38 108 116 59 47 84 101 109 112 101
  114 97 116 117 114 101 38 103 116 59 13 10 32 32 38 108 116 59 68 101 119 80
  111 105 110 116 38 103 116 59 32 53 55 32 70 32 40 49 52 32 67 41 38 108 116
  59 47 68 101 119 80 111 105 110 116 38 103 116 59 13 10 32 32 38 108 116 59
  82 101 108 97 116 105 118 101 72 117 109 105 100 105 116 121 38 103 116 59 32
  52 55 37 38 108 116 59 47 82 101 108 97 116 105 118 101 72 117 109 105 100
  105 116 121 38 103 116 59 13 10 32 32 38 108 116 59 80 114 101 115 115 117
  114 101 38 103 116 59 32 51 48 46 49 56 32 105 110 46 32 72 103 32 40 49 48
  50 50 32 104 80 97 41 38 108 116 59 47 80 114 101 115 115 117 114 101 38 103
  116 59 13 10 32 32 38 108 116 59 83 116 97 116 117 115 38 103 116 59 83 117
  99 99 101 115 115 38 108 116 59 47 83 116 97 116 117 115 38 103 116 59 13 10
  38 108 116 59 47 67 117 114 114 101 110 116 87 101 97 116 104 101 114 38 103
  116 59 60 47 71 101 116 87 101 97 116 104 101 114 82 101 115 117 108 116 62
  60 47 71 101 116 87 101 97 116 104 101 114 82 101 115 112 111 110 115 101 62
  60 47 115 111 97 112 58 66 111 100 121 62 60 47 115 111 97 112 58 69 110 118
  101 108 111 112 101 62)
CL-USER> (format nil "~{~A~}" (map 'list #'(lambda (value) (code-char value)) answer))
"<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><soap:Body><GetWeatherResponse xmlns=\"http://www.webserviceX.NET\"><GetWeatherResult>&lt;?xml version=\"1.0\" encoding=\"utf-16\"?&gt;
&lt;CurrentWeather&gt;
  &lt;Location&gt;Valencia / Aeropuerto, Spain (LEVC) 39-30N 000-28W 62M&lt;/Location&gt;
  &lt;Time&gt;Jun 07, 2016 - 06:30 AM EDT / 2016.06.07 1030 UTC&lt;/Time&gt;
  &lt;Wind&gt; from the E (080 degrees) at 9 MPH (8 KT) (direction variable):0&lt;/Wind&gt;
  &lt;Visibility&gt; greater than 7 mile(s):0&lt;/Visibility&gt;
  &lt;SkyConditions&gt; mostly clear&lt;/SkyConditions&gt;
  &lt;Temperature&gt; 78 F (26 C)&lt;/Temperature&gt;
  &lt;DewPoint&gt; 57 F (14 C)&lt;/DewPoint&gt;
  &lt;RelativeHumidity&gt; 47%&lt;/RelativeHumidity&gt;
  &lt;Pressure&gt; 30.18 in. Hg (1022 hPa)&lt;/Pressure&gt;
  &lt;Status&gt;Success&lt;/Status&gt;
&lt;/CurrentWeather&gt;</GetWeatherResult></GetWeatherResponse></soap:Body></soap:Envelope>"
CL-USER>

答案 1 :(得分:1)

对响应八位字节使用UTF-8编码:

(ppcre:regex-replace-all (format nil "~c" #\Return) (flexi-streams:octets-to-string response :external-format :utf-8) "")))