I'm testing my Flask application using FlaskClient, in order to avoid to run a Flask server always when I'm testing my application.
I've created a 'sign_in' view that returns an 'Authorization' header with a encrypted token when the user logs successfully in my front-end.
This view works normally in a normal environment, it returns the 'Authorization' header correctly, however when I'm testing this view, inside the test environment, it does not return the 'Authorization' header. The view returns None in 'Authorization' header.
I've already tried some solutions on the internet, such as to add self.app.config['TESTING'] = True in my test case, but the terminal raises an error 'FlaskClient' object has no attribute 'config' that I've already tried to look for a solution, but without success.
I would like to know what may be happening.
Does anyone know any solution for this question?
I send my code below for analysis.
Thank you in advance.
view.py
#app.route("/sign_in", methods = ["POST"])
def sign_in():
...
username, password = ...
try:
encoded_jwt_token = auth_login(username, password)
except UserDoesNotExistException as error:
return str(error), error.status_code
resp = Response("Returned Token")
resp.headers['Authorization'] = encoded_jwt_token
return resp
test.py
class TestAPIAuthLogin(TestCase):
def setUp(self):
self.app = catalog_app.test_client()
# self.app.config['TESTING'] = True # config does not exist
def test_get_api_auth_login_user_test(self):
username = "test"
password = get_string_in_hash_sha512("test")
authorization = 'Basic ' + get_string_in_base64(username + ":" + password)
headers = {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json',
'Authorization': authorization
}
response = self.app.get('/sign_in', headers=headers)
# it returns None
authorization = response.headers.get("Authorization")
self.assertIsNotNone(authorization)
self.assertNotEqual(authorization, "")
I believe this may be to do with the way HTTP requests process headers, where they capitalise them and add HTTP_ as a prefix. Try changing your header to HTTP_AUTHORIZATION instead of just Authorization, since the test client will not be setting this properly.
I'm sorry guys for this silly question.
Now I've figure the answer out.
The problem was that I was trying to do a GET request in a view that is using a POST method.
I've just replaced the request from
response = self.app.get('/sign_in', headers=headers)
to
response = self.app.post('/sign_in', headers=headers)
and now it started to work.
I will let this question here in case of someone gets the same silly error.
Thank you so much.
If similar issue for DRF clients, You can use,
client = APIClient()
client.credentials(HTTP_AUTHORIZATION='Token {token}'.format(token=token))
Ref: https://www.django-rest-framework.org/api-guide/testing/#credentialskwargs
Related
I am using pandas and requests to create a post request, and the one I am creating sent me back a status code 200 instead of a 201.
In this post, I send a JSON from a dataframe. This part seems to be good.
I don't know if the header is good or not, I changed a lot of things in it, without success.
This problem doesn't show any error and the server affected by the request doesn't give any sign too.
The first request give me the access token and work well.
def post_json(nbr_requests):
auth_json = {'grant_type': 'password', 'client_id': 'hidden','client_secret':'hidden','username':'hidden','password':'hidden'}
auth_response = requests.post('http://hidden:8080/lot/of/stufs/token',data=auth_json)
token = auth_response.json()["access_token"]
api_call_headers = {'content-type':'application/json', 'accept':'application/json','authorization': 'Bearer' + token}
url_to_go = "http://localhost:8080/hidden/link"
for i in range(nbr_requests):
api_call_response = requests.post(url_to_go, headers=api_call_headers, json=json_array_to_send[i],data={"key": "value"})
print (api_call_response.status_code)
I know the question wasn't clear, but if someone got the same problem, you should add a space between "Bearer" and the token in the header.
In my example above you should do something like this :
api_call_headers = {'content-type':'application/json', 'accept':'application/json','authorization': 'Bearer ' + token}
I'm fairly new to using web APIs and pulling data and i'm also pretty new with python. My goal is to make a stat-tracker app but I keep getting a 401 when I try and pull the data.
I've printed out the entire url just to make sure I didn't get it wrong. I copied and pasted the API key exactly so that shouldn't be a problem
api_token = 'api key in python file'
api_url_base = 'https://public-api.tracker.gg/v2/apex/standard/'
headers = {'Content-Type' : 'application/json',
'Authorization' : 'Bearer {}'.format(api_token)}
def get_player_profile():
api_url = '{}profile/psn/Daltoosh'.format(api_url_base)
response = requests.get(api_url, headers=headers)
if response.status_code == 200:
return json.loads(response.content.decode('utf-8'))
else:
return response.status_code, api_url
print(get_player_profile())
#player_profile = get_player_profile()
#if player_profile is not None:
# print("Career Stats:")
# for k, v in player_profile['profile/psn/Daltoosh'].items():
# print('{0}:{1}.format(k, v)')
#else:
# print('[!] Data Request Failed [!]')
I expected a status code of 200 but there seems to be a problem authenticating.
I'm not too well versed in the web API that you are using, but I think you might be using the API token incorrectly. I don't think that specific API requires a Bearer token, but instead a separate header called TRN-Api-Key.
So maybe write something like this:
headers = {'Content-Type' : 'application/json', 'TRN-Api-Key' : api_token}
If you look here, you should be able to read up on how to set up authentication.
I can't create new repositoies in bitbucket cloud with code below.
I'm able to delete repositiries (with change form 'post' to 'delete' requests method). When I'm using code below I've got http 400 which means according to api docs - If the input document was invalid, or if the caller lacks the privilege to create repositories under the targeted account.
import requests
username = 'user#mail.com'
password = 'password'
headers = {"Content-Type": 'application/json'}
auth = (username, password)
bb_base_url = f"https://api.bitbucket.org/2.0/repositories/username/reponame"
res = requests.post(bb_base_url, headers=headers, auth=auth)
print(res)
So would like to ask for help to refactor code in way I will be able to do two things
so I am hosting an image using flask and then I want to do a post request to an API using the url all in the same code:
#app.route('/host')
def host():
return send_from_directory("C:/images", "image1.png")
#app.route('/post')
def post():
response = requests.post(url, data={'input':'<url for host>', headers=headers)
return jsonify(response.json())
I believe as both these view functions are in the same python file, post() gets blocked.
Is there a workaround this problem ?
PS: if I host images on a different machine, it works, but that's not what I desire.
Thanks!
I think there are some problems with your code.
First, I don't believe there is an #app.post() decorator in Flask. My guess is that you were trying to specify that that route should be POSTed to by your users. The way to do that would be #app.route('/post', methods=['POST']).
Next, it seems like you want the /post endpoint to send a POST request to a user-specified(?) URL when the user sends an HTTP request to this endpoint. The way you would do that for a user-specified / user-POSTed URL is something like this (I haven't run this code to test it):
#app.route('/send_post_request', methods=['POST'])
def send_post_request():
user_posted_data = json.loads(request.data)
user_specified_url = user_posted_data['url']
dict_to_post= { 'input': url_for('hosts') }
headers = {} # Fill these in
response = requests.post(user_specified_url , json=dict_to_post, headers=headers)
return jsonify(response.json())
If the URL to send the POST request to is known by the server, you could have your user simply send a GET request:
#app.route('/send_post_request', methods=['GET'])
def send_post_request():
dict_to_post = { 'input': url_for('hosts') }
headers = {} # Fill these in
server_specified_url = '' # Fill this in
response = requests.post(server_specified_url, json=dict_to_post, headers=headers)
return jsonify(response.json())
Quick question: I'm trying to use the Discord API to make a backup of all the messages on a server (or a guild, if you use the official term).
So I implemented OAuth without any problems, I have my access token and I can query some endpoints (I tried /users/#me, /users/#me/guilds). Though, most of them don't work. For example, if I query /users/#me/channels (which is supposed to be the DMs) I get a 401 Unauthorized response from the API. It's the same if I gather a guild id from /users/#me/guilds and then try to list the channels in it with /guilds/guild.id/channels.
The really weird thing is that I do have all the scopes required (I think so, I didn't take the RPC ones since I don't think it's required for what I want to do) and I can't figure it out myself... What is also weird is that on the OAuth authorization screen, I have those two things:
It kind of counterdicts itself... :(
Do you have any ideas you'd like to share ?
Thanks!
Note: I'm using Python but I don't think it's related here, since some endpoints do work with the headers and tokens I have...
Here is my "authentication code":
baseUrl = "https://discordapp.com/api"
def authorize():
scopes = [
"guilds",
"email",
"identify",
"messages.read",
"guilds.join",
"gdm.join",
"connections"
]
urlAuthorize = "{}/oauth2/authorize?client_id={}&scope={}&response_type=code".format(baseUrl, clientid, ('+'.join(scopes)))
pyperclip.copy(urlAuthorize)
code = input("Code: ")
return code
def getAccessToken(code):
url = "{}/oauth2/token".format(baseUrl)
params = {
"client_id" : clientid,
"client_secret" : clientsecret,
"redirect_uri" : "http://localhost",
"grant_type":"authorization_code",
"code" : code,
}
req = requests.post(url, params = params)
return json.loads(req.text)
And the code related to an API request:
def getHeaders():
return {
"Authorization" : "{} {}".format("Bearer", config["accessToken"]),
# "user-agent" : "DiscordBackup/0.0.1"
}
def getRequest(endpoint, asJson = True, additional = None):
url = "{}/{}".format(baseUrl, endpoint)
req = requests.get(url, headers = getHeaders())
print()
print(getHeaders())
print(url)
print(req.text)
if asJson:
return json.loads(req.text)
else:
return req.text
def getMe(): # this works
endpoint = "users/#me"
return getRequest(endpoint)
def getMyDMs(): # this gives me a code 401 Unauthorized
endpoint = "/users/#me/channels"
return getRequest(endpoint)
I came across this post when encountering this issue, and to put it bluntly, there's no way to resolve it.
The messages.read permission is for a local RPC server; https://discordapp.com/developers/docs/topics/oauth2#shared-resources-oauth2-scopes
However, local RPC servers are in private beta and you must sign up/get accepted to use this.
I wanted to create a DM exporter, but that doesn't look likely now.