1

The task is post request to some TTS(text to speech) endpoint, and get audio from response. The endpoint is in private network so I cannot share with you to test against directly, but my question is not domain specific and I think it is a general http question.

There's existing working curl and python2 scripts, as following:

curl -v  -H  "Content-Type:multipart/form-data;boundary=message_boundary_0001" -H "Accept:audio/ogg;codecs=opus;" --data-binary @request.txt ip:port/someother/ -m 10 -o response.txt

requests.txt:

    --message_boundary_0001--
Content-Disposition: form-data; name="RequestData"
Content-Type: application/json; charset=utf-8

{
    jsondata1
}
--message_boundary_0001--
Content-Disposition: form-data; name="TtsParameter"; paramName="TEXT_TO_READ"
Content-Type: application/json; charset=utf-8

{
   jsondata2
}
--message_boundary_0001--

The python2 scripts mainly constructs the request content, then call httplib.HTTPConnection..request('POST', uri, some BytesIO(), headers). if needed I can paste the code here.

Now I want to rewrite using python 3 requests library.

I've searched requests doc, and one exsisting SO question, and wrote following code, but got 400 error:

import requests
from requests_toolbelt import MultipartEncoder

headers = {'Accept': 'audio/ogg;codecs=opus;',
           'Connection': 'keep-alive',
           'Content-Type': 'multipart/form-data;boundary=message_boundary_0001',
           }

RequestData = '''{
    jsondata1
}'''

TtsParameter_TEXT_TO_READ = '''{
   jsondata2
}'''

# url_origin = 'https://httpbin.org/post' # for debugging
url = 'http://ip:port/someother/'
resp = requests.post(url, headers=headers,
                     files={'RequestData': (None, RequestData), 'TtsParameter': (None, TtsParameter_TEXT_TO_READ)},
                     timeout=10)
print(resp.status_code)
print(resp.content.decode('utf-8'))

Which is not surprising, because in my curl request.txt there's a special Content-Disposition: Content-Disposition: form-data; name="TtsParameter"; paramName="TEXT_TO_READ", which is rarely seen in any tutorials.

So my question is how to pass the paramName="TEXT_TO_READ" to requests?

Update

the latest python code is pushed to github now. https://github.com/LeiYangGH/py3requeststts

Lei Yang
  • 3,970
  • 6
  • 38
  • 59

1 Answers1

2

There is no way to do this with vanilla requests.

There's a less than ideal way to do it with the toolbelt thought.

from requests_toolbelt.multipart import encoder


mpe = encoder.MultipartEncoder(fields={'RequestData': (None, RequestData), 'TtsParameter': (None, TtsParameter_TEXT_TO_READ)})
for part in mpe.parts:
   if 'name="TtsParameter"' in part.headers:
       part.headers = part.headers.replace('name="TtsParameter"',
                                           'name="TtsParameter"; paramName="TEXT_TO_READ"')

headers.update({'Content-Type': mpe.content_type})
requests.post(url, headers=headers, data=mpe)
Ian Stapleton Cordasco
  • 26,944
  • 4
  • 67
  • 72
  • thanks! but above code cannot run directly, part.headers are not of string type. I added some encoding code and can run now. but still cannot work. could you have a look at my code in [github](https://github.com/LeiYangGH/py3requeststts)? – Lei Yang Jan 30 '19 at 02:48
  • solved now. adding `to_string()` after mpe can get the correct request. thanks! – Lei Yang Feb 12 '19 at 09:55