POST method in Power Query 400 Bad Request - post

I'm trying to receive data from an API, but it's POST method, so I'm trying to send the data, but it won't
let
body = [COD_INT= "886000", COD_INT_CSO= "0"],
Parsed_JSON = Json.FromValue(body),
Source = Web.Contents("https://apixxxxxxx.yyyyyyyyy.com.br/api/CursosConcluidos",
[
Headers= [#"User-Token" ="673E9CAF-xxxxxxxxxxx-xxx-xx-968"],
Content = Parsed_JSON
]
),
final = Json.Document(Source)
in
final
In Postman it works perfectly
Print from Postman
I tried the same from here but it's the same result
Changing or not the ParsedJSON in Binary gives the same result, 400

Related

Acessing Post Rest Api using Power query

I am new to power BI and power query, I am trying to get the JSon data from Post rest api. But i always get a 400 error. Where am I going wrong.
let
authkey ="Bearer xxxx",
url = "https://example.com/xxx",
body = "{""objectId"":""settlement_entity"",""queryString"":""?itemrefs=settlementreference,itemdescription&perpage=12&includekeyitems=true&includeforeignkeyitems=true&includetimestamp=true&includeadditionalmeta=true""}",
Source = Json.Document(Web.Contents(url,
[
Headers = [#"Authorization"= authkey,#"Content-Type"="application/json"], Content = Text.ToBinary(body)
]
))
in
Source
Ok I fixed the issue the body was missing square bracket
let
authkey ="Bearer xxxx",
url = "https://example.com/xxx",
body = "[{""objectId"":""settlement_entity"",""queryString"":""?itemrefs=settlementreference,itemdescription&perpage=12&includekeyitems=true&includeforeignkeyitems=true&includetimestamp=true&includeadditionalmeta=true""]}",
Source = Json.Document(Web.Contents(url,
[
Headers = [#"Authorization"= authkey,#"Content-Type"="application/json"], Content = Text.ToBinary(body)
]
))
in
Source

Substituting in string variables in http post request payload

I'm iterating over a for loop of a list of ingredients (strings) calling a http post request for each one to obtain their nutritional info.
The following works.
data = '{"query": "black olives"}'
r = requests.post(url, headers = headers, data = data)
body = json.loads(r.text)
But this:
for ingredient in ingredients:
data = '{"query": ' + ingredient + '}'
r = requests.post(url, headers = headers, data = data)
body = json.loads(r.text)
gives the error:
{'message': 'Unexpected token r in JSON at position 10'}
How do I fix it?
Edit: It works now.
It is safer to construct JSON from a dict.
Try this:
import json
for ingredient in ingredients:
data = {"query": ingredient}
# Two options : let requests do the json conversion of the dict
r = requests.post(url, headers = headers, json=data)
# or do it yourself
# r = requests.post(url, headers = headers, data=json.dumps(data))
body = json.loads(r.text)

With VoiceResponce - response.gather() with POST does not send Digits

I have a Twilio number configured to http://66.175.221.103:6543/ivr/860d247f4bc7 with GET.
The below code catches it in the GET and creates a voice response with the welcome message. The action is the same URL but with POST.
itemID = request.matchdict['itemid']
itemData = getItemData(request,itemID)
if itemData is not None:
itemResponses = getItemResponses(request,itemID)
if request.method == 'GET':
#Gather the response and POST to the same ID
response = VoiceResponse()
with response.gather(numDigits=1, action=request.route_url('ivr',itemid=itemID), method="POST") as g:
g.say(itemData["item_desc"],voice="alice", language="en-GB", loop=3)
return twiml(response)
else:
log.debug("*************888")
log.debug(request.POST)
log.debug("*************888")
soption = request.POST.get('Digits', '0')
noption = int(soption)
for resp in itemResponses:
if resp["resp_num"] == noption:
response = VoiceResponse()
response.redirect(request.route_url('ivr',itemid=resp["target_item"]))
return twiml(response)
resp = VoiceResponse()
resp.say("Error, was not able to find a response")
resp.hangup()
return twiml(resp)
That produces the following XML
<Response><Gather action="http://66.175.221.103:6543/ivr/860d247f4bc7" method="POST" numDigits="1"><Say language="en-GB" loop="3" voice="alice">Welcome to the Agricultural Podcast service. To listen to a podcast press 1. To request for new content press 2</Say></Gather></Response>
I press 1 for example and I get this on the post:
[('Called', '+17656133098'), ('ToState', 'IN'), ('CallerCountry', 'LS'), ('Direction', 'inbound'), ('CallerState', ''), ('ToZip', '46952'), ('CallSid', 'CAa127058ffcc4b148e8757ffb9025440c'), ('To', '+17656133098'), ('CallerZip', ''), ('ToCountry', 'US'), ('ApiVersion', '2010-04-01'), ('CalledZip', '46952'), ('CalledCity', 'MARION'), ('CallStatus', 'in-progress'), ('From', '+266696687'), ('AccountSid', 'ACaa8c3038f45a521b83c74789d51af27d'), ('CalledCountry', 'US'), ('CallerCity', ''), ('Caller', '+266696687'), ('FromCountry', 'LS'), ('ToCity', 'MARION'), ('FromCity', ''), ('CalledState', 'IN'), ('FromZip', ''), ('FromState', '')]
The Gather does a POST TO "http://66.175.221.103:6543/ivr/860d247f4bc7" but does not send "Digits" as part of the post.
Any idea why?
For some reason that is not documented in Twilio a get request to an URL cannot perform a post (using Gather) to the same URL. I separated the post and get in separated URLs and now all works fine.

Capture full response in Lua Socket call

I am trying to call a REST API through LUA. However, I am not able to capture full raw response returned by the API. Below is the code sample:
local http_socket = require("socket.http")
local pretty_print = require("pl.pretty")
local header = {
["x-device-type"] = "M",
["authorization"] = "ashdjkashd",
["x-app-secret"] = "asdasda",
["x-user-id"] = "asdasdasd"
}
r, c, h = http_socket.request {
method = "GET", -- Validation API Method
url = "http://google.com", -- Validation API URL
headers = header
}
print(r .. c)
pretty_print.dump(h)
I'm using lua 5.3, and luarocks version=2.4.1.
In variable c i am getting code, and in h there are a few headers. I need to capture full response returned by the API.
As you may know, luasocket's http.request supports two forms of usage. I'm assuming you need the second form to customize the resty request for that particular API.
In this case to capture the response body you'll need to use the sink field with ltn12.sink module. For example
local ltn12 = require 'ltn12'
-- ...
local res = {}
r, c, h, s = http_socket.request
{
method = "GET", -- Validation API Method
url = "http://google.com", -- Validation API URL
headers = header,
sink = ltn12.sink.table(res)
}
res = table.concat(res)
print(res)
The table.concat is needed since the response could be comprised of multiple chunk sizes(appended to res as it's received).
You can also write it out to file by replacing above with ltn12.sink.file, eg. using ltn12.sink.file(io.stdout) will dump the response to standard output.

OAuth authentication, invalid signature

I tired to port the request-oauth library (based on python-request) to Python 3 (with help of 2to3) but I have problems to validate a signature with StatusNet (same API as Twitter).
When I do a request to oauth/request_token, I have no problem but to oauth/access_token I have an error 401 Invalid signature. I don't understand why because it seems to me that what I sign is correct.
For example, with the python 2 code, cf hook.py and auth.py (original from the git repo), I get :
signing_key = '0de1456373dfc9349dd38a48e61fc844&136d6b9a597ee57d4338254812681acd',
signing_raw = 'POST&http%3A%2F%2Fstatus2.dotzero.me%2Fapi%2Foauth%2Faccess_token&oauth_consumer_key%3Dec3ad931b294b51a5ff595c732acb7a5%26oauth_nonce%3D33448267%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1332279747%26oauth_token%3D2131043f3516bcb730d391ed2033a880%26oauth_verifier%3D8816492%26oauth_version%3D1.0'
oauth_hook.token.key = '2131043f3516bcb730d391ed2033a880'
oauth_hook.token.secret = '136d6b9a597ee57d4338254812681acd'
request.data_and_params = {'oauth_version': '1.0', 'oauth_signature': 'xyjxH5QcfZXnG111L7qANZ+ahRI=',
'oauth_token': '2131043f3516bcb730d391ed2033a880', 'oauth_nonce': '33448267',
'oauth_timestamp': '1332279747', 'oauth_verifier': '8816492',
'oauth_consumer_key': 'ec3ad931b294b51a5ff595c732acb7a5',
'oauth_signature_method': 'HMAC-SHA1'}
and with my python 3 port, cf hook.py and auth.py, I get :
signing_key = '0de1456373dfc9349dd38a48e61fc844&136d6b9a597ee57d4338254812681acd',
signing_raw = 'POST&http%3A%2F%2Fstatus2.dotzero.me%2Fapi%2Foauth%2Faccess_token&oauth_consumer_key%3Dec3ad931b294b51a5ff595c732acb7a5%26oauth_nonce%3D52360702%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1332278837%26oauth_token%3D2131043f3516bcb730d391ed2033a880%26oauth_verifier%3D8816492%26oauth_verifier%3D8816492%26oauth_version%3D1.0'
oauth_hook.token.key = '2131043f3516bcb730d391ed2033a880'
oauth_hook.token.secret = '136d6b9a597ee57d4338254812681acd'
request.data_and_params = {'oauth_nonce': '52360702', 'oauth_timestamp': '1332278837',
'oauth_verifier': '8816492', 'oauth_consumer_key': 'ec3ad931b294b51a5ff595c732acb7a5',
'oauth_signature_method': 'HMAC-SHA1', 'oauth_version': '1.0',
'oauth_token': '2131043f3516bcb730d391ed2033a880',
'oauth_signature': 'BRsb11dk++405uaq5pRS+CMUzbo='}
Both looks good to me but the first one succeed and the second returns a 401 error, invalid signature.
In both cases, I get the token.key and token.secret as the result of :
OAuthHook.consumer_key = self.ckey
OAuthHook.consumer_secret = self.csecret
oauth_hook = OAuthHook()
client = requests.session(hooks={'pre_request': oauth_hook})
response = client.post('%soauth/request_token' % (self.url), {'oauth_callback': 'oob'})
# new oauth_hook with the request token
oauth_hook = OAuthHook(response[b'oauth_token'][0],response[b'oauth_token_secret'][0])
Them, I go to oauth/authorize?oauth_token=%s" % oauth_hook.token.key to get authorize the app and get a pincode. After that I can do the problematic request
...
response = client.post('%soauth/request_token' % (self.url), {'oauth_callback': 'oob'})
oauth_hook = OAuthHook(response[b'oauth_token'][0],response[b'oauth_token_secret'][0])
# get the pincode from %soauth/authorize?oauth_token=%s" % (self.url, oauth_hook.token.key)
oauth_hook.token.set_verifier(pincode)
client = requests.session(hooks={'pre_request': oauth_hook})
response = client.post("%soauth/access_token" % (self.url),
{'oauth_verifier': pincode})
The signature code from the auth.py file is
def sign(self, request, consumer, token):
"""Builds the base signature string."""
key, raw = self.signing_base(request, consumer, token)
hashed = hmac.new(key.encode(), raw.encode(), sha1)
# Calculate the digest base 64.
return binascii.b2a_base64(hashed.digest())[:-1]
Any idea why it doesn't work with the py3k code ?
Thank you
Found the answer ! There were two oauth_verifier in the POST request, leading to a wrong signature...
You may need to verify the Authorization header string in your request. Normally it would be of the format:
'Authorization' => 'OAuth
realm="",oauth_timestamp="1243392158",oauth_nonce="VsaPHb",oauth_consumer_key="xxxxxxxxxxxxxxxxxx",oauth_token="xxxxxx-xxxx-xxxxxxxxxxxxxx",oauth_version="1.0",oauth_signature_method="HMAC-SHA1",oauth_signature="xxxxxxxxxxxxxxxxxxxx"'
In the above header value, check that the "oauth_signature" is decoded properly. That is, it should not contain values like: %3D. You can use this tool to decode the string.
This has worked for me. Hope it helps someone.

Resources