1. 背景
这个项目之前是采用的Python的requests库以POST的方式向服务器传送json字符串的形式,这次由于合作方的变化,要采用web services的形式,按照SOAP协议,传送XML格式的数据到服务端。
本着少改动的原则,决定继续使用Python的requests库,将原来的json字符串拼成XML格式,再发送给服务端。
在改动的过程中,遇到了一些问题,并逐个进行了解决。下面是详细的过程。
2. tomcat启动问题
1.首先有个服务端,合作方已经部署在了tomcat上,并把压缩包发了过来;第一步肯定是先运行tomcat;
2.运行tomcat后,localhost:8080显示tomcat已经启动,但是服务的域名localhost:8080/TPService/TPServicePort?wsdl却显示404,如图所示:
3.然后发现运行起来的tomcat是9.0版本,而合作方发来的tomcat是7.0版本;
4.使用的是windows电脑,将环境变量中的CATALINA_HOME的值改为7.0版本的tomcat文件夹路径,即可启动7.0版本的tomcat,并能够成功访问localhost:8080/TPService/TPServicePort?wsdl
3. 报415错误
- 首先并不急于将完整的数据发送给服务端,而是仅仅想把与服务端的连接成功建立。此时的代码大概如下:
import requests url = 'http://localhost:8080/TPService/TPServicePort?wsdl' payload = {'a':'test'} response = requests.post(url, json=payload, timeout=5)
2.此时会报415错误;到服务端查看,发现如下报错信息:
Unsupported Content-Type: application/json Supported ones are: [text/xml] com.sun.xml.ws.server.UnsupportedMediaException: Unsupported Content-Type: application/json Supported ones are: [text/xml]
3.按照提示,增加headers,将content-type的值设置为text/xml,此时代码如下:
import requests from requests.structures import CaseInsensitiveDict url = 'http://localhost:8080/TPService/TPServicePort?wsdl' headers = CaseInsensitiveDict() headers['Content-Type'] = 'text/xml' payload = {'a': 'b'} response = requests.post(url, headers=headers, json=payload, timeout=5) print(response.status_code)
- 此时报500错误,说明通信连接已经建立了;
4. 按照SOAP格式拼装xml
- 一开始拼接的xml如下:
<?xml version ="1.0" encoding="UTF-8"?> <S:Envelope xmlns:S='http://schemas.xmlsoap.org/soap/envelope/'> <S:Body> <n:uploadTestData xmlns:n="http://localhost:8080/TPService/TPServicePort?wsdl"> <a>test</a> </n:uploadTestData> </S:Body> </S:Envelope>
2.此时代码大概如下:
import requests from requests.structures import CaseInsensitiveDict url = 'http://localhost:8080/TPService/TPServicePort?wsdl' headers = CaseInsensitiveDict() headers['Content-Type'] = 'text/xml' payload = ‘’‘ <?xml version ="1.0" encoding="UTF-8"?> <S:Envelope xmlns:S='http://schemas.xmlsoap.org/soap/envelope/'> <S:Body> <n:uploadTestData xmlns:n="http://localhost:8080/TPService/TPServicePort?wsdl"> <a>test</a> </n:uploadTestData> </S:Body> </S:Envelope> ’‘’ response = requests.post(url, headers=headers, data=payload, timeout=5) print(response.status_code)
3.然后这时会报错500如下:
Couldn't create SOAP message due to exception: XML reader error: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[2,14] Message: The processing instruction target matching "[xX][mM][lL]" is not allowed. com.sun.xml.ws.protocol.soap.MessageCreationException: Couldn't create SOAP message due to exception: XML reader error: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[2,14]
3.按照提示,找到[2, 14]的位置,发现是xml version这里,去掉两个单词之间的空格,再次请求,报错500,但是服务端没有信息显示。
4.发现是请求地址写错了,请求地址应与localhost:8080/TPService/TPServicePort?wsdl中的namespace保持一致。将代码修改为:
import requests from requests.structures import CaseInsensitiveDict url = 'http://localhost:8080/TPService/TPServicePort?wsdl' headers = CaseInsensitiveDict() headers['Content-Type'] = 'text/xml' payload = ‘’‘ <?xml version ="1.0" encoding="UTF-8"?> <S:Envelope xmlns:S='http://schemas.xmlsoap.org/soap/envelope/'> <S:Body> <n:uploadTestData xmlns:n="http://www.xxxx.com"> <a>test</a> </n:uploadTestData> </S:Body> </S:Envelope> ’‘’ response = requests.post(url, headers=headers, data=payload, timeout=5) print(response.status_code)
6.再次发起请求,返回结果如下:
<?xml version="1.0" ?> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body> <ns2:uploadTestDataResponse xmlns:ns2="http://www.glorysoft.com"> <return> {"responseDate":"20210420114103554","resultCode":"OK","resultMessage":"success"} </return> </ns2:uploadTestDataResponse> </S:Body> </S:Envelope>
说明成功进行了通信。