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
=== modified file 'settings.py'
--- settings.py 2012-09-16 10:52:00 +0000
+++ settings.py 2012-09-16 11:02:19 +0000
@@ -16,6 +16,14 @@
16# Restrict number of short urls that can be created from a single ip address.16# Restrict number of short urls that can be created from a single ip address.
17URLS_PER_IP = 10017URLS_PER_IP = 100
1818
19# Whether installation is behind a proxy.
20# Warning: reads X-Forwarded-For to find out REMOTE_ADDR, so make sure you
21# do have a proxy server adding to X-Forwarded-For, since it can otherwise
22# be easily spoofed and will easily defeat the purpose of URLS_PER_IP
23# protection.
24TRANSPARENT_PROXY = True
25
26
19ADMINS = (27ADMINS = (
20 ('Admin', 'root@localhost'),28 ('Admin', 'root@localhost'),
21)29)
2230
=== modified file 'url_shortener/tests.py'
--- url_shortener/tests.py 2012-09-16 10:52:00 +0000
+++ url_shortener/tests.py 2012-09-16 11:02:19 +0000
@@ -6,6 +6,7 @@
6 TooManyUrlsError,6 TooManyUrlsError,
7 Url,7 Url,
8)8)
9from url_shortener.views import UrlCreationView
9import utils10import utils
10import settings11import settings
1112
@@ -82,6 +83,9 @@
82 self.assertEqual(200, response.status_code)83 self.assertEqual(200, response.status_code)
8384
8485
86class MockRequest(object):
87 META = {}
88
85class TestUrlCreationView(TestCase):89class TestUrlCreationView(TestCase):
86 def test_url_creation_view_success(self):90 def test_url_creation_view_success(self):
87 response = self.client.post(91 response = self.client.post(
@@ -92,6 +96,32 @@
92 response.content96 response.content
93 )97 )
9498
99 def test_get_ip_address_remote_addr(self):
100 # This reads back REMOTE_ADDR from the server environment.
101 request = MockRequest()
102 request.META = { 'REMOTE_ADDR': 'my-ip', }
103 self.assertEqual('my-ip', UrlCreationView.get_ip_address(request))
104
105 def test_get_ip_address_x_forwarded_to_no_proxy(self):
106 # This reads back REMOTE_ADDR from the server environment,
107 # and ignores X_FORWARDED_FOR when allow_proxy is False.
108 request = MockRequest()
109 request.META = { 'REMOTE_ADDR': 'my-ip',
110 'X_FORWARDED_FOR': 'ip1, ip2'}
111 self.assertEqual(
112 'my-ip',
113 UrlCreationView.get_ip_address(request, allow_proxy=False))
114
115 def test_get_ip_address_x_forwarded_to_allow_proxy(self):
116 # This reads back REMOTE_ADDR from the server environment,
117 # and ignores X_FORWARDED_FOR when allow_proxy is False.
118 request = MockRequest()
119 request.META = { 'REMOTE_ADDR': 'my-ip',
120 'X_FORWARDED_FOR': 'ip1, ip2'}
121 self.assertEqual(
122 'ip1',
123 UrlCreationView.get_ip_address(request, allow_proxy=True))
124
95 def test_url_creation_view_no_param(self):125 def test_url_creation_view_no_param(self):
96 response = self.client.post('/create/')126 response = self.client.post('/create/')
97 self.assertEqual(400, response.status_code)127 self.assertEqual(400, response.status_code)
98128
=== modified file 'url_shortener/views.py'
--- url_shortener/views.py 2012-09-15 09:11:25 +0000
+++ url_shortener/views.py 2012-09-16 11:02:19 +0000
@@ -39,11 +39,22 @@
3939
4040
41class UrlCreationView(View):41class UrlCreationView(View):
42 @staticmethod
43 def get_ip_address(request, allow_proxy=False):
44 if allow_proxy and 'X_FORWARDED_FOR' in request.META:
45 all_ips = request.META['X_FORWARDED_FOR'].split(',')
46 # Only the left-most one is accepted.
47 return all_ips[0]
48 else:
49 return request.META['REMOTE_ADDR']
50
42 def post(self, request, **kwargs):51 def post(self, request, **kwargs):
43 try:52 try:
53 ip_address = self.get_ip_address(
54 request, settings.TRANSPARENT_PROXY)
44 url = Url.get_or_create_url(55 url = Url.get_or_create_url(
45 long_url=request.POST['long_url'],56 long_url=request.POST['long_url'],
46 ip_address=request.META['REMOTE_ADDR']57 ip_address=ip_address,
47 )58 )
48 host_name = request.META['HTTP_HOST']59 host_name = request.META['HTTP_HOST']
49 full_short_url = 'http://%s/%s' % (host_name, url.short_url)60 full_short_url = 'http://%s/%s' % (host_name, url.short_url)

Subscribers

People subscribed via source and target branches