如何将 Python 中的 Multipart/related 请求发送到 SOAP 服务器?
How to send Multipart/related requests in Python to SOAP server?
我必须通过 multipart/related HTTP POST.
将文件发送到 SOAP 服务器
我是这样从头开始构建消息的:
from email.mime.application import MIMEApplication
from email.encoders import encode_7or8bit
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
envelope = """<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xop="http://www.w3.org/2004/08/xop/include" xmlns:xmime5="http://www.w3.org/2005/05/xmlmime" xmlns:osc-data="http://oracc.org/wsdl/ows.xsd" xmlns:osc-meth="http://oracc.org/wsdl/ows.wsdl"><SOAP-ENV:Body><osc-meth:Request><osc-data:keys><osc-data:key>atf</osc-data:key><osc-data:key>tests/mini</osc-data:key><osc-data:key>00atf/hyphens.atf</osc-data:key></osc-data:keys><osc-data:data><osc-data:item xmime5:contentType="*/*"><xop:Include href="cid:id6"/></osc-data:item></osc-data:data></osc-meth:Request></SOAP-ENV:Body></SOAP-ENV:Envelope>"""
mtompkg = MIMEMultipart('related',boundary='============boundary============', charset='utf-8', type='application/xop+xml', start='<SOAP-ENV:Envelope>')
#Doesn't like the hyphen in start-info when passing as MIMEMultipart param
mtompkg.set_param('start-info', 'application/soap+xml')
mtompkg['Host'] = "http://oracc.museum.upenn.edu:8085"
mtompkg['Connection'] = "close"
del(mtompkg['mime-version'])
rootpkg = MIMEApplication(envelope, 'xop+xml', encode_7or8bit)
rootpkg.set_param('charset', 'utf-8')
rootpkg.set_param('type', 'application/soap+xml')
rootpkg.add_header('Content-ID', '<SOAP-ENV:Envelope>')
del(rootpkg['Content-Transfer-Encoding'])
rootpkg.add_header('Content-Transfer-Encoding', 'binary')
del(rootpkg['mime-version'])
mtompkg.attach(rootpkg)
document = MIMEBase('*','*')
document['Content-Transfer-Encoding'] = "binary"
document['Content-ID'] = "<id6>"
filename = "./request.zip"
document.set_payload(open(filename,'rb').read())
del(document['mime-version'])
mtompkg.attach(document)
bound = '--%s' % (mtompkg.get_boundary(), )
marray = mtompkg.as_string().split(bound)
mtombody = bound
mtombody += bound.join(marray[1:])
mtompkg.add_header("Content-Length", str(len(mtombody)))
这会导致一条消息与我从 SOAP 服务器开发人员那里得到的示例消息相匹配,我们知道它工作正常:
Content-Type: multipart/related; start="<SOAP-ENV:Envelope>"; charset="utf-8";
type="application/xop+xml"; boundary="============boundary============";
start-info="application/soap+xml"
Host: http://MY_URL:SOME_PORT
Connection: close
Content-Length: 1429
--============boundary============
Content-Type: application/xop+xml; charset="utf-8"; type="application/soap+xml"
Content-ID: <SOAP-ENV:Envelope>
Content-Transfer-Encoding: binary
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xop="http://www.w3.org/2004/08/xop/include" xmlns:xmime5="http://www.w3.org/2005/05/xmlmime" xmlns:osc-data="http://oracc.org/wsdl/ows.xsd" xmlns:osc-meth="http://oracc.org/wsdl/ows.wsdl"><SOAP-ENV:Body><osc-meth:Request><osc-data:keys><osc-data:key>atf</osc-data:key><osc-data:key>tests/mini</osc-data:key><osc-data:key>00atf/hyphens.atf</osc-data:key></osc-data:keys><osc-data:data><osc-data:item xmime5:contentType="*/*"><xop:Include href="cid:id6"/></osc-data:item></osc-data:data></osc-meth:Request></SOAP-ENV:Body></SOAP-ENV:Envelope>
--============boundary============
Content-Type: */*
Content-Transfer-Encoding: binary
Content-ID: <id6>
P�AtG.�Uen00atf/hyphens.atfUT cOVJOVux
�S
04A.傢���+����b��L.�Ē4+���T�Ҽ���T.�PNb^�BEi���BuN飦�ڌDݤLݢR.��\+�Ĥ̢�h0��P�AtG.�Uen��00atf/hyphens.atfUTcOVux
�PKW�
--============boundary============--
为了发送它,我尝试了请求、urllib2 和 httplib,我得到的行为是服务器永远挂起。我已经尝试设置超时,希望能从服务器给我某种输出,但它不起作用。这是我试过的:
有请求:
import requests
url = 'http://MY_URL:SOME_PORT'
headers = dict(mtompkg.items())
body = mtompkg.as_string().split('\n\n', 1)[1]
response = requests.post(url, data=body, headers=headers)
使用 urllib2:
import urllib2
request = urllib2.Request('http://MY_URL:SOME_PORT', body, headers)
urllib2.urlopen(request).read()
使用 httplib:
import urlparse
import httplib
schema, netloc, url, params, query, fragments = urlparse.urlparse('http://MY_URL:SOME_PORT')
http = httplib.HTTPConnection(netloc)
http.connect()
http.putrequest("POST", 'http://MY_URL:SOME_PORT')
http.putheader('Content-type', mtompkg['Host'])
http.putheader('Content-type',mtompkg['Content-Type'])
http.putheader('Content-Length", str(1429))
http.endheaders()
http.send(body)
response = http.getresponse()
suds、suds-jurko、SOAPpy 等高级选项似乎不支持 multiform/related 附件。我 运行 没有可供测试的选项,因此非常感谢任何形式的帮助。
通过在这一行之后添加以下行,我能够让它工作
body = mtompkg.as_string().split('\n\n', 1)[1]
#RFC spec asks you to use \r\n instead of python default of \n
body = body.replace('\n', '\r\n', 5)
我必须通过 multipart/related HTTP POST.
将文件发送到 SOAP 服务器我是这样从头开始构建消息的:
from email.mime.application import MIMEApplication
from email.encoders import encode_7or8bit
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
envelope = """<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xop="http://www.w3.org/2004/08/xop/include" xmlns:xmime5="http://www.w3.org/2005/05/xmlmime" xmlns:osc-data="http://oracc.org/wsdl/ows.xsd" xmlns:osc-meth="http://oracc.org/wsdl/ows.wsdl"><SOAP-ENV:Body><osc-meth:Request><osc-data:keys><osc-data:key>atf</osc-data:key><osc-data:key>tests/mini</osc-data:key><osc-data:key>00atf/hyphens.atf</osc-data:key></osc-data:keys><osc-data:data><osc-data:item xmime5:contentType="*/*"><xop:Include href="cid:id6"/></osc-data:item></osc-data:data></osc-meth:Request></SOAP-ENV:Body></SOAP-ENV:Envelope>"""
mtompkg = MIMEMultipart('related',boundary='============boundary============', charset='utf-8', type='application/xop+xml', start='<SOAP-ENV:Envelope>')
#Doesn't like the hyphen in start-info when passing as MIMEMultipart param
mtompkg.set_param('start-info', 'application/soap+xml')
mtompkg['Host'] = "http://oracc.museum.upenn.edu:8085"
mtompkg['Connection'] = "close"
del(mtompkg['mime-version'])
rootpkg = MIMEApplication(envelope, 'xop+xml', encode_7or8bit)
rootpkg.set_param('charset', 'utf-8')
rootpkg.set_param('type', 'application/soap+xml')
rootpkg.add_header('Content-ID', '<SOAP-ENV:Envelope>')
del(rootpkg['Content-Transfer-Encoding'])
rootpkg.add_header('Content-Transfer-Encoding', 'binary')
del(rootpkg['mime-version'])
mtompkg.attach(rootpkg)
document = MIMEBase('*','*')
document['Content-Transfer-Encoding'] = "binary"
document['Content-ID'] = "<id6>"
filename = "./request.zip"
document.set_payload(open(filename,'rb').read())
del(document['mime-version'])
mtompkg.attach(document)
bound = '--%s' % (mtompkg.get_boundary(), )
marray = mtompkg.as_string().split(bound)
mtombody = bound
mtombody += bound.join(marray[1:])
mtompkg.add_header("Content-Length", str(len(mtombody)))
这会导致一条消息与我从 SOAP 服务器开发人员那里得到的示例消息相匹配,我们知道它工作正常:
Content-Type: multipart/related; start="<SOAP-ENV:Envelope>"; charset="utf-8";
type="application/xop+xml"; boundary="============boundary============";
start-info="application/soap+xml"
Host: http://MY_URL:SOME_PORT
Connection: close
Content-Length: 1429
--============boundary============
Content-Type: application/xop+xml; charset="utf-8"; type="application/soap+xml"
Content-ID: <SOAP-ENV:Envelope>
Content-Transfer-Encoding: binary
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:SOAP-ENC="http://www.w3.org/2003/05/soap-encoding" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xop="http://www.w3.org/2004/08/xop/include" xmlns:xmime5="http://www.w3.org/2005/05/xmlmime" xmlns:osc-data="http://oracc.org/wsdl/ows.xsd" xmlns:osc-meth="http://oracc.org/wsdl/ows.wsdl"><SOAP-ENV:Body><osc-meth:Request><osc-data:keys><osc-data:key>atf</osc-data:key><osc-data:key>tests/mini</osc-data:key><osc-data:key>00atf/hyphens.atf</osc-data:key></osc-data:keys><osc-data:data><osc-data:item xmime5:contentType="*/*"><xop:Include href="cid:id6"/></osc-data:item></osc-data:data></osc-meth:Request></SOAP-ENV:Body></SOAP-ENV:Envelope>
--============boundary============
Content-Type: */*
Content-Transfer-Encoding: binary
Content-ID: <id6>
P�AtG.�Uen00atf/hyphens.atfUT cOVJOVux
�S
04A.傢���+����b��L.�Ē4+���T�Ҽ���T.�PNb^�BEi���BuN飦�ڌDݤLݢR.��\+�Ĥ̢�h0��P�AtG.�Uen��00atf/hyphens.atfUTcOVux
�PKW�
--============boundary============--
为了发送它,我尝试了请求、urllib2 和 httplib,我得到的行为是服务器永远挂起。我已经尝试设置超时,希望能从服务器给我某种输出,但它不起作用。这是我试过的:
有请求:
import requests
url = 'http://MY_URL:SOME_PORT'
headers = dict(mtompkg.items())
body = mtompkg.as_string().split('\n\n', 1)[1]
response = requests.post(url, data=body, headers=headers)
使用 urllib2:
import urllib2
request = urllib2.Request('http://MY_URL:SOME_PORT', body, headers)
urllib2.urlopen(request).read()
使用 httplib:
import urlparse
import httplib
schema, netloc, url, params, query, fragments = urlparse.urlparse('http://MY_URL:SOME_PORT')
http = httplib.HTTPConnection(netloc)
http.connect()
http.putrequest("POST", 'http://MY_URL:SOME_PORT')
http.putheader('Content-type', mtompkg['Host'])
http.putheader('Content-type',mtompkg['Content-Type'])
http.putheader('Content-Length", str(1429))
http.endheaders()
http.send(body)
response = http.getresponse()
suds、suds-jurko、SOAPpy 等高级选项似乎不支持 multiform/related 附件。我 运行 没有可供测试的选项,因此非常感谢任何形式的帮助。
通过在这一行之后添加以下行,我能够让它工作
body = mtompkg.as_string().split('\n\n', 1)[1]
#RFC spec asks you to use \r\n instead of python default of \n
body = body.replace('\n', '\r\n', 5)