@@ -1236,10 +1236,16 @@ class SecureSchemeHeader(Setting):
12361236 desc = """\
12371237
12381238 A dictionary containing headers and values that the front-end proxy
1239- uses to indicate HTTPS requests. These tell Gunicorn to set
1239+ uses to indicate HTTPS requests. If the source IP is permitted by
1240+ ``forwarded-allow-ips`` (below), *and* at least one request header matches
1241+ a key-value pair listed in this dictionary, then Gunicorn will set
12401242 ``wsgi.url_scheme`` to ``https``, so your application can tell that the
12411243 request is secure.
12421244
1245+ If the other headers listed in this dictionary are not present in the request, they will be ignored,
1246+ but if the other headers are present and do not match the provided values, then
1247+ the request will fail to parse. See the note below for more detailed examples of this behaviour.
1248+
12431249 The dictionary should map upper-case header names to exact string
12441250 values. The value comparisons are case-sensitive, unlike the header
12451251 names, so make sure they're exactly what your front-end proxy sends
@@ -1267,6 +1273,70 @@ class ForwardedAllowIPS(Setting):
12671273
12681274 By default, the value of the ``FORWARDED_ALLOW_IPS`` environment
12691275 variable. If it is not defined, the default is ``"127.0.0.1"``.
1276+
1277+ .. note::
1278+
1279+ The interplay between the request headers, the value of ``forwarded_allow_ips``, and the value of
1280+ ``secure_scheme_headers`` is complex. Various scenarios are documented below to further elaborate. In each case, we
1281+ have a request from the remote address 134.213.44.18, and the default value of ``secure_scheme_headers``:
1282+
1283+ .. code::
1284+
1285+ secure_scheme_headers = {
1286+ 'X-FORWARDED-PROTOCOL': 'ssl',
1287+ 'X-FORWARDED-PROTO': 'https',
1288+ 'X-FORWARDED-SSL': 'on'
1289+ }
1290+
1291+
1292+ .. list-table::
1293+ :header-rows: 1
1294+ :align: center
1295+ :widths: auto
1296+
1297+ * - ``forwarded-allow-ips``
1298+ - Secure Request Headers
1299+ - Result
1300+ - Explanation
1301+ * - .. code::
1302+
1303+ ["127.0.0.1"]
1304+ - .. code::
1305+
1306+ X-Forwarded-Proto: https
1307+ - .. code::
1308+
1309+ wsgi.url_scheme = "http"
1310+ - IP address was not allowed
1311+ * - .. code::
1312+
1313+ "*"
1314+ - <none>
1315+ - .. code::
1316+
1317+ wsgi.url_scheme = "http"
1318+ - IP address allowed, but no secure headers provided
1319+ * - .. code::
1320+
1321+ "*"
1322+ - .. code::
1323+
1324+ X-Forwarded-Proto: https
1325+ - .. code::
1326+
1327+ wsgi.url_scheme = "https"
1328+ - IP address allowed, one request header matched
1329+ * - .. code::
1330+
1331+ ["134.213.44.18"]
1332+ - .. code::
1333+
1334+ X-Forwarded-Ssl: on
1335+ X-Forwarded-Proto: http
1336+ - ``InvalidSchemeHeaders()`` raised
1337+ - IP address allowed, but the two secure headers disagreed on if HTTPS was used
1338+
1339+
12701340 """
12711341
12721342
0 commit comments