Environment:
- Python 3.6.1
- Flask 0.12.2
- Werkzeug 0.14.1
While writing tests for my Flask application, I have discovered the following peculiarity: if in tests for Flask application you will be redirected to the same url two times 'in a row' ClientRedirectError: loop detected
will be thrown, even if it stops redirecting after the second redirect (i.e. loop is not, actually, happening).
Consider the following, simplified, example:
app.py
from flask import (
Flask,
redirect,
url_for,
session
)
app = Flask(__name__)
app.secret_key = 'improper secret key'
@app.route('/')
def index():
if not session.get('test', False):
session['test'] = True
return redirect(url_for('index'))
else:
return "Hello"
@app.route('/redirection/')
def redirection():
# do something — login user, for example
return redirect(url_for('index'))
test_redirect.py
from unittest import TestCase
from app import app
class RedirectTestCase(TestCase):
def setUp(self):
self.test_client = app.test_client()
def testLoop(self):
response = self.test_client.get('/redirection/', follow_redirects=True)
self.assertTrue('Hello'.encode('ascii') in response.data)
Now, if I will run the test — it'll throw a ClientRedirectError: loop detected
(even though, it could be seen from the code that second redirect will happen only once).
If I just run the app and go to the /redirection/
— it takes me to the index (i.e. /
) with no problem, and no looping is happening.
The reason I need if not session.get('test', False):
in index()
, is because in my app I'm using it to set some things in session
, in case user accessing /
for the first time. As suggested by comment in code, in my 'real' app redirection()
is a function that logs user in.
My questions are:
- Is there a 'right' way to overcome throwing of
ClientRedirectError: loop detected
in similar cases (i.e. is it possible to make the test run & pass)? - Is there a better/'more correct' way to setup things in
session
for the 'first-time' user? - Can mentioned behaviour be considered a bug in werkzeug (i.e. actual looping is not happening, but
ClientRedirectError: loop detected
is thrown, still)?
Workaround, I have came up with (which does not answer my questions, still):
def testLoop(self):
self.test_client.get('/redirection/') # removed follow_redirects=True
response = self.test_client.get('/', follow_redirects=True) # navigating to '/', directly
self.assertTrue('Hello'.encode('ascii') in response.data)
This might look redundant, but it's just a simplified example (it'll, probably, make more sense if self.test_client.get('/redirection/')
would be replaced with something like self.test_client.post('/login/', data=dict(username='user', password='pass'))
.