@@ -54,10 +54,16 @@ def wsgi_decoding_dance(s, charset="utf-8", errors="replace"):
54
54
return s .encode ("latin1" ).decode (charset , errors )
55
55
56
56
57
- def get_host (environ ):
58
- # type: (Dict[str, str]) -> str
57
+ def get_host (environ , use_x_forwarded_for = False ):
58
+ # type: (Dict[str, str], bool ) -> str
59
59
"""Return the host for the given WSGI environment. Yanked from Werkzeug."""
60
- if environ .get ("HTTP_HOST" ):
60
+ if use_x_forwarded_for and "HTTP_X_FORWARDED_HOST" in environ :
61
+ rv = environ ["HTTP_X_FORWARDED_HOST" ]
62
+ if environ ["wsgi.url_scheme" ] == "http" and rv .endswith (":80" ):
63
+ rv = rv [:- 3 ]
64
+ elif environ ["wsgi.url_scheme" ] == "https" and rv .endswith (":443" ):
65
+ rv = rv [:- 4 ]
66
+ elif environ .get ("HTTP_HOST" ):
61
67
rv = environ ["HTTP_HOST" ]
62
68
if environ ["wsgi.url_scheme" ] == "http" and rv .endswith (":80" ):
63
69
rv = rv [:- 3 ]
@@ -77,23 +83,24 @@ def get_host(environ):
77
83
return rv
78
84
79
85
80
- def get_request_url (environ ):
81
- # type: (Dict[str, str]) -> str
86
+ def get_request_url (environ , use_x_forwarded_for = False ):
87
+ # type: (Dict[str, str], bool ) -> str
82
88
"""Return the absolute URL without query string for the given WSGI
83
89
environment."""
84
90
return "%s://%s/%s" % (
85
91
environ .get ("wsgi.url_scheme" ),
86
- get_host (environ ),
92
+ get_host (environ , use_x_forwarded_for ),
87
93
wsgi_decoding_dance (environ .get ("PATH_INFO" ) or "" ).lstrip ("/" ),
88
94
)
89
95
90
96
91
97
class SentryWsgiMiddleware (object ):
92
- __slots__ = ("app" ,)
98
+ __slots__ = ("app" , "use_x_forwarded_for" )
93
99
94
- def __init__ (self , app ):
95
- # type: (Callable[[Dict[str, str], Callable[..., Any]], Any]) -> None
100
+ def __init__ (self , app , use_x_forwarded_for = False ):
101
+ # type: (Callable[[Dict[str, str], Callable[..., Any]], Any], bool ) -> None
96
102
self .app = app
103
+ self .use_x_forwarded_for = use_x_forwarded_for
97
104
98
105
def __call__ (self , environ , start_response ):
99
106
# type: (Dict[str, str], Callable[..., Any]) -> _ScopedResponse
@@ -110,7 +117,9 @@ def __call__(self, environ, start_response):
110
117
scope .clear_breadcrumbs ()
111
118
scope ._name = "wsgi"
112
119
scope .add_event_processor (
113
- _make_wsgi_event_processor (environ )
120
+ _make_wsgi_event_processor (
121
+ environ , self .use_x_forwarded_for
122
+ )
114
123
)
115
124
116
125
transaction = Transaction .continue_from_environ (
@@ -269,8 +278,8 @@ def close(self):
269
278
reraise (* _capture_exception (self ._hub ))
270
279
271
280
272
- def _make_wsgi_event_processor (environ ):
273
- # type: (Dict[str, str]) -> EventProcessor
281
+ def _make_wsgi_event_processor (environ , use_x_forwarded_for ):
282
+ # type: (Dict[str, str], bool ) -> EventProcessor
274
283
# It's a bit unfortunate that we have to extract and parse the request data
275
284
# from the environ so eagerly, but there are a few good reasons for this.
276
285
#
@@ -284,7 +293,7 @@ def _make_wsgi_event_processor(environ):
284
293
# https://github.com/unbit/uwsgi/issues/1950
285
294
286
295
client_ip = get_client_ip (environ )
287
- request_url = get_request_url (environ )
296
+ request_url = get_request_url (environ , use_x_forwarded_for )
288
297
query_string = environ .get ("QUERY_STRING" )
289
298
method = environ .get ("REQUEST_METHOD" )
290
299
env = dict (_get_environ (environ ))
0 commit comments