Any idea how to open bytes object in new tab? - python

I am requesting an api to grant access to communicate with application for integration. While requesting I am getting response which is in bytes object that is why i am unable to open it in new tab because I want login to access my application.
header = {
'Content-Type': 'application/x-www-form-urlencoded'
}
response = requests.get(
'https://api.getbase.com/oauth2/authorize',
data='client_id=' + self.client_id + '&response_type=code&redirect_uri='
+ self.redirect_uri, headers=header).content
webbrowser.open_new_tab(response)

just fixing your stated problem, you need to decode the bytes into a string or just use the text attribute.
that said, your code seems unnecessarily fragile and might be nicer as:
response = requests.post('https://api.getbase.com/oauth2/authorize', data={
'client_id': self.client_id,
'response_type': 'code',
'redirect_uri': self.redirect_uri
})
# make sure we throw an exception on failure
response.raise_for_status()
webbrowser.open_new_tab(response.text)
that way you can let requests deal with encoding/escaping the parameters appropriately. the default encoding/data type with an HTTP POST request is application/x-www-form-urlencoded as you need. GET requests don't send a body, so I'm not sure how your previous code was working

Related

How to print text of POST request without making request

If I make the request
api-key = 'asdfklhsdfkjahsdlgkjahlkdjahfsa'
url = 'https://www.website.com'
headers = {'api-key': api-key,
'Content-Type': 'application/json'}
request_data = {'foo': 'bar', 'egg': 'spam'}
result = requests.post(url, headers=headers, data=request_data)
The server is contacted. Suppose that instead I want to do something like
request_string = requests.foobar(url, headers=headers, data=request_data)
import os
os.system('curl ' + request_string)
So that I can look to see what the request is doing without bothering the server (possibly to the point that I could c&p it into curl), what would foobar be? Or in general, what is a way to inspect the contents of the request without making it?
Here's another post that implies that you can use Request().prepare() to observe the request without actually sending the request.
Furthermore the official documentation reads "In some cases you may wish to do some extra work to the body or headers (or anything else really) before sending a request. The simple recipe for this is the following" and then it illustrates Request.prepare()

Requests package and API documentation

I'm having trouble understanding where to add parameters defined by API documentation. Take BeeBole's documentation for example, which specifies that to get an absence by ID, the following request is required:
{
"service": "absence.get",
"id": "absence_id"
}
They provide only one URL in the documentation:
BeeBole is accepting HTTP POST resquests in a json-doc format to the following URL:
https://beebole-apps.com/api/v2
How would this be implemented in the context of Python requests? The following code I've tried returns 404:
import requests
payload = {
"service": "absence.get",
"id": "absence_id"
}
auth = {
"username": "API_token",
"password": "x"
}
url = "https://beebole-apps.com/api/v2"
req = requests.get(url, params=payload, auth=auth).json()
BeeBole is accepting HTTP POST resquests in a json-doc format to the following URL: https://beebole-apps.com/api/v2
The JSON document format here is the part you missed; you need to pass the information as a JSON encoded body of the request. The params argument you used only sets the URL query string (the ?... part in a URL).
Use
import requests
payload = {
"service": "absence.get",
"id": "absence_id"
}
auth = ("API_token", "x")
url = "https://beebole-apps.com/api/v2"
req = requests.get(url, json=payload, auth=auth).json()
The json= part ensures that the payload dictionary is encoded to JSON and sent as a POST body. This also sets the Content-Type header of the request.
I've also updated the API authentication, all that the auth keyword needs here is a tuple of the username and password. See the Basic Authentication section.
You may want to wait with calling .json() on the response; check if the response was successful first:
req = requests.get(url, json=payload, auth=auth)
if not req.ok:
print('Request not OK, status:', req.status_code, req.reason)
if req.content:
print(req.text)
else:
data = req.json()
if data['status'] == 'error':
print('Request error:', data['message'])
This uses the documented error responses.
From the site documentation it would appear that this particular vendor has chosen an unusual API. Most people use different endpoints to implement different operations, but BeeBole appears to implement everything off the one endpoint, and then selects the operation by examining the "service" key in the request data.
Try
response - request.post('https://beebole-apps.com/api/v2',
json={"service": "company.list"},
headers={"authorization": TOKEN)
From the documentation I can't guarantee that will put the request in the right format, but at least if it doesn't work it should give you some clue as to how to proceed. Establishing the correct value of TOKEN is described under "Authorization" in the BeeBole documentation.
It's an unusual way to offer an API, but it seems workable.

Python POST request does not take form data with no files

Before downvoting/marking as duplicate, please note:
I have already tried out this, this, this, this,this, this - basically almost all the methods I could find pointed out by the Requests documentation but do not seem to find any solution.
Problem:
I want to make a POST request with a set of headers and form data.
There are no files to be uploaded. As per the request body in Postman, we set the parameters by selecting 'form-data' under the 'Body' section for the request.
Here is the code I have:
headers = {'authorization': token_string,
'content-type':'multipart/form-data; boundary=----WebKitFormBoundaryxxxxxXXXXX12345'} # I get 'unsupported application/x-www-form-url-encoded' error if I remove this line
body = {
'foo1':'bar1',
'foo2':'bar2',
#... and other form data, NO FILE UPLOADED
}
#I have also tried the below approach
payload = dict()
payload['foo1']='bar1'
payload['foo2']='bar2'
page = ''
page = requests.post(url, proxies=proxies, headers=headers,
json=body, files=json.dump(body)) # also tried data=body,data=payload,files={} when giving data values
Error
{"errorCode":404,"message":"Required String parameter 'foo1' is not
present"}
EDIT:
Adding a trace of the network console. I am defining it in the same way in the payload as mentioned on the request payload.
There isn't any gui at all? You could get the network data from chrome, although:
Try this:
headers = {'authorization': token_string}
Probably there is more authorization? Or smthng else?
You shouldn't add Content-Type as requests will handle it for you.
Important, you could see the content type as WebKitFormBoundary, so for the payload you must take, the data from the "name" variable.
Example:
(I know you won't upload any file, it just an example) -
So in this case, for my payload would look like this: payload = {'photo':'myphoto'} (yea there would be an open file etc etc, but I try to keep it simple)
So your payload would be this-> (So always use name from the WebKit)
payload = {'foo1':'foo1data',
'foo2':'foo2data'}
session.post(url,data = payload, proxies etc...)
Important! As I can see you use the method from requests library. Firstly you always should create a session like this
session = requests.session() -> it will handle cookies, headers, etc, and won't open a new session, or plain requests with every requests.get/post.

Django calls with Json. Common_Unsupported_Media_Type

I'm trying to make a RESTful api call in python/django with requests.post
I can get requests.get(url=url, auth=auth) to work. Similar call in the same api family for this company
I'm trying to do:
data = {'start': 13388, 'end': 133885, 'name': 'marcus0.5'}
r = requests.post(url=url, auth=auth, headers={'Accept': 'application/json'}, data=data)
and I get the following error:
>>> r.text
u'{"status":"error","errorCode":"COMMON_UNSUPPORTED_MEDIA_TYPE","incidentId":"czEtbXNyZXBvcnRzMDQuc3RhZ2V4dHJhbmV0LmFrYW1haS5jb20jMTM3NTgxMzc3MTk4NQ==","errorMessage":"The server is refusing to service the request because the entity of the request is in a format not supported by the requested resource for the requested method.. Content type \'application/x-www-form-urlencoded;charset=UTF-8\' not supported."}'
I think it has something to do with the json, but I'm not sure what and I'm not sure how to fix it. Any ideas?
Extra info [not sure if it applies]:
I imported
import requests, django
I know the the auth is correct and I tested it with the get method
You want to set the Content-Type parameter of your request to 'application/json', not the Accept parameter.
Taken from w3.org:
The Accept request-header field can be used to specify certain media types which are acceptable for the response.
Try this instead:
import json
data = {'start': 13388, 'end': 133885, 'name': 'marcus0.5'}
r = requests.post(url=url, auth=auth, data=json.dumps(data),
headers={'content-type': 'application/json'})
EDIT:
There is a little bit of confusion (for me as well) about when to send data as a dict or a json encoded string (ie. the result of json.dumps). There is an excellent post here that explains the problem. For a brief summary send a dict when the API requires form-encoded data, and a json encoded string when it requires json-encoded data.

Grab some ofx data with python

I was trying to use http://www.jongsma.org/gc/scripts/ofx-ba.py to grab my bank account information from wachovia. Having no luck, I decided that I would just try to manually construct some request data using this example
So, I have this file that I want to use as the request data. Let's call it req.ofxsgml:
FXHEADER:100
DATA:OFXSGML
VERSION:102
SECURITY:NONE
ENCODING:USASCII
CHARSET:1252
COMPRESSION:NONE
OLDFILEUID:NONE
NEWFILEUID:NONE
<OFX>
<SIGNONMSGSRQV1>
<SONRQ>
<DTCLIENT>20071015021529.000[-8:PST]
<USERID>TheNameIuseForOnlineBanking
<USERPASS>MySecretPassword
<LANGUAGE>ENG
<FI>
<ORG>Wachovia
<FID>4309
</FI>
<APPID>Money
<APPVER>1700
</SONRQ>
</SIGNONMSGSRQV1>
<BANKMSGSRQV1>
<STMTTRNRQ>
<TRNUID>438BD6F4-2106-4C88-8DE5-7625915A2FC0
<STMTRQ>
<BANKACCTFROM>
<BANKID>061000227
<ACCTID>101555555555
<ACCTTYPE>CHECKING
</BANKACCTFROM>
<INCTRAN>
<INCLUDE>Y
</INCTRAN>
</STMTRQ>
</STMTTRNRQ>
</BANKMSGSRQV1>
</OFX>
Then, in python, I try:
>>> import urllib2
>>> query = open('req.ofxsgml').read()
>>> request = urllib2.Request('https://pfmpw.wachovia.com/cgi-forte/fortecgi?servicename=ofx&pagename=PFM',
query,
{ "Content-type": "application/x-ofx",
"Accept": "*/*, application/x-ofx"
})
>>> f = urllib2.urlopen(request)
This command gives me a 500 and this traceback. I wonder what is wrong with my request.
Visiting the url with no data and no concern for headers,
>>> f = urllib2.urlopen('https://pfmpw.wachovia.com/cgi-forte/fortecgi?servicename=ofx&pagename=PFM')
yields the same thing as visiting that url directly,
HTTPError: HTTP Error 403: <BODY><H1>Request not allowed</H1></BODY>.
This is pretty obvious but just an observation. Everything on the subject seems to be pretty outdated. Hoping to write a simple python ofx module to open source. Maybe there is already something developed that I have not managed to find?
EDIT -
If I make a flat mapping of the above information:
d = {'ACCTID': '10555555',
'ACCTTYPE': 'CHECKING',
'APPID': 'Money',
'APPVER': '1700',
'BANKID': '061000227',
'DTCLIENT': '20071015021529.000[-8:PST]',
'FID': '4309',
'INCLUDE': 'Y',
'LANGUAGE': 'ENG',
'ORG': 'Wachovia',
'TRNUID': 'I18BD6F4-2006-4C88-8DE5-7625915A2FC0',
'USERID': 'm48m40',
'USERPASS': '12397'}
and then urlencode it and make the request with that as the data
query=urllib.urlencode(d)
request = urllib2.Request('https://pfmpw.wachovia.com/cgi-forte/fortecgi?servicename=ofx&pagename=PFM',
query,
{ "Content-type": "application/x-ofx",
"Accept": "*/*, application/x-ofx"
})
f = urllib2.urlopen(request)
HTTP Error 403: <BODY><H1>Request not allowed</H1></BODY>
The problem was that you were previously passing in the data from your file directly as the data parameter to the Request. The file you were reading in contains both the headers and the data that you should be sending. You needed to supply the headers and the data separately as you have now done.
HTTP error 403 means the request was correct but the server is refusing to respond to it. Have you already signed up and arranged permission to use the web service you are trying to access? If so is there some authentication that you need to do before making the request?
could just be authentication? (or lack therof?)

Categories