Python send mtom message - python

How do I send an mtom message in python? I have tried using the requests library but I am getting an error from the server. The workflow is HTTP headers with a SOAP envelope and a binary attachment. I am using an MTOM template file which is structured as follows:
Content-Type: multipart/related;
boundary=boundary1234567890; type="application/xop+xml";
start="<0.urn:uuid:1FACEDB95C3509148F1570480012346#w3.org>"; start-info="text/xml"
Transfer-Encoding: chunked
SOAPAction: "soap-action"
--boundary1234567890
Content-Type: application/xop+xml; charset=UTF-8; type="text/xml"
Content-Transfer-Encoding: binary
Content-ID: <0.urn:uuid:1FACEDB95C3509148F1570480012346#w3.org>
set soap envelope here
--boundary1234567890
Content-Type: application/zip
Content-Transfer-Encoding: binary
Content-ID: <1.urn:uuid:1FACEDB95C3509148F1570480012347#w3.org>
set binary attachment here
I then send the message with the python requests library as follows:
import requests
data = open(template, 'rb').read()
response = requests.post(url, data=data, headers={})
However, I am getting an error from the server saying that my request was not able to be processed. I am probably doing something wrong, but I do not know how to send an MTOM message. Any help would be greatly appreciated.

I think the only real support for MTOM
is currently in Java and C#.You can use Axis2/C which I believe supports MTOM and
put a Python wrapper around it.

Related

Http request boundaries getting caught in pdf decoding process

I'm trying to decode a base64 pdf file and send it to another endpoint.
I used a python policy for the decoding part and here's the code
import base64
pdfB64 = flow.getVariable("request.content")
pdfFile = base64.b64decode(pdfB64)
flow.setVariable("pdfFileDecoded",pdfFile)
Now, when I send my http post request which is below
headers :
Accept : */*
boundary : --Boundaryy
--Boundaryy
Content-Disposition: form-data; name="testdu12janvier"; filename="testdu12janvier.pdf"
Content-Type: application/pdf
<< Heres is sensitive data which is basically a base64 encoded pdf file >>
--Boundaryy--
When I send this POST request and trace it in Apigee Edge, I notice that something else is encoded before the pdf file I think its either the boundary or one of the headers. This makes a corrupt pdf file which can't be read.
How do I isolate the pdf file from the request body without removing boundaries? as I'll need to send multiple in near future.

Sending a raw XML request to a SOAP service with Zeep (trying to duplicate an argument)

I am able to send a simple SOAP request with Zeep.
with client.settings(strict=False):
resp = client.service.demandeFicheProduit(
demandeur=self.xxx, motDePasse=self.yyy,
ean13s="foo",
multiple=False)
However, I need to give multiple times the ean13s argument, which is not possible in a Python function call, so I figured I need to build the XML myself.
With Zeep's debug on, I see that the XML sent is this:
<?xml version='1.0' encoding='utf-8'?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Body>
<ns0:demandeFicheProduit xmlns:ns0="http://fel.ws.accelya.com/">
<demandeur>xxx
</demandeur>
<motDePasse>yyy
</motDePasse>
<ean13s>foo
</ean13s>
<multiple>false
</multiple>
</ns0:demandeFicheProduit>
</soap-env:Body>
</soap-env:Envelope>
So I only need to replicate the
<ean13s>foo
</ean13s>
part.
Looking into Zeep, I see a Transport.post_xml method: https://github.com/mvantellingen/python-zeep/blob/da8a88b9f5/src/zeep/transports.py#L86 which takes an lxml tree as parameter. (doc)
def post_xml(self, address, envelope, headers):
"""Post the envelope xml element to the given address with the headers.
This method is intended to be overriden if you want to customize the
serialization of the xml element. By default the body is formatted
and encoded as utf-8. See ``zeep.wsdl.utils.etree_to_string``.
"""
message = etree_to_string(envelope)
return self.post(address, message, headers)
I tried a post_raw_xml method, without etree_to_string:
def post_raw_xml(self, address, raw_envelope, headers):
return self.post(address, raw_envelope, headers)
I call it with the above XML
transport = zeep.Transport()
transport.post_raw_xml("adress", my_xml, {}) # {}: headers?
and the response status is OK (200), however the service answers it is an invalid request.
Are there XML / SOAP intricacies I didn't pay attention to? Encoding? Headers? (here {})
edit: after spying a bit more the Zeep internals, the headers it sends are
{'SOAPAction': '""', 'Content-Type': 'text/xml; charset=utf-8'}
So I thought I could simply use requests.post, to no avail yet. To use requests, see Sending SOAP request using Python Requests
How to otherwise build an XML manually?
Any more idea on how I can duplicate the eans13 argument?
Thank you.
I solved my problem without Zeep.
I send a raw XML string with requests, I don't construct an XML manually with lxml or xsd.
What helped me was print-debugging the internals of Zeep's transport.py/post method (so the headers are {'SOAPAction': '""', 'Content-Type': 'text/xml; charset=utf-8'}
),
this other question: Sending SOAP request using Python Requests to send a post request:
requests.post(url, data=xml, headers=headers)
and being careful on the XML string (yes there is a newline character after the closing <?xml> tag).
The downside is to parse the XML back.

Create SOAP requst by zeep

I'm working on WSDL. I need to create SOAP request using by zeep package. So I implemented the code that
from zeep import Client
service = Client('https://api.mindbodyonline.com/0_5_1/ClientService.asmx?wsdl')
request = service.service.GetClientServices
But I could not move on. Because I could not login through this request and pass parameters. I want to fill following all requirement through this request. could anyone tell me that how to pass all this parameters by this request.
This is HTTP headers
SOAPAction: "http://clients.mindbodyonline.com/api/0_5_1/GetClientServices"
Content-Type: text/xml; charset="utf-8"

How to parse raw HTTP request (to get Soap XML from its content) with Python?

I have raw http POST request with Soap message inside:
POST / HTTP/1.1
Host: localhost
Content-Type: application/soap+xml; charset=utf-8
Content-Length: 431
<?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>
</soap12:Body>
</soap12:Envelope>
I would like use already implemented Python library to get XML content (SOAP message) from this raw data. And also would be nice to get HTTP request other content (Http version, Host, content-type ...) I tried to search it, but no success.
I know what I could simple use find in string like i.e. "<?xml version="
and it will indicate the beginning of XML message and after read to the end of the raw request will get me full soap message. But it's not very elegant solution.
Any ideas of available libraries or tools?

OAuth and the YouTube API

I am trying to use the YouTube services with OAuth. I have been able to obtain request tokens, authorize them and transform them into access tokens.
Now I am trying to use those tokens to actually do requests to the YouTube services. For instance I am trying to add a video to a playlist. Hence I am making a POST request to
https://gdata.youtube.com/feeds/api/playlists/XXXXXXXXXXXX
sending a body of
<?xml version="1.0" encoding="UTF-8"?>
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:yt="http://gdata.youtube.com/schemas/2007">
<id>XXXXXXXXX</id>
</entry>
and with the headers
Gdata-version: 2
Content-type: application/atom+xml
Authorization: OAuth oauth_consumer_key="www.xxxxx.xx",
oauth_nonce="xxxxxxxxxxxxxxxxxxxxxxxxx",
oauth_signature="XXXXXXXXXXXXXXXXXXX",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1310985770",
oauth_token="1%2FXXXXXXXXXXXXXXXXXXXX",
oauth_version="1.0"
X-gdata-key: key="XXXXXXXXXXXXXXXXXXXXXXXXX"
plus some standard headers (Host and Content-Length) which are added by urllib2 (I am using Python) at the moment of the request.
Unfortunately, I get an Error 401: Unknown authorization header, and the headers of the response are
X-GData-User-Country: IT
WWW-Authenticate: GoogleLogin service="youtube",realm="https://www.google.com/youtube/accounts/ClientLogin"
Content-Type: text/html; charset=UTF-8
Content-Length: 179
Date: Mon, 18 Jul 2011 10:42:50 GMT
Expires: Mon, 18 Jul 2011 10:42:50 GMT
Cache-Control: private, max-age=0
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
Server: GSE
Connection: close
In particular I do not know how to interpret the WWW-Authenticate header, whose realm hints to ClientLogin.
I have also tried to play with the OAuth Playground and the Authorization header sent by that site looks exactly like mine, except for the order of the fields. Still, on the plyaground everything works. Well, almost: I get an error telling that a Developer key is missing, but that is reasonable since there is no way to add one on the playground. Still, I go past the Error 401.
I have also tried to manually copy the Authorization header from there, and I got an Error 400: Bad request.
What am I doing wrong?
Turns out the problem was the newline before xmlns:yt. I was able to debug this using ncat, as suggeested here, and inspecting the full response.
i would suggest using the oauth python module, because it much more simple and takes care of the auth headers :) https://github.com/simplegeo/python-oauth2, as a solution i suggest you encode your parameters with 'utf-8' , i had a similar problem, and the solution was that google was expecting utf-8 encoded strings

Categories

Resources