POST data with urllib2 gives 400 - python

In the following code, when the following data(template_data) is passed in postman app on chrome then there is a response but the same data when posted with urllib2 gives an error, The only difference i notice is the required field i.e, false should not be given in quotes even in postman script else there is no response but the same fails in urllib2
If 'false' is given quotes in template_data even then the result is 400
Edit: In postman false should not be given in quotes if gives gives an error, so not sure how to send this paramater
import urllib
import urllib2
def get_url_data(url, request_method, content_type, data=None,
headers={}):
method = request_method
handler = urllib2.HTTPHandler(debuglevel=1)
opener = urllib2.build_opener(handler)
if data is not None:
data = urllib.urlencode(data)
request = urllib2.Request(url, data=data,headers=headers)
request.add_header("Content-Type", content_type)
request.get_method = lambda: method
try:
connection = opener.open(request)
except urllib2.HTTPError,e:
connection = e
print connection.code
if connection.code == 200:
resp = connection.read()
return resp
return None
form_template_url="https://example.com"
auth='sometokenid'
template_header_param = {'Authorization':auth}
template_data = {
"templateName": "somename",
"category": "Handbook",
"formTemplateDef": [{
"id": "0",
"component": "textInput",
"editable": "true",
"index": "0",
"label": "Handbook",
"description": "",
"placeholder": "TextInput",
"options": [],
"required": 'false'
}]
}
template_response = get_url_data(form_template_url,
'POST', 'application/json',
template_data, template_header_param)

Remove
data = urllib.urlencode(data)
and use
urllib2.urlopen(req, json.dumps(data))
This should work.

Related

Unable to filter, paginate, or add any data to Notion API query from python code

I've been trying to query the Notion API using Python, and as I have more than 100 results, I need to either filter them down or be able to paginate. I tried different variants of the following code to no avail:
headersNotion = {
"Authorization": "Bearer " + notionToken,
"Content-Type": "application/json",
"Notion-Version": "2021-05-13"
}
data = {
"start_cursor" : nextCursor
}
readUrl = f"https://api.notion.com/v1/databases/{databaseId}/query"
res = requests.request("POST", readUrl, data=data, headers=headers)
I've also tried with data = { "filter": {"cover" : "is_empty"} } or even with an idiotic or empty filter, but as soon as I add any sort of data to the request, I get a 400 error:
{"object": "error", "status": 400, "code": "invalid_json", "message": "Error parsing JSON body."}
Would anyone have any idea what I might be doing wrong?
look here headersNotion schould be headers.
https://developers.notion.com/reference/post-database-query
Just as example.
payload = {
'filter': {
'and': [
{
'property': 'aktualisiert am',
'date': {
'after': str(age)
}
},
{
'property': 'aktiv',
'text': {
'equals': 'yes'
}
}
]
}
}
headers = {
"Accept": "application/json",
"Authorization": "Bearer " + token,
"Content-Type": "application/json",
"Notion-Version": "2021-08-16"
}
def readDatabase(databaseId, headers, payload):
readUrl = f"https://api.notion.com/v1/databases/{databaseId}/query"
res = requests.request("POST", readUrl, json=payload, headers=headers)
datadb = res.json()
print(res.text) #for Debug
# Errors Returns a 404 HTTP response if the database doesn't exist, or if the integration doesn't have access to the database.
# Returns a 400 or a 429 HTTP response if the request exceeds the request limits.
# Returns 200 HTTP responce if OK
#print ('')
print ('')
if res.status_code == 200:
print('200 Success!') # Yes everything OK!
elif res.status_code == 404:
print('404 Not Found.')
#sendmail
subject = " Fehler!! 404 Database Not Found"
send_email(user, password, recipient, subject, body)
return
elif res.status_code == 429:
print(' Fehler !! 429 request exceeds the request limits.')
#sendmail
subject = " Fehler !! 429 request exceeds the request limits."
send_email(user, password, recipient, subject, body)
return
elif res.status_code == 400:
print('400 request exceeds the request limits.')
#sendmail
subject = " Fehler !! 400 request exceeds the request limits. "
send_email(user, password, recipient, subject, body)
return
# print(res.text)
# write csv File
with open('./dbmain.json', 'w', encoding='utf8') as f:
json.dump(datadb, f, ensure_ascii=False)

Downloading custom Nessus scan report using Nessus API

I have python code that successfully downloads a Nessus scan report in csv format, but I need to add some additional fields to the downloaded report. I include parameters in the request payload to include some fields, but the scan that is downloaded does not include those fields.
I've tried changing the value of the reportedContents params to actual Boolean types with the True keyword.
Also, I changed the format to pdf and it exports a PDF file that is just a title page and a page with a blank table of contents.
The downloaded csv file has data in it, but only includes the default headers (i.e.):
Plugin ID,CVE,CVSS v2.0 Base Score,Risk,Host,Protocol,Port,Name,Synopsis,Description,Solution,See Also,Plugin Output
The raw output of the POST request looks like:
POST https://localhost:8834/scans/<scan_id>/export
X-ApiKeys: accessKey=accessKey;secretKey=secretKey
Content-Type: application/x-www-form-urlencoded
Content-Length: 122
format=csv&reportContents.vulnerabilitySections.exploitable_with=true&reportContents.vulnerabilitySections.references=true
def download_scan(scan_num):
# Post an export request
headers = {
'X-ApiKeys': 'accessKey=accessKey;secretKey=secretKey',
'Content-Type': 'application/x-www-form-urlencoded'
}
data = {
'format': 'csv',
'reportContents.vulnerabilitySections.exploitable_with': 'true',
'reportContents.vulnerabilitySections.references': 'true'
}
res = requests.post(url + '/scans/{id_num}/export'.format(id_num = scan_num), data=data, verify=False, headers=headers)
if res.status_code == 200:
export = json.loads(res.text)
file_id = export.get('file')
# Continually check the scan status until the status is ready
while True:
# Check file status
res = requests.get(url + '/scans/{id_num}/export/{file_num}/status'.format(id_num = scan_num, file_num = file_id), verify=False, headers=headers)
if res.status_code == 200:
status = json.loads(res.text)['status']
if status == 'ready':
break
# Download the scan
res = requests.get(url + '/scans/{scan_num}/export/{file_num}/download'.format(scan_num = scan_num, file_num = file_id), verify=False, headers=headers)
# If the scan is successfully downloaded, get the attachment file
if res.status_code == 200:
attachment = res.content
print("Scan downloaded!!!")
else:
raise Exception("Download request failed with status code: " + str(res))
return attachment
def main():
# Download the scan based on the scan_id. I have a helper function that returns the id that I am omitting here
try:
scan = download_scan(scan_id)
except Exception as e:
print(e)
quit()
with open("scan.csv", "wb") as f:
f.write(scan)
f.close()
if __name__ == "__main__":
main()
I'm having the exact same issue but with PowerShell. Neither my additional columns nor filters appear to be working. Was wondering if you'd had any joy getting this to work?
If I change the scan_id I get the correct different results, which suggests it is receiving the JSON but ignoring the columns and filters.
My JSON is as follows...
{
"scan_id": 3416,
"format": "csv",
"reportContents.vulnerabilitySections.cvss3_base_score": true,
"filters": {
"filter.0.quality": "gt",
"filter.0.filter": "cvss2_base_score",
"filter.0.value": "6.9",
"filter.1.quality": "neq",
"filter.1.filter": "cvss2_base_score",
"filter.1.value": ""
}
}
I managed to fix it, my problem was that I was using Python's requests module and it's data={} keyword, which defaults to header content-type: application-x-www-form-urlencoded, it generates reports with strictly 13 fields regardless of your payload.
To make it actually consider your payload, use the header "content-type": "application/json", in your code implicitly and json={} in your payload instead of data={}.
WILL NOT WORK:
requests.post(
nessus_url + f"/scans/{scan_id}/export",
data={
"format": "csv",
"template_id": "",
"reportContents": {
"csvColumns": {
"id": True,
"cve": True,
"cvss": True,
**other_columns,
}
}
},
verify=False,
headers={
"X-ApiKeys": f"accessKey={credentials['access_key']}; secretKey={credentials['secret_key']}",
},
)
WILL WORK:
requests.post(
nessus_url + f"/scans/{scan_id}/export",
json={
"format": "csv",
"template_id": "",
"reportContents": {
"csvColumns": {
"id": True,
"cve": True,
"cvss": True,
**other_columns
}
}
},
verify=False,
headers={
"X-ApiKeys": f"accessKey={credentials['access_key']}; secretKey={credentials['secret_key']}",
"content-type": "application/json",
},
)

PayPal Tracking showing INVALID_TRACKING_CODE

Looks like I'm doing just about everything correct but I keep receiving this error....
Response text error:
response .text {"name":"INVALID_TRACKING_NUMBER","message":"The requested resource ID was not found","debug_id":"12345","details":[{"field":"tracker_id","value":"1234-567890","location":"path","issue":"INVALID_TRACKING_INFO"}],"links":[]}
Response status: <Response [404]>
I'm using a real transaction and a real tracking number.
I'm doing this through python and this is my code:
def paypal_oauth():
url = 'https://api-m.paypal.com/v1/oauth2/token'
headers = {
"Content-Type": "application/json",
"Accept-Language": "en_US",
}
auth = "1234-1234","0987"
data = {"grant_type":"client_credentials"}
response = requests.post(url, headers=headers, data=data, auth=(auth))
return response
def paypal_tracking(paypal_transaction_token, tracking_number, status, carrier):
try:
_paypal_oauth = paypal_oauth()
_paypal_oauth_response = _paypal_oauth.json()
except Exception as e:
print(e)
pass
access_token = _paypal_oauth_response['access_token']
url = 'https://api-m.paypal.com/v1/shipping/trackers/%s-%s/' % (paypal_transaction_token, tracking_number)
# https://api-m.paypal.com/v1/shipping/trackers/1234-567890/
carrier = carrier_code(carrier)
# This grabs carrier from a method and gets back: 'DHL'
headers = {
'Content-Type' : 'application/json',
'Authorization' : 'Bearer %s' % access_token,
}
# {'Content-Type': 'application/json', 'Authorization': 'Bearer 1234'}
data = {
"transaction_id":"%s" % paypal_transaction_token,
"tracking_number":"%s" % tracking_number,
"status": "%s" % status,
"carrier": "%s" % carrier
}
# {'transaction_id': '1234', 'tracking_number': '567890', 'status': 'SHIPPED', 'carrier': 'DHL'}
response = requests.put(url, headers=headers, data=json.dumps(data))
return HttpResponse(status=200)
Anyone with experience in paypal or using API's see my issue?
To add a tracking number (not update), use an HTTP POST request, as documented.
The URL to POST to is https://api-m.sandbox.paypal.com/v1/shipping/trackers-batch , with no additional URL parameters.
The body format is
{
"trackers": [
{
"transaction_id": "8MC585209K746392H",
"tracking_number": "443844607820",
"status": "SHIPPED",
"carrier": "FEDEX"
},
{
"transaction_id": "53Y56775AE587553X",
"tracking_number": "443844607821",
"status": "SHIPPED",
"carrier": "FEDEX"
}
]
}
Note that trackers is an array of JSON object(s).

SendBird Error 400403 Invalid value: JSON body

I am trying to create user using send bird API
I am using python to make the API call, but getting error code 400403,
If I try from postman it works, not sure where I'm going wrong in the code
Following is my code -
import json
import requests
url = ‘https://api-someappidhere.sendbird.com/v3/users’
headers = {
'Content-Type' : 'application/json; charset=utf8',
'Api-Token' : 'secondaryApiToken'
}
data = {
'user_id' : 'someuserId',
'nickname' : 'somenickname',
'profile_url' : ''
}
try:
apiResponse = requests.post(url, headers=headers, data=data)
apiResponse = apiResponse.json()
return response
except Exception as error:
print(error)
I am getting the following response -
{
"hasError": false,
"result": {
"message": "Invalid value: \"JSON body.\".",
"code": 400403,
"error": true
}
}
References -
https://docs.sendbird.com/platform/quick_start
https://docs.sendbird.com/platform/error_codes
You should use json.dumps().
import json
import requests
url = ‘https://api-someappidhere.sendbird.com/v3/users’
headers = {
'Content-Type' : 'application/json; charset=utf8',
'Api-Token' : 'secondaryApiToken'
}
data = {
'user_id' : 'someuserId',
'nickname' : 'somenickname',
'profile_url' : ''
}
jsonData = json.dumps(data)
try:
apiResponse = requests.post(url, headers=headers, data=jsonData)
apiResponse = apiResponse.json()
return response
except Exception as error:
print(error)

How to use python api get request

I use the below function to get data from the web , but failed. I wonder whether urllib.quote use incorrect
i have used urllib.urlencode(xx) but it show not a valid non-string sequence or mapping object
and my request data is:
[{"Keys": "SV_cY1tKhYiocNluHb", "Details": [{"id2": "PK_2gl9xtYKX7TJi29"}], "language": "EN", "id": "535985"}]
Anyone can help. Thanks a lot !!!
###This Funcation call API Post Data
def CallApi(apilink, indata):
token = gettoken()
data = json.dumps(indata, ensure_ascii=False)
print(data)
headers = {'content-type': 'application/json', 'Accept': 'application/json', 'Authorization': 'Bearer %s' % (token)}
proxy = urllib2.ProxyHandler({})
opener = urllib2.build_opener(proxy)
urllib2.install_opener(opener)
DataForGet=urllib.quote(data)
NewUrl= apilink + "?" + DataForGet
request = urllib2.Request(NewUrl, headers=headers)
response = urllib2.urlopen(request, timeout=300)
message = response.read()
print(message)
Error:
the err message below: File "/opt/freeware/lib/python2.7/urllib2.py", line 1198, in do_open raise URLError(err)
You could see the comment of urlencode
Encode a dict or sequence of two-element tuples into a URL query string
So you could choose removing the outer []
{"Keys": "SV_cY1tKhYiocNluHb", "Details": [{"id2": "PK_2gl9xtYKX7TJi29"}], "language": "EN", "id": "535985"}
Or use a two-element tuple
(('Keys', 'SV_cY1tKhYiocNluHb'), ('Details', [{...}]...)
Demo
>>> import urllib
>>> s = {"Keys": "SV_cY1tKhYiocNluHb", "Details": [{"id2": "PK_2gl9xtYKX7TJi29"}], "language": "EN", "id": "535985"}
>>> urllib.urlencode(s)
'Keys=SV_cY1tKhYiocNluHb&Details=%5B%7B%27id2%27%3A+%27PK_2gl9xtYKX7TJi29%27%7D%5D&language=EN&id=535985'
>>>

Categories