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

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.

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.

Related

how to write an Axios query where I don't know a parent value?

I have a simple firebase DB which looks like
someNode: {
pushId-A: {param1: 'some string'},
pushId-B: {param1: 'some other string')
}
Using Axios GET, is there a way to query someNode for the value of param1 where I don't know the value of the pushId?
I want it to return the pushId of the node that contains "param1: 'some string'.
[EDIT}
I understand now that this is not an Axios question, but rather a Firebase question.
I've read the firebase docs here:
Filtering Data
But when I send the get request with any paramaters other than the auth token, I get back a 400 code. Which tells me it is incorrectly syntaxed.
here is the last part of the DB url
a8/data/houses/-L4OiszP7IOzkfh1f1NY/houseName
where houseName = "Aubergine"
Trying to filter for houseName I am passing:
axios.get('/houses.json/' + '?orderBy="houseName"&startAt="A"' + '&auth=' + token)
I'm keeping the params separate so I can more easily read and change them. Concatenating the strings has no effect.
No matter what combination of params I pass I get the 400 error code. If I leave them off, then the data comes through as expected.
What am I doing wrong????

How to properly make POST request

I'm trying to make my first POST request to an API. For some reason, I always get status 403 in return. I suspect it's the signature that is being incorrectly generated. The api-key and client id is for sure correct.
My code
nonce <-as.integer(Sys.time())
post_message <- paste0(nonce, data_client.id, data_key) # data_client.id = client id # data_key = key
sha.message <- toupper(digest::hmac(data_secret, object = post_message, algo = 'sha256', serialize = TRUE))
url <- 'https://www.bitstamp.net/api/v2/balance/'
body = list('API-KEY' = data_key, 'nonce' = nonce, 'signature' = sha.message)
httr::POST(url, body = body, verbose())
Output
<- HTTP/1.1 403 Authentication Failed
I'm trying to access the Bitstamp API: https://www.bitstamp.net/api/?package=Rbitcoin&version=0.9.2
All private API calls require authentication. For a successful
authentication you need to provide your API key, a signature and a
nonce parameter.
API KEY
To get an API key, go to "Account", "Security" and then "API Access".
Set permissions and click "Generate key".
NONCEN
once is a regular integer number. It must be increased with every
request you make. Read more about it here. Example: if you set nonce
to 1 in your first request, you must set it to at least 2 in your
second request. You are not required to start with 1. A common
practice is to use unix time for that parameter.
SIGNATURE
Signature is a HMAC-SHA256 encoded message containing nonce, customer
ID (can be found here) and API key. The HMAC-SHA256 code must be
generated using a secret key that was generated with your API key.
This code must be converted to it's hexadecimal representation (64
uppercase characters).
I'm not sure if your question is still standing, but based on your code, I managed to get it working. In fact, the main problem is in the body, the API documentation shows it expects 'key' instead of 'API-KEY'.
Also, serialize should be FALSE instead of TRUE.
At the moment this works (but the API may change):
nonce <-as.integer(Sys.time())
post_message <- paste0(nonce, data_client.id, data_key) # data_client.id = client id # data_key = key
sha.message <- toupper(digest::hmac(data_secret, object = post_message, algo = 'sha256', serialize = FALSE))
url <- 'https://www.bitstamp.net/api/v2/balance/'
body = list('key' = data_key, 'nonce' = nonce, 'signature' = sha.message)
httr::POST(url, body = body, verbose())

Technique to get an id back with an http query when empty array is returned

Let me first say I have a solution to this problem, but I'm interested in knowing whether there is a better way, and whether I'm doing something wrong.
I have a table of objects on the front-end of a webapp, I need to asynchronously load some data for the objects as it is needed on a per-object basis. The server returns a JSON array containing the data for that object, and the data contains the object's key, so I can update the object on the front-end with its data. When there is no data, I just get an empty array, which unfortunately presents no way of updating the object, since I don't have the key to update it with. This can result in another query later, which is a waste of time/resources. I can't modify the server, is there a way to do this nicely?
My current solution is to just set the object's data to an empty array before sending the request, then just update when the result is received if the result is nonempty.
I was wondering if there is a better/more idiomatic way to do this.
For reference, I'm using Elm with PostgREST as the backend.
You can use currying and partial function application to indicate which object ID should be updated.
I'm assuming you have some code similar to this:
type Msg
= ...
| FetchData Int
| DataFetched [Data]
| DataFetchFail Http.Error
-- inside the update function
update msg model =
case msg of
...
FetchData id =
model ! [ Task.perform DataFetchFail DataFetched (Http.post ...) ]
If you define your DataFetched constructor to include the ID as the first parameter, you can use partial application to include the ID for future lookup, regardless of what the server returns.
Here's the same code chunks with this idea:
type Msg
= ...
| FetchData Int
| DataFetched Int [Data]
| DataFetchFail Http.Error
-- inside the update function
update msg model =
case msg of
...
FetchData id =
model ! [ Task.perform DataFetchFail (DataFetched id) (Http.post ...) ]
You could also add the ID to the Fail message for more fine-grained error messages.

Convert string to map in lua

I am quite new to lua. I trying to convert a string of the form
{"result": "success", "data":{"shouldLoad":"true"}"}
into lua map. So that I can access it like json. e.g. someMap[data][shouldLoad] => true
I dont have any json bindings in lua. I also tried loadstring to convert string of the form {"result" = "success", "data"={"shouldLoad"="true"}"}, which is not working.
Following, is the code snippet, where I am calling getLocation hook, which in turn returns json stringified map. Now I want to access some keys from this response body and take some decisions accordingly.
access_by_lua "
local res = ngx.location.capture('/getLocation')
//res.body = {"result"= "success", "data" = {"shouldLoad" = "true"}}
local resData = loadstring('return '..res.body)()
local shoulLoad = resData['data']['shouldLoad']
"
When I try to load shouldLoad value, nginx error log reports error saying trying to index nil value.
How do I access key value with either of the string formats. Please help.
The best answer is to consider a pre-existing JSON module, as suggested by Alexey Ten. Here's the list of JSON modules from Alexey.
I also wrote a short pure-Lua json module that you are free to use however you like. It's public domain, so you can use it, modify it, sell it, and don't need to provide any credit for it. To use that module you would write code like this:
local json = require 'json' -- At the top of your script.
local jsonStr = '{"result": "success", "data":{"shouldLoad":"true"}"}'
local myTable = json.parse(jsonStr)
-- Now you can access your table in the usual ways:
if myTable.result == 'success' then
print('shouldLoad =', myTable.data.shouldLoad)
end

Google Cloud Endpoints adding extra parameters

I'm using the 'endpoints-proto-datastore' library and a bit lost in how to add extra parameters to my requests.
Basically I want to add these fields [ID, token] with ID being required. Blossom.io is doing something similar, here Blossom.io Api
Here's my Post method
#Doctor.method(path='doctor', http_method='POST', name='doctor.insert')
def DoctorInsert(self, doctor):
#Edit
Without the Proto-Datastore library:
request = endpoints.ResourceContainer(
message_types.VoidMessage,
id=messages.IntegerField(1,variant=messages.Variant.INT32),
token=messages.IntegerField(2, variant=messages.Variant.INT32)
)
#endpoints.method(request, response,
path='doctor/{id}', http_method='POST',
name='doctor.insert')
How can I do the same using the proto-datastore library?
The way I do it is to add another property to the model decorated with #EndpointsAliasProperty and a setter. I wouldn't call it ID because it may confuse with the App Engine built-in ID.
class Doctor(EndpointsModel):
...
#EndpointsAliasProperty(
setter=set_doctorid, property_type=messages.StringField
)
def doctorid(self):
#Logic to retrieve the ID
return doctorid
def set_doctorid(self, value):
#The ID will be in the value, assign and store it in your model

Resources