0

I have a working curl command as follows :

    curl -X POST \
      http://localhost:7777/upload \
      -H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \
      -F file_name=temp.py \
      -F file_content=@/Users/blah/requirements.txt \
      -F d_name=blah \
      -F owner=blah \
      -F name=blah \
      -F local_git_path=blah \
      -F local_git_hash=blah

Ofcourse I fiddled around with POSTMAN - and got my POST to work from my computer to my test service. The issue I am facing is when I am writing a client for my server. A sample conversion for the above I have is as follows :

    def upload(self, file_path):
        api_url = os.path.join(Config().get_url(), "upload")
        payload = "------WebKitFormBoundaryTESTING\r\nContent-Disposition: form-data; " \
                  "name=\"file_name\"\r\n\r\n{filename}\r\n" \
                  "------WebKitFormBoundaryTESTING\r\nContent-Disposition: form-data; " \
                  "name=\"file_content\"; filename=\"{file_content}\"\r\nContent-Type: text/plain\r\n\r\n\r\n" \
                  "------WebKitFormBoundaryTESTING\r\nContent-Disposition: form-data; " \
                  "name=\"d_name\"\r\n\r\n{dname}\r\n" \
                  "------WebKitFormBoundaryTESTING\r\nContent-Disposition: form-data; " \
                  "name=\"owner\"\r\n\r\n{owner}\r\n" \
                  "------WebKitFormBoundaryTESTING\r\nContent-Disposition: form-data; " \
                  "name=\"name\"\r\n\r\n{name}\r\n" \
                  "------WebKitFormBoundaryTESTING\r\nContent-Disposition: form-data; " \
                  "name=\"local_git_path\"\r\n\r\nblah\r\n" \
                  "------WebKitFormBoundaryTESTING\r\nContent-Disposition: form-data; " \
                  "name=\"local_git_hash\"\r\n\r\nblah\r\n" \
                  "------WebKitFormBoundaryAAFDAGSTORE--".format(filename="temp.py", file_content=file_path, dname="blah", owner="blah",
                                                                 name="blah")
        headers = {
            'content-type': "multipart/form-data; boundary=----WebKitFormBoundaryTESTING",
            'cache-control': "no-cache"
        }

        response = requests.post(url=api_url, data=payload, headers=headers)

        return json.loads(response.text)

This really has started to annoy me, because the POST works fine - but my file content received on the server side is an EMPTY file. This happens only in the python side.

But doen'tt happen with cURL. I am pretty comfortable with request module. I prefer not changing it.

Also the webserver is a flask application - seems to be working fine because my cURL works.

Update#1 Also tried the following, this was my first approach before I changed to webkits. This really tripped me badly - I was getting a 404 from my webserver. This was strange because my cURL was still working indicating - my webserver was doing its job right.

def upload(self, file_path):
    headers = {
        'Content-Type': "application/json",
        'content-type': "multipart/form-data"
    }
    api_url = os.path.join(Config().get_url(), "upload")
    files_dict = dict(file_content=open(file_path, "rb"),
                      file_name=(None, "temp.py"),
                      dag_name=(None, "dag_name"),
                      owner=(None, "blah"),
                      name=(None, "blah"),
                      local_git_path=(None, "blah"),
                      local_git_hash=(None, "blah"))
    response = requests.post(url=api_url, files=files_dict, headers=headers)
    return json.loads(response.text)
sudhishkr
  • 3,318
  • 5
  • 33
  • 55
  • is there a particular reason you are building the payload like this as opposed to a dictionary? – gold_cy Mar 12 '19 at 17:58
  • @aws_apprentice : thats a whole new discussion .. I should have said that approach was tried as well. I used the `request.post` with `files` dict input .. and that was causing an error response from my webserver. I went with the assumption that my request call was WRONG. Because of the same reason I explained above. After that I decided to try the webkit approach which was an automated code generated stub from `POSTMAN` that I used to proceed with. – sudhishkr Mar 12 '19 at 18:00
  • can you edit the question with that approach, people such as myself might not be familiar with the format generated by Postman – gold_cy Mar 12 '19 at 18:01
  • yes sir. will do that asap! – sudhishkr Mar 12 '19 at 18:02
  • But you are not posting a file, your `"name="file_content"` section is *empty*. Don't build a multipart-form section manually, though. – Martijn Pieters Mar 12 '19 at 18:02
  • so `file_content` is the field that points to the local file location on my computer. there is another field called `name`. I am not sure if I confused you with my chosen names, or are you suggesting having a key-value setting where you set the key by calling `name=file_content` as you indicated. – sudhishkr Mar 12 '19 at 18:05
  • Just use the native multipart/form support by including your open file object in the `files` dictionary, the other fields in the `data` dictionary, and leave setting the boundary and headers to `requests`: `with open('/Users/blah/requirements.txt', 'rb') as file_to_post: `files = {'file_content': file_to_post}`, `data = {'file_name': 'temp.py', 'd_name': 'blah', ...}`, `response = requests.post(url, files=files, data=data)`. – Martijn Pieters Mar 12 '19 at 18:08
  • Your updated code snippet sets `content-type`. *Don't do that*. You set it to two different content types, both of them wrong, and because you set those, you interfered with the automatic Content-Type header generation that is done for you when using `files`. – Martijn Pieters Mar 12 '19 at 18:08
  • okay cool .. i think i have understood what you are suggesting. Let me try that out quickly. Thanks! – sudhishkr Mar 12 '19 at 18:09
  • all i needed was to NOT `override` the `headers` like you mentioned. Thanks for helping me here. Not sure how to close this issue out. Do we mark it as a duplicate and move on? – sudhishkr Mar 12 '19 at 18:26

0 Answers0