Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -9,6 +9,7 @@ from mimetypes import guess_type, add_type
|
||||
from formencode import htmlfill, Invalid, variabledecode
|
||||
from formencode.schema import merge_dicts
|
||||
from paste.recursive import ForwardRequestException
|
||||
from urlparse import urlsplit, urlunsplit
|
||||
|
||||
try:
|
||||
from simplejson import loads
|
||||
@@ -69,7 +70,7 @@ def abort(status_code=None, detail='', headers=None, comment=None, **kw):
|
||||
raise exc.status_map[status_code](detail=detail, headers=headers, comment=comment, **kw)
|
||||
|
||||
|
||||
def redirect(location, internal=False, code=None, headers={}):
|
||||
def redirect(location=None, internal=False, code=None, headers={}, add_slash=False):
|
||||
'''
|
||||
Perform a redirect, either internal or external. An internal redirect
|
||||
performs the redirect server-side, while the external redirect utilizes
|
||||
@@ -81,6 +82,16 @@ def redirect(location, internal=False, code=None, headers={}):
|
||||
:param headers: Any HTTP headers to send with the response, as a dictionary.
|
||||
'''
|
||||
|
||||
new_env = request.environ.copy()
|
||||
if add_slash:
|
||||
if location is None:
|
||||
split_url = list(urlsplit(state.request.url))
|
||||
new_proto = new_env.get('HTTP_X_FORWARDED_PROTO', split_url[0])
|
||||
split_url[0] = new_proto
|
||||
location = urlunsplit(split_url)
|
||||
location = location.rstrip('/') + '/'
|
||||
if not headers:
|
||||
headers = {}
|
||||
if internal:
|
||||
if code is not None:
|
||||
raise ValueError('Cannot specify a code for internal redirects')
|
||||
@@ -210,7 +221,7 @@ class Pecan(object):
|
||||
'POST data when redirected. Please update your code '\
|
||||
'to POST to '%s/' or set force_canonical to False" % \
|
||||
(request.pecan['routing_path'], request.pecan['routing_path'])
|
||||
raise exc.HTTPFound(add_slash=True)
|
||||
redirect(code=302, add_slash=True)
|
||||
return e.controller, e.remainder
|
||||
|
||||
def determine_hooks(self, controller=None):
|
||||
|
||||
@@ -546,10 +546,11 @@ class TestBase(TestCase):
|
||||
@expose()
|
||||
def permanent(self):
|
||||
redirect('/testing', code=301)
|
||||
|
||||
|
||||
@expose()
|
||||
def testing(self):
|
||||
return 'it worked!'
|
||||
|
||||
|
||||
app = TestApp(make_app(RootController(), debug=True))
|
||||
r = app.get('/')
|
||||
@@ -569,6 +570,29 @@ class TestBase(TestCase):
|
||||
r = r.follow()
|
||||
assert r.status_int == 200
|
||||
assert r.body == 'it worked!'
|
||||
|
||||
|
||||
def test_x_forward_proto(self):
|
||||
class ChildController(object):
|
||||
@expose()
|
||||
def index(self):
|
||||
redirect('/testing')
|
||||
class RootController(object):
|
||||
@expose()
|
||||
def index(self):
|
||||
redirect('/testing')
|
||||
@expose()
|
||||
def testing(self):
|
||||
return 'it worked!'
|
||||
child = ChildController()
|
||||
|
||||
app = TestApp(make_app(RootController(), debug=True))
|
||||
response = app.get('/child', extra_environ=dict(HTTP_X_FORWARDED_PROTO='https'))
|
||||
##non-canonical url will redirect, so we won't get a 301
|
||||
assert response.status_int == 302
|
||||
##should add trailing / and changes location to https
|
||||
assert response.location == 'https://localhost/child/'
|
||||
assert response.environ['HTTP_X_FORWARDED_PROTO'] == 'https'
|
||||
|
||||
def test_streaming_response(self):
|
||||
import StringIO
|
||||
|
||||
3
tests/test_config/sample_apps/sample_app/app.py
Normal file
3
tests/test_config/sample_apps/sample_app/app.py
Normal file
@@ -0,0 +1,3 @@
|
||||
def setup_app(config):
|
||||
assert config.foo.sample_key == True
|
||||
return 'DEPLOYED!'
|
||||
9
tests/test_config/sample_apps/sample_app_config.py
Normal file
9
tests/test_config/sample_apps/sample_app_config.py
Normal file
@@ -0,0 +1,9 @@
|
||||
import sample_app
|
||||
|
||||
app = {
|
||||
'modules': [sample_app]
|
||||
}
|
||||
|
||||
foo = {
|
||||
'sample_key': True
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import sample_app_missing
|
||||
|
||||
app = {
|
||||
'modules': [sample_app_missing]
|
||||
}
|
||||
|
||||
foo = {
|
||||
'sample_key': True
|
||||
}
|
||||
61
tests/test_deploy.py
Normal file
61
tests/test_deploy.py
Normal file
@@ -0,0 +1,61 @@
|
||||
from pecan.deploy import deploy
|
||||
from unittest import TestCase
|
||||
|
||||
import pytest
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
class TestDeploy(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
test_config_d = os.path.join(os.path.dirname(__file__), 'test_config', 'sample_apps')
|
||||
|
||||
if test_config_d not in sys.path:
|
||||
sys.path.append(test_config_d)
|
||||
|
||||
def test_module_lookup(self):
|
||||
"""
|
||||
1. A config file has:
|
||||
app { 'modules': [valid_module] }
|
||||
2. The module, `valid_module` has an app.py that defines a `def setup.py`
|
||||
"""
|
||||
test_config_file = os.path.join(os.path.dirname(__file__), 'test_config', 'sample_apps', 'sample_app_config.py')
|
||||
assert deploy(test_config_file) == 'DEPLOYED!'
|
||||
|
||||
def test_module_lookup_find_best_match(self):
|
||||
"""
|
||||
1. A config file has:
|
||||
app { 'modules': [invalid_module, valid_module] }
|
||||
2. The module, `valid_module` has an app.py that defines a `def setup_app`
|
||||
"""
|
||||
test_config_file = os.path.join(os.path.dirname(__file__), 'test_config', 'sample_apps', 'sample_app_config.py')
|
||||
assert deploy(test_config_file) == 'DEPLOYED!'
|
||||
|
||||
def test_missing_app_file_lookup(self):
|
||||
"""
|
||||
1. A config file has:
|
||||
app { 'modules': [valid_module] }
|
||||
2. The module has no `app.py` file.
|
||||
"""
|
||||
test_config_file = os.path.join(os.path.dirname(__file__), 'test_config', 'sample_apps', 'sample_app_config_missing.py')
|
||||
self.assertRaisesRegexp(
|
||||
Exception,
|
||||
'No app.setup_app found in any of the configured app.modules',
|
||||
deploy,
|
||||
test_config_file
|
||||
)
|
||||
|
||||
def test_missing_setup_app(self):
|
||||
"""
|
||||
1. A config file has:
|
||||
app { 'modules': [valid_module] }
|
||||
2. The module, `valid_module` has an `app.py` that contains no `def setup_app`
|
||||
"""
|
||||
test_config_file = os.path.join(os.path.dirname(__file__), 'test_config', 'sample_apps', 'sample_app_config_missing_app.py')
|
||||
self.assertRaisesRegexp(
|
||||
Exception,
|
||||
'No app.setup_app found in any of the configured app.modules',
|
||||
deploy,
|
||||
test_config_file
|
||||
)
|
||||
Reference in New Issue
Block a user