微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

带有Spyne和Twisted的Python SOAP服务器给出错误405“您必须在Content-Type标头正确设置的情况下发出POST请求”

如何解决带有Spyne和Twisted的Python SOAP服务器给出错误405“您必须在Content-Type标头正确设置的情况下发出POST请求”

在使用Twisted作为传输来使用Spyne公开的Python SOAP函数时遇到一些麻烦。

每次我尝试使用SoapUI或直接使用pysimplesoap在Pyhton中调用函数时,即使我的请求是POST请求,我也总是会收到405错误您必须发出Content-Type的POST请求标头设置正确”。

如果我将传输层从Twisted更改为Wsgi,则一切正常。

这是Twisted的服务器代码

import logging
logging.basicConfig(level=logging.DEBUG)
from spyne import Application,rpc,ServiceBase,Integer,Unicode
from spyne import Iterable
from spyne.decorator import srpc
from spyne.model.primitive import String
from spyne.protocol.soap import Soap11
from spyne.server.twisted import TwistedWebResource
from twisted.internet import reactor
from twisted.web.server import Site

class HelloWorldService(ServiceBase):
    @srpc(_returns=Iterable(String))
    def say_hello():
        for i in range(0,5):
            yield 'Hello,%s' % i

if __name__=='__main__':
    logging.basicConfig(level=logging.DEBUG)
    logging.getLogger('spyne.protocol.xml').setLevel(logging.DEBUG)
    app = Application([HelloWorldService],'spyne.examples.hello.http',in_protocol=Soap11(validator='lxml'),out_protocol=Soap11(),)

    resource = TwistedWebResource(app)
    site = Site(resource)
    reactor.listenTCP(8000,site,interface='0.0.0.0')
    reactor.run()

这是客户端代码

from pysimplesoap.client import SoapClient
cli = SoapClient(wsdl='http://localhost:8000/?wsdl')
res = cli.say_hello()
print(res)

那就是我得到的错误

File "<stdin>",line 1,in <module>
  File "C:\Users\user1\AppData\Roaming\Python\python38\site-packages\pysimplesoap\client.py",line 177,in <lambda>
    return lambda *args,**kwargs: self.wsdl_call(attr,*args,**kwargs)
  File "C:\Users\user1\AppData\Roaming\Python\python38\site-packages\pysimplesoap\client.py",line 351,in wsdl_call
    return self.wsdl_call_with_args(method,args,kwargs)
  File "C:\Users\user1\AppData\Roaming\Python\python38\site-packages\pysimplesoap\client.py",line 375,in wsdl_call_with_args
    response = self.call(method,*params)
  File "C:\Users\user1\AppData\Roaming\Python\python38\site-packages\pysimplesoap\client.py",line 256,in call
    self.xml_response = self.send(method,self.xml_request)
  File "C:\Users\user1\AppData\Roaming\Python\python38\site-packages\pysimplesoap\client.py",line 317,in send
    response,content = self.http.request(
  File "C:\Users\user1\AppData\Roaming\Python\python38\site-packages\pysimplesoap\transport.py",line 145,in request
    f = self.request_opener(req,timeout=self._timeout)
  File "C:\Program Files\python38\lib\urllib\request.py",line 531,in open
    response = meth(req,response)
  File "C:\Program Files\python38\lib\urllib\request.py",line 640,in http_response
    response = self.parent.error(
  File "C:\Program Files\python38\lib\urllib\request.py",line 569,in error
    return self._call_chain(*args)
  File "C:\Program Files\python38\lib\urllib\request.py",line 502,in _call_chain
    result = func(*args)
  File "C:\Program Files\python38\lib\urllib\request.py",line 649,in http_error_default
    raise HTTPError(req.full_url,code,msg,hdrs,fp)
urllib.error.HTTPError: HTTP Error 405: Method Not Allowed

这是使用SoapUI的请求和响应:

请求:

POST http://localhost:8000/ HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: "say_hello"
Content-Length: 220
Host: localhost:8000
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)

响应:

HTTP/1.1 405 Method Not Allowed
Server: TwistedWeb/20.3.0
Date: Fri,25 Sep 2020 09:39:09 GMT
Content-Type: text/xml; charset=utf-8
Content-Length: 389

<?xml version='1.0' encoding='UTF-8'?>
<soap11env:Envelope xmlns:soap11env="http://schemas.xmlsoap.org/soap/envelope/"><soap11env:Body><soap11env:Fault><faultcode>soap11env:Client.RequestNotAllowed</faultcode><faultstring>You must issue a POST request with the Content-Type header properly set.</faultstring><faultactor></faultactor></soap11env:Fault></soap11env:Body></soap11env:Envelope>

如上所述,如果我将传输层从Twisted更改为Wsgi,则不会收到错误Here,您可以从SoapUI中看到有关Wsgi服务器的请求和响应的示例。

除了导入行以外,Twisted服务器和Wsgi服务器之间的代码唯一区别是:

logging.basicConfig(level=logging.DEBUG)
logging.getLogger('spyne.protocol.xml').setLevel(logging.DEBUG)
app = Application([HelloWorldService],)

wsgi_app = WsgiApplication(app)
server = make_server('127.0.0.1',7789,wsgi_app)

print("listening to http://127.0.0.1:7789")
print("wsdl is at: http://localhost:7789/?wsdl")

server.serve_forever()

我该怎么办?

我的python版本是3.8.1。 Spyne版本为2.13.15,Twisted版本为20.3.0

谢谢!

编辑01/10/2020 :客户端代码中有错误。在第3行,我编写了client.say_hello()而不是cli.say_hello()。在这里写下问题时,这只是输入错误

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。