Merge lp:~danilo/stega/proxy-support into lp:stega

Proposed by Данило Шеган
Status: Merged
Approved by: Sanja
Approved revision: 20
Merged at revision: 20
Proposed branch: lp:~danilo/stega/proxy-support
Merge into: lp:stega
Diff against target: 101 lines (+50/-1)
3 files modified
settings.py (+8/-0)
url_shortener/tests.py (+30/-0)
url_shortener/views.py (+12/-1)
To merge this branch: bzr merge lp:~danilo/stega/proxy-support
Reviewer Review Type Date Requested Status
Sanja Approve
Review via email: mp+124567@code.launchpad.net

Description of the change

Add support for handling X-Forwarded-For if hosted behind a semi-transparent
proxy (semi-transparent because it doesn't keep the REMOTE_ADDR but instead
uses X-Forwarded-For header).

To post a comment you must log in.
Revision history for this message
Sanja (sanjazivotic) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'settings.py'
2--- settings.py 2012-09-16 10:52:00 +0000
3+++ settings.py 2012-09-16 11:02:19 +0000
4@@ -16,6 +16,14 @@
5 # Restrict number of short urls that can be created from a single ip address.
6 URLS_PER_IP = 100
7
8+# Whether installation is behind a proxy.
9+# Warning: reads X-Forwarded-For to find out REMOTE_ADDR, so make sure you
10+# do have a proxy server adding to X-Forwarded-For, since it can otherwise
11+# be easily spoofed and will easily defeat the purpose of URLS_PER_IP
12+# protection.
13+TRANSPARENT_PROXY = True
14+
15+
16 ADMINS = (
17 ('Admin', 'root@localhost'),
18 )
19
20=== modified file 'url_shortener/tests.py'
21--- url_shortener/tests.py 2012-09-16 10:52:00 +0000
22+++ url_shortener/tests.py 2012-09-16 11:02:19 +0000
23@@ -6,6 +6,7 @@
24 TooManyUrlsError,
25 Url,
26 )
27+from url_shortener.views import UrlCreationView
28 import utils
29 import settings
30
31@@ -82,6 +83,9 @@
32 self.assertEqual(200, response.status_code)
33
34
35+class MockRequest(object):
36+ META = {}
37+
38 class TestUrlCreationView(TestCase):
39 def test_url_creation_view_success(self):
40 response = self.client.post(
41@@ -92,6 +96,32 @@
42 response.content
43 )
44
45+ def test_get_ip_address_remote_addr(self):
46+ # This reads back REMOTE_ADDR from the server environment.
47+ request = MockRequest()
48+ request.META = { 'REMOTE_ADDR': 'my-ip', }
49+ self.assertEqual('my-ip', UrlCreationView.get_ip_address(request))
50+
51+ def test_get_ip_address_x_forwarded_to_no_proxy(self):
52+ # This reads back REMOTE_ADDR from the server environment,
53+ # and ignores X_FORWARDED_FOR when allow_proxy is False.
54+ request = MockRequest()
55+ request.META = { 'REMOTE_ADDR': 'my-ip',
56+ 'X_FORWARDED_FOR': 'ip1, ip2'}
57+ self.assertEqual(
58+ 'my-ip',
59+ UrlCreationView.get_ip_address(request, allow_proxy=False))
60+
61+ def test_get_ip_address_x_forwarded_to_allow_proxy(self):
62+ # This reads back REMOTE_ADDR from the server environment,
63+ # and ignores X_FORWARDED_FOR when allow_proxy is False.
64+ request = MockRequest()
65+ request.META = { 'REMOTE_ADDR': 'my-ip',
66+ 'X_FORWARDED_FOR': 'ip1, ip2'}
67+ self.assertEqual(
68+ 'ip1',
69+ UrlCreationView.get_ip_address(request, allow_proxy=True))
70+
71 def test_url_creation_view_no_param(self):
72 response = self.client.post('/create/')
73 self.assertEqual(400, response.status_code)
74
75=== modified file 'url_shortener/views.py'
76--- url_shortener/views.py 2012-09-15 09:11:25 +0000
77+++ url_shortener/views.py 2012-09-16 11:02:19 +0000
78@@ -39,11 +39,22 @@
79
80
81 class UrlCreationView(View):
82+ @staticmethod
83+ def get_ip_address(request, allow_proxy=False):
84+ if allow_proxy and 'X_FORWARDED_FOR' in request.META:
85+ all_ips = request.META['X_FORWARDED_FOR'].split(',')
86+ # Only the left-most one is accepted.
87+ return all_ips[0]
88+ else:
89+ return request.META['REMOTE_ADDR']
90+
91 def post(self, request, **kwargs):
92 try:
93+ ip_address = self.get_ip_address(
94+ request, settings.TRANSPARENT_PROXY)
95 url = Url.get_or_create_url(
96 long_url=request.POST['long_url'],
97- ip_address=request.META['REMOTE_ADDR']
98+ ip_address=ip_address,
99 )
100 host_name = request.META['HTTP_HOST']
101 full_short_url = 'http://%s/%s' % (host_name, url.short_url)

Subscribers

People subscribed via source and target branches