Python requests inside a Django view hangs out and needs timeout - python

I'm seeking help for this rather strange behaviour.
I have a Django view that gets called after a button click in a Django template
#require_http_methods(['GET', 'POST'])
#login_required
#transaction.atomic
def create_key(request, slug):
#some unrelated code
try:
r = requests.post(
some_url,
data={
#some_data
},
auth=(client_id, client_secret),
timeout=(req_to, res_to)
)
if r.status_code == 200:
return True
else:
return False
except ReadTimeout as to:
# handle exception
return True
except Exception as e:
# handle exception
return False
#some unrelated code
that basically calls an API endpoint to create a key.
Now the request with Postman works fine, taking out that python snippet and running it alone also works, but when put inside this Django view it hangs until reaches response timeout.
Does anybody has any idea or pointer on where the problem might be?
Thank you in advance!
EDIT: i've found similar problems but these while they share with me the same structure, the problem was somewhere else
Why Python requests library failing to get response?
LiveServerTestCase hangs at python-requests post call in django view

Related

Django Test Client client.post() sends GET request in my Testcase

How can I submit a POST request with Django test Client? I just want to test the login function of my application. It's strange that I put
response = self.client.post(reverse('rbac:login'), data=data) in my testcase, and I want to validate it so I print response.status_code.Actually it should return 302 coz it should turn to another page. but it return 200. This situation happens when I use "python manage.py test testmodel" to test. However, if I use "python manage.py shell" to make an InteractiveConsole and write exactly the same code, it return 302 at last.
I have nearly tried all the methods provided from stack overflow, e.g. change the url, offer the content-type when I post....but these are meaningless.
from django.test import TestCase
from django.test.utils import setup_test_environment,teardown_test_environment
from django.test import Client
from django.urls import reverse
import django
from rbac.models import RbacUser, RbacRole
from system_module.models import Redeploy
from urllib import urlencode
class CreateUser(TestCase):
#classmethod
def setUp(self):
self.client = Client()
def test_create_user(self):
data = {"Username": "admin_xy", "Password": "aaa"}
response = self.client.post(reverse('rbac:login'), data=data)
print response
and it shows me 200.....
However, in interactive console:
>>> response = client.post(reverse('rbac:login'), data=data)
>>> print response.status_code
302
it shows the right result.
I want to know how to cope with this annoying problem. Thx
I expect when I use test file to test my test case, it works fine....like show 302 code.
Before sending the POST or GET request by using Client, first you need to create the user make the user active and give necessary permissions and login through client and then send the post request.
Ex: self.client.login(username='username', 'password'='password)
It's been long time that this question is here, I hope you found the answer, but for other people I'll suggest to add this to this code to be redirected:
response = self.client.post(reverse('rbac:login'), data=data, follow=True)
The follow=True will follow the redirect .

Stripe API; {'error': 'invalid_grant', 'error_description': 'This authorization code has already been used

I'm using Stripe API and I'm trying to save the connect account keys in db. But I cannot save them successfully and a weird thing is happening.
My code is here
resp = stripe_connect_service.get_raw_access_token(method='POST', data=data)
connect_account_info = json.loads(resp.text)
connect_public_key = connect_account_info['stripe_publishable_key']
connect_access_token = connect_account_info['access_token']
connect_user_id = connect_account_info['stripe_user_id']
connect_refresh_token = connect_account_info['refresh_token']
print(connect_public_key)
print(connect_access_token)
print(connect_user_id)
print(connect_refresh_token)
form = Form()
if form.validate_on_submit():
data = Data(connect_public_key=connect_public_key, connect_access_token=connect_access_token, connect_user_id=connect_user_id, connect_refresh_token=connect_refresh_token)
db.session.add(data)
db.session.commit()
So after getting the token and finished submitting the form on the page rediercted from Stripe Connect page, I will save the data. print actually shows the connect account keys, but after submitting the form, the error says
connect_public_key = connect_account_info['stripe_publishable_key']
KeyError: 'stripe_publishable_key'
even though print does work.
And when I run debugger, the error says like this
{'error': 'invalid_grant', 'error_description': 'This authorization code has already been used.
How can I fix this error?
This error usually happens when your code incorrectly re-uses the authorization code (ac_XXXX) that you get in the URL.
This is often caused by refreshing the browser/page you're on after the redirect. Your code will fetch the code from the URL and use it to exchange it on the /oauth/token endpoint but if you do it twice it causes the connection to be revoked for security reasons.
In my case it was my server that retried on failure that eventually leads to this error response.
So in my case the problem was that my server's function crashed in a different place, after getting the token from the code.
And after the function crashed, since the server was setup for retry, it called the endpoint once again with the same params and in the second attempt the code was already used indeed, hence the error.
Maybe it can help someone too.

how to redirect to a external 404 page python flask

I am trying to redirect my 404 to a external URL like this:
#app.route('404')
def http_error_handler(error):
return flask.redirect("http://www.exemple.com/404"), 404
but it does not work. I keep getting:
Not Found
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
You should try something like this:
from flask import render_template
#app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'), 404
Source http://flask.pocoo.org/docs/1.0/patterns/errorpages/
You cannot do this - the user-agent (in most cases, a browser) looks at the status code that is returned to determine what to do. When you return a 404 status code what you are saying to the user-agent is, "I don't know what this thing is you are requesting" and the user-agent can then:
Display what you return in the body of the response
Display its own error message to the end user
Do some combination of the above two options
redirect actually creates a little HTML response (via werkzeug.exceptions), which normally the end user doesn't see because the user-agent follows the Location header when it sees the 302 response. However, you override the status code when you provide your own status code (404).
The fix is to either:
Remove the status code (at the cost of sending the wrong signal to the end user, potentially)
or Send a 404 with a meta:refresh and / or JavaScript redirect (slightly better, still confusing):
return redirect("/where-ever"), 404, {"Refresh": "1; url=/where-ever"}
Try this instead of a route
from flask import request
#app.errorhandler(404)
def own_404_page(error):
pageName = request.args.get('url')
print(pageName)
print(error)
f = open('erreur404.tpl')
return f.read()

Django issue with requests in getting json

I have a front-end server that is getting some JSON data from my backend server. Both servers are running Django. This is the exact code that gets the json data..
def View(request):
r = requests.get(path)
return HttpResponse(r.json())
However, I am running into a strange problem today where the call completes successfully ONCE after restarting the server. If I run the following code: -
def View(request):
r = requests.get(path)
r = requests.get(path)
return HttpResponse(r.json())
This works successfully as well.
However, on the second time that View() is called, I get an error. This is what the error message says:
"uWSGI exceptions catcher for "GET /api/v1/backend/" (request plugin: "python", modifier1: 0)
Exception: TypeError: http header value must be a string
Exception class: TypeError
Exception message: http header value must be a string"
Clearly, the error is being thrown on my backend server, but I only changed some templates on the frontend today. I am at a loss as to what has caused this problem to start occurring today. Can anyone point me in the right direction?
give it the right json header:
return HttpResponse(data, content_type='application/json')

Django Test Client post() returns 302 despite error on view's post()

I'm currently writing up some basic tests to ensure pages in a medium sized Django application are GETting and POSTing correctly. However, using django.test.client.Client isn't reliably failing when it should be. It returns a 302 response even when there's obviously placed errors in my code.
in my app/urls.py:
url(r'^mymodel/create/$',
views.MyModelView.as_view(),
name = 'my_model_create'),
Then, in attempts to intentionally create a 500 response, I did the following:
class MyModelCreateView(MyModelView, CreateView):
def post(self, request, *args, **kwargs):
print self.hello
self.object = MyModel()
return super(MyModelCreateView, self).post(request, *args, **kwargs)
Obviously, the view doesn't have any object called hello. This fails as expected when trying to send the request through the browser.
and even went as far as replacing "print self.hello" with
return HttpResponse(status = 500)
and yet, I still get the following:
#We have a model called Client, so it
#is imported as RequestClient to avoid conflicts
In [1]: from django.test.client import Client as RequestClient
In [2]: client = RequestClient()
In [3]: response = client.post("/app/mymodel/create/")
In [4]: response.status_code
Out[4]: 302
Clearly the problem here is between the keyboard and the chair, since there's no reason Client()/RequestClient() shouldn't return a 500 error if done correctly. Even some problems arise as I receive 302 responses for POST requests instead of 200 responses, but that may be because we're using HttpRedirect.
Does anyone out there know what may be the problem here? For reference I'm on Python 2.7 and Django 1.5 (though I may need to be compatible with Django 1.4).
It's not totally clear why you're getting a redirect, but if you want to follow it you need to tell RequestClient to follow redirects - per the documentation:
If you set follow to True the client will follow any redirects and a
redirect_chain attribute will be set in the response object containing
tuples of the intermediate urls and status codes.
So your test code should look like:
response = client.post("/app/mymodel/create/", follow=True)
It'd be worth checking the request chain to see where exactly it was routed.

Categories

Resources