python-requestsweb2pyweb2py-modules

Web2py: Sending JSON Data via a Rest API post call in Web2py scheduler


I have a form whose one field is type IS_JSON

db.define_table('vmPowerOpsTable',
                Field('launchId',label=T('Launch ID'),default =datetime.datetime.now().strftime("%d%m%y%H%M%S")),
                Field('launchDate',label=T('Launched On'),default=datetime.datetime.now()),
                Field('launchBy',label=T('Launched By'),default = auth.user.email if auth.user else "Anonymous"),
                Field('inputJson','text',label=T('Input JSON*'),
                      requires = [IS_NOT_EMPTY(error_message='Input JSON is required'),IS_JSON(error_message='Invalid JSON')]),
                migrate=True)

When the user submits this Form, this data is also simultaneously inserted to another table.

db.opStatus.insert(launchId=vmops_launchid,launchDate=vmops_launchdate
                               ,launchBy=vmops_launchBy,opsType=operation_type,
                               opsData=vmops_inputJson,
                               statusDetail="Pending")
db.commit()

Now from the scheduler, I am trying to retrieve this data and make a POST request.

vm_power_opStatus_row_data = vm_power_opStatus_row.opsData

Note in the above step I am able to retrieve the data. (I inserted it in a DB and saw the field exactly matches what the user has entered.

Then from the scheduler, I do a POST.

power_response = requests.post(vm_power_op_url, json=vm_power_opStatus_row_data)

The POST request is handled by a function in my controller.

Controller Function:

@request.restful()
def vmPowerOperation():
    response.view = 'generic.json'
    si = None
    def POST(*args, **vars):
        jsonBody = request.vars
        print "Debug 1"+ str(jsonBody) ##-> Here it returns blank in jsonBody.

But if I do the same request from Outside(POSTMAN client or even python request ) I get the desired result.

Is anything going wrong with the data type when I am trying to fetch it from the table.


Solution

  • power_response = requests.post(vm_power_op_url,
                                   json=vm_power_opStatus_row_data)
    

    It appears that vm_power_opStatus_row_data is already a JSON-encoded string. However, the json argument to requests.post() should be a Python object, not a string (requests will automatically encode the Python object to JSON and set the content type appropriately). So, the above should be:

    power_response = requests.post(vm_power_op_url,
                                   json=json.loads(vm_power_opStatus_row_data))
    

    Alternatively, you can use the data argument and set the content type to JSON:

    power_response = requests.post(vm_power_op_url,
                                   data=vm_power_opStatus_row_data,
                                   headers={'Content-Type': 'application/json')
    

    Also, note that in your REST POST function, request.vars is already passed to the function as **vars, so within the function, you can simply refer to vars rather than request.vars.