Search code examples
pythonpython-requestspython-unittestweb2pypythonanywhere

Pass files with json payload in single requests to web2py endpoint


I wrote endpoint called foobar in default.py controller of web2py, it looks like

@service.json
def foobar(*args, **vars):
    payload = request.vars.student
    print(payload)
    #Above payload prints [rollNo, firstName, lastName]
    #Expected is {"rollNo": 6299857, "FirstName": Prasad, "LastName": Telkikar}

    fileObj= request.vars.video
    studentActivity = fileObj.file.read()
    
    #Currently I am unable to do it from unit test, but it works from postman
    print(f"Student's Roll number = {payload.rollNo} \n FirstName = {payload.firstName},  \n lastName = {payload.lastName}, fileSize = {fileObj.file.tell()}")

    #storing studentActivity video to specific location
    #Doing business logic

Now I am writing unit test for this endpoint, where i am trying to call this endpoint using requests,

import requests
import unittest

...
    
class TestStudentsData(unittest.TestCase):
    def test_Individual_student(self):
        payload = dict(rollNo=6299857, firstName="Prasad", lastName="Telkikar")
        url = "http://127.0.0.1:8000/v1/foobar"
        header = dict(Authorization="Bearer <Token>")
        response = requests.post(url,files={'studentActivity':open("Activity.mp4", 'rb')},  data=payload, headers=headers)

        self.assertEqual(response.status_code, 200)

if __name__ == '__main__':
    unittest.main(verbosity=2)

Here I am unable to pass student payload as a json.

How can I pass json payload with studentActivity file using requests?


What I tried so far?

  • I tried both the approaches given in this SO answer.
  • I read requests documentation where it says "the json parameter is ignored if either data or files is passed" requests documentation

Solution

  • I resolved this problem by adding proper content-type to payload,

    import os
    
    ...
    
    filePath = os.getcwd()
    files = {'studentActivity':open(filePath, "Activity.mp4", 'rb'), 
                 'payload':(None, payload, 'application/json')}
                                           #^^^^^^^^^^^^^^^^^ This was missing
     
    response = requests.post(url,files={'studentActivity':open("Activity.mp4", 'rb')},  data=payload, headers=headers)