Skip to content

Commit 2772737

Browse files
authored
Merge pull request #54 from smartystreets/eric/x-forwarded-for
Eric/x forwarded for
2 parents f7b3783 + 201344e commit 2772737

File tree

3 files changed

+72
-4
lines changed

3 files changed

+72
-4
lines changed

smartystreets_python_sdk/client_builder.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ def __init__(self, signer):
2323
self.max_timeout = 10
2424
self.url_prefix = None
2525
self.proxy = None
26+
self.ip = None
2627
self.debug = None
2728
self.header = None
2829
self.licenses = []
@@ -114,6 +115,15 @@ def with_custom_header(self, custom_header):
114115
"""
115116
self.header = custom_header
116117
return self
118+
119+
def with_x_forwarded_for(self, ip):
120+
"""
121+
Add and X-Forwarded-For header when necessary.
122+
:param ip: Input the desired ip for the X-Forwarded-For header
123+
:return: Returns self to accommodate method chaining
124+
"""
125+
self.ip = ip
126+
return self
117127

118128
def with_debug(self):
119129
"""
@@ -170,7 +180,7 @@ def build_sender(self):
170180
if self.http_sender is not None:
171181
return self.http_sender
172182

173-
sender = smarty.RequestsSender(self.max_timeout, self.proxy)
183+
sender = smarty.RequestsSender(self.max_timeout, self.proxy, self.ip)
174184
sender.debug = self.debug
175185

176186
sender = smarty.StatusCodeSender(sender)

smartystreets_python_sdk/requests_sender.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@
55

66

77
class RequestsSender:
8-
def __init__(self, max_timeout=None, proxy=None):
8+
def __init__(self, max_timeout=None, proxy=None, ip=None):
99
self.session = Session()
1010
self.max_timeout = max_timeout or 10
1111
self.proxy = proxy
1212
self.debug = None
13+
self.ip = ip
1314

1415
def send(self, smarty_request):
15-
request = build_request(smarty_request)
16+
ip = self.ip
17+
request = build_request(smarty_request, ip)
1618
prepped_request = self.session.prepare_request(request)
1719
prepped_proxies = self.build_proxies()
1820
if self.debug:
@@ -43,13 +45,15 @@ def build_proxies(self):
4345
return {'http': proxy_string, 'https': proxy_string}
4446

4547

46-
def build_request(smarty_request):
48+
def build_request(smarty_request, ip=None):
4749
try:
4850
request = Request(url=smarty_request.url_prefix, params=smarty_request.parameters)
4951
request.headers['User-Agent'] = "smartystreets (sdk:python@{})".format(version.__version__)
5052
request.headers['Content-Type'] = smarty_request.content_type
5153
if smarty_request.referer:
5254
request.headers['Referer'] = smarty_request.referer
55+
if ip != None:
56+
request.headers['X-Forwarded-For'] = ip
5357
if smarty_request.payload:
5458
request.data = smarty_request.payload
5559
request.method = 'POST'

test/x_forwarded_for_test.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import smartystreets_python_sdk as smarty
2+
import unittest
3+
from mock import patch
4+
5+
6+
def mocked_session_send(request, **kwargs):
7+
class MockResponse:
8+
def __init__(self, payload, status_code):
9+
self.text = payload
10+
self.status_code = status_code
11+
self.headers = None
12+
13+
def __enter__(self):
14+
return self
15+
16+
def __exit__(self, type, value, traceback):
17+
pass
18+
19+
def json(self):
20+
return self.text
21+
22+
mockresponse = MockResponse("This is the test payload.", 200)
23+
24+
return mockresponse
25+
26+
27+
class TestCustomHeaderSender(unittest.TestCase):
28+
29+
def test_populates_header(self):
30+
sender = smarty.RequestsSender(ip = '0.0.0.0')
31+
32+
self.assertEqual(sender.ip, '0.0.0.0')
33+
34+
@patch('requests.Session.send', side_effect=mocked_session_send)
35+
def test_x_forwarded_for_header_set(self, mock_send):
36+
sender = smarty.RequestsSender(ip = '0.0.0.0')
37+
smartyrequest = smarty.Request()
38+
smartyrequest.url_prefix = "http://localhost"
39+
smartyrequest.payload = "This is the test content."
40+
41+
request = smarty.requests_sender.build_request(smartyrequest, '0.0.0.0')
42+
43+
self.assertEqual('0.0.0.0', request.headers['X-Forwarded-For'])
44+
45+
@patch('requests.Session.send', side_effect=mocked_session_send)
46+
def test_custom_headers_used(self, mock_send):
47+
sender = smarty.RequestsSender(ip = '0.0.0.0')
48+
smartyrequest = smarty.Request()
49+
smartyrequest.url_prefix = "http://localhost"
50+
smartyrequest.payload = "This is the test content."
51+
52+
request = smarty.requests_sender.build_request(smartyrequest, '0.0.0.0')
53+
54+
self.assertEqual('0.0.0.0', request.headers['X-Forwarded-For'])

0 commit comments

Comments
 (0)