2013-05-14 18:00:04 +08:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
"""
|
2014-09-01 03:54:45 +08:00
|
|
|
tests.reqctx
|
2014-09-21 22:47:38 +08:00
|
|
|
~~~~~~~~~~~~
|
2013-05-14 18:00:04 +08:00
|
|
|
|
|
|
|
Tests the request context.
|
|
|
|
|
2018-02-09 02:57:40 +08:00
|
|
|
:copyright: © 2010 by the Pallets team.
|
2013-05-14 18:00:04 +08:00
|
|
|
:license: BSD, see LICENSE for more details.
|
|
|
|
"""
|
|
|
|
|
2014-09-02 11:26:52 +08:00
|
|
|
import pytest
|
|
|
|
|
2013-05-14 18:00:04 +08:00
|
|
|
import flask
|
2017-04-23 04:39:54 +08:00
|
|
|
from flask.sessions import SessionInterface
|
2014-09-21 22:47:38 +08:00
|
|
|
|
2013-05-14 18:00:04 +08:00
|
|
|
try:
|
|
|
|
from greenlet import greenlet
|
|
|
|
except ImportError:
|
|
|
|
greenlet = None
|
2014-09-04 03:02:03 +08:00
|
|
|
|
2013-05-14 18:00:04 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
def test_teardown_on_pop(app):
|
2014-09-04 02:56:10 +08:00
|
|
|
buffer = []
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
@app.teardown_request
|
|
|
|
def end_of_request(exception):
|
|
|
|
buffer.append(exception)
|
|
|
|
|
|
|
|
ctx = app.test_request_context()
|
|
|
|
ctx.push()
|
|
|
|
assert buffer == []
|
|
|
|
ctx.pop()
|
|
|
|
assert buffer == [None]
|
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_teardown_with_previous_exception(app):
|
2014-09-04 02:56:10 +08:00
|
|
|
buffer = []
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
@app.teardown_request
|
|
|
|
def end_of_request(exception):
|
|
|
|
buffer.append(exception)
|
|
|
|
|
|
|
|
try:
|
|
|
|
raise Exception('dummy')
|
|
|
|
except Exception:
|
|
|
|
pass
|
|
|
|
|
|
|
|
with app.test_request_context():
|
|
|
|
assert buffer == []
|
|
|
|
assert buffer == [None]
|
2013-05-14 18:00:04 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_teardown_with_handled_exception(app):
|
2015-03-23 23:17:19 +08:00
|
|
|
buffer = []
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2015-03-23 23:17:19 +08:00
|
|
|
@app.teardown_request
|
|
|
|
def end_of_request(exception):
|
|
|
|
buffer.append(exception)
|
|
|
|
|
|
|
|
with app.test_request_context():
|
|
|
|
assert buffer == []
|
|
|
|
try:
|
|
|
|
raise Exception('dummy')
|
|
|
|
except Exception:
|
|
|
|
pass
|
|
|
|
assert buffer == [None]
|
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_proper_test_request_context(app):
|
2014-09-04 02:56:10 +08:00
|
|
|
app.config.update(
|
|
|
|
SERVER_NAME='localhost.localdomain:5000'
|
|
|
|
)
|
2013-05-14 18:00:04 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
@app.route('/')
|
|
|
|
def index():
|
|
|
|
return None
|
2013-10-17 02:12:20 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
@app.route('/', subdomain='foo')
|
|
|
|
def sub():
|
|
|
|
return None
|
2013-10-17 02:12:20 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
with app.test_request_context('/'):
|
|
|
|
assert flask.url_for('index', _external=True) == \
|
2017-05-24 06:18:39 +08:00
|
|
|
'http://localhost.localdomain:5000/'
|
2013-05-14 18:00:04 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
with app.test_request_context('/'):
|
|
|
|
assert flask.url_for('sub', _external=True) == \
|
2017-05-24 06:18:39 +08:00
|
|
|
'http://foo.localhost.localdomain:5000/'
|
2014-09-02 11:26:52 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
try:
|
|
|
|
with app.test_request_context('/', environ_overrides={'HTTP_HOST': 'localhost'}):
|
2014-09-02 11:26:52 +08:00
|
|
|
pass
|
2014-09-04 02:56:10 +08:00
|
|
|
except ValueError as e:
|
|
|
|
assert str(e) == (
|
|
|
|
"the server name provided "
|
|
|
|
"('localhost.localdomain:5000') does not match the "
|
|
|
|
"server name from the WSGI environment ('localhost')"
|
|
|
|
)
|
2013-05-14 18:00:04 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
app.config.update(SERVER_NAME='localhost')
|
|
|
|
with app.test_request_context('/', environ_overrides={'SERVER_NAME': 'localhost'}):
|
|
|
|
pass
|
|
|
|
|
|
|
|
app.config.update(SERVER_NAME='localhost:80')
|
|
|
|
with app.test_request_context('/', environ_overrides={'SERVER_NAME': 'localhost:80'}):
|
|
|
|
pass
|
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_context_binding(app):
|
2014-09-04 02:56:10 +08:00
|
|
|
@app.route('/')
|
|
|
|
def index():
|
|
|
|
return 'Hello %s!' % flask.request.args['name']
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
@app.route('/meh')
|
|
|
|
def meh():
|
|
|
|
return flask.request.url
|
|
|
|
|
|
|
|
with app.test_request_context('/?name=World'):
|
2014-09-02 11:26:52 +08:00
|
|
|
assert index() == 'Hello World!'
|
2014-09-04 02:56:10 +08:00
|
|
|
with app.test_request_context('/meh'):
|
|
|
|
assert meh() == 'http://localhost/meh'
|
|
|
|
assert flask._request_ctx_stack.top is None
|
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_context_test(app):
|
2014-09-04 02:56:10 +08:00
|
|
|
assert not flask.request
|
|
|
|
assert not flask.has_request_context()
|
|
|
|
ctx = app.test_request_context()
|
|
|
|
ctx.push()
|
|
|
|
try:
|
|
|
|
assert flask.request
|
|
|
|
assert flask.has_request_context()
|
|
|
|
finally:
|
2013-05-14 18:00:04 +08:00
|
|
|
ctx.pop()
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
|
|
|
def test_manual_context_binding(app):
|
2014-09-04 02:56:10 +08:00
|
|
|
@app.route('/')
|
|
|
|
def index():
|
|
|
|
return 'Hello %s!' % flask.request.args['name']
|
|
|
|
|
|
|
|
ctx = app.test_request_context('/?name=World')
|
|
|
|
ctx.push()
|
|
|
|
assert index() == 'Hello World!'
|
|
|
|
ctx.pop()
|
2016-03-04 19:30:40 +08:00
|
|
|
with pytest.raises(RuntimeError):
|
2014-09-04 02:56:10 +08:00
|
|
|
index()
|
|
|
|
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2014-09-04 02:56:10 +08:00
|
|
|
@pytest.mark.skipif(greenlet is None, reason='greenlet not installed')
|
2017-05-24 07:51:50 +08:00
|
|
|
class TestGreenletContextCopying(object):
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2017-05-24 07:51:50 +08:00
|
|
|
def test_greenlet_context_copying(self, app, client):
|
2017-05-24 07:13:19 +08:00
|
|
|
greenlets = []
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2017-05-24 07:13:19 +08:00
|
|
|
@app.route('/')
|
|
|
|
def index():
|
2018-11-04 11:32:24 +08:00
|
|
|
flask.session['fizz'] = 'buzz'
|
2017-05-24 07:13:19 +08:00
|
|
|
reqctx = flask._request_ctx_stack.top.copy()
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2017-05-24 07:13:19 +08:00
|
|
|
def g():
|
|
|
|
assert not flask.request
|
|
|
|
assert not flask.current_app
|
|
|
|
with reqctx:
|
|
|
|
assert flask.request
|
|
|
|
assert flask.current_app == app
|
|
|
|
assert flask.request.path == '/'
|
|
|
|
assert flask.request.args['foo'] == 'bar'
|
2018-11-04 11:32:24 +08:00
|
|
|
assert flask.session.get('fizz') == 'buzz'
|
2017-05-24 07:13:19 +08:00
|
|
|
assert not flask.request
|
|
|
|
return 42
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2017-05-24 07:13:19 +08:00
|
|
|
greenlets.append(greenlet(g))
|
|
|
|
return 'Hello World!'
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2017-05-24 07:13:19 +08:00
|
|
|
rv = client.get('/?foo=bar')
|
|
|
|
assert rv.data == b'Hello World!'
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2017-05-24 07:13:19 +08:00
|
|
|
result = greenlets[0].run()
|
|
|
|
assert result == 42
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2017-05-24 07:51:50 +08:00
|
|
|
def test_greenlet_context_copying_api(self, app, client):
|
2017-05-24 07:13:19 +08:00
|
|
|
greenlets = []
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2017-05-24 07:13:19 +08:00
|
|
|
@app.route('/')
|
|
|
|
def index():
|
2018-11-04 11:32:24 +08:00
|
|
|
flask.session['fizz'] = 'buzz'
|
2017-05-24 07:13:19 +08:00
|
|
|
reqctx = flask._request_ctx_stack.top.copy()
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2017-05-24 07:13:19 +08:00
|
|
|
@flask.copy_current_request_context
|
|
|
|
def g():
|
|
|
|
assert flask.request
|
|
|
|
assert flask.current_app == app
|
|
|
|
assert flask.request.path == '/'
|
|
|
|
assert flask.request.args['foo'] == 'bar'
|
2018-11-04 11:32:24 +08:00
|
|
|
assert flask.session.get('fizz') == 'buzz'
|
2017-05-24 07:13:19 +08:00
|
|
|
return 42
|
2017-05-24 06:18:39 +08:00
|
|
|
|
2017-05-24 07:13:19 +08:00
|
|
|
greenlets.append(greenlet(g))
|
|
|
|
return 'Hello World!'
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2017-05-24 07:13:19 +08:00
|
|
|
rv = client.get('/?foo=bar')
|
|
|
|
assert rv.data == b'Hello World!'
|
2014-09-04 02:56:10 +08:00
|
|
|
|
2017-05-24 07:13:19 +08:00
|
|
|
result = greenlets[0].run()
|
|
|
|
assert result == 42
|
2017-04-23 04:39:54 +08:00
|
|
|
|
|
|
|
|
|
|
|
def test_session_error_pops_context():
|
|
|
|
class SessionError(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
class FailingSessionInterface(SessionInterface):
|
|
|
|
def open_session(self, app, request):
|
|
|
|
raise SessionError()
|
|
|
|
|
|
|
|
class CustomFlask(flask.Flask):
|
|
|
|
session_interface = FailingSessionInterface()
|
|
|
|
|
|
|
|
app = CustomFlask(__name__)
|
|
|
|
|
|
|
|
@app.route('/')
|
|
|
|
def index():
|
|
|
|
# shouldn't get here
|
|
|
|
assert False
|
|
|
|
|
|
|
|
response = app.test_client().get('/')
|
|
|
|
assert response.status_code == 500
|
|
|
|
assert not flask.request
|
|
|
|
assert not flask.current_app
|
2018-11-13 05:59:09 +08:00
|
|
|
|
|
|
|
|
|
|
|
def test_bad_environ_raises_bad_request():
|
|
|
|
app = flask.Flask(__name__)
|
|
|
|
|
2018-11-14 02:09:16 +08:00
|
|
|
# We cannot use app.test_client() for the Unicode-rich Host header,
|
|
|
|
# because werkzeug enforces latin1 on Python 2.
|
|
|
|
# However it works when actually passed to the server.
|
|
|
|
|
|
|
|
from flask.testing import make_test_environ_builder
|
|
|
|
builder = make_test_environ_builder(app)
|
|
|
|
environ = builder.get_environ()
|
|
|
|
|
|
|
|
# use a non-printable character in the Host - this is key to this test
|
|
|
|
environ['HTTP_HOST'] = u'\x8a'
|
|
|
|
|
|
|
|
with app.request_context(environ):
|
|
|
|
response = app.full_dispatch_request()
|
|
|
|
assert response.status_code == 400
|
|
|
|
|
|
|
|
|
|
|
|
def test_environ_for_valid_idna_completes():
|
|
|
|
app = flask.Flask(__name__)
|
|
|
|
|
2018-11-13 05:59:09 +08:00
|
|
|
@app.route('/')
|
|
|
|
def index():
|
2018-11-14 02:09:16 +08:00
|
|
|
return 'Hello World!'
|
2018-11-13 05:59:09 +08:00
|
|
|
|
2018-11-14 02:09:16 +08:00
|
|
|
# We cannot use app.test_client() for the Unicode-rich Host header,
|
|
|
|
# because werkzeug enforces latin1 on Python 2.
|
|
|
|
# However it works when actually passed to the server.
|
|
|
|
|
|
|
|
from flask.testing import make_test_environ_builder
|
|
|
|
builder = make_test_environ_builder(app)
|
|
|
|
environ = builder.get_environ()
|
|
|
|
|
|
|
|
# these characters are all IDNA-compatible
|
|
|
|
environ['HTTP_HOST'] = u'ąśźäüжŠßя.com'
|
|
|
|
|
|
|
|
with app.request_context(environ):
|
|
|
|
response = app.full_dispatch_request()
|
|
|
|
|
|
|
|
assert response.status_code == 200
|
2018-11-13 05:59:09 +08:00
|
|
|
|
|
|
|
|
|
|
|
def test_normal_environ_completes():
|
|
|
|
app = flask.Flask(__name__)
|
|
|
|
|
|
|
|
@app.route('/')
|
|
|
|
def index():
|
|
|
|
return 'Hello World!'
|
|
|
|
|
|
|
|
response = app.test_client().get('/', headers={'host': 'xn--on-0ia.com'})
|
|
|
|
assert response.status_code == 200
|