123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- import importlib
-
- from twisted.web.http_headers import Headers
-
-
- def import_by_path(path):
- """
- Given a dotted/colon path, like project.module:ClassName.callable,
- returns the object at the end of the path.
- """
- module_path, object_path = path.split(":", 1)
- target = importlib.import_module(module_path)
- for bit in object_path.split("."):
- target = getattr(target, bit)
- return target
-
-
- def header_value(headers, header_name):
- value = headers[header_name]
- if isinstance(value, list):
- value = value[0]
- return value.decode("utf-8")
-
-
- def parse_x_forwarded_for(
- headers,
- address_header_name="X-Forwarded-For",
- port_header_name="X-Forwarded-Port",
- proto_header_name="X-Forwarded-Proto",
- original_addr=None,
- original_scheme=None,
- ):
- """
- Parses an X-Forwarded-For header and returns a host/port pair as a list.
-
- @param headers: The twisted-style object containing a request's headers
- @param address_header_name: The name of the expected host header
- @param port_header_name: The name of the expected port header
- @param proto_header_name: The name of the expected proto header
- @param original_addr: A host/port pair that should be returned if the headers are not in the request
- @param original_scheme: A scheme that should be returned if the headers are not in the request
- @return: A list containing a host (string) as the first entry and a port (int) as the second.
- """
- if not address_header_name:
- return original_addr, original_scheme
-
- # Convert twisted-style headers into dicts
- if isinstance(headers, Headers):
- headers = dict(headers.getAllRawHeaders())
-
- # Lowercase all header names in the dict
- headers = {name.lower(): values for name, values in headers.items()}
-
- # Make sure header names are bytes (values are checked in header_value)
- assert all(isinstance(name, bytes) for name in headers.keys())
-
- address_header_name = address_header_name.lower().encode("utf-8")
- result_addr = original_addr
- result_scheme = original_scheme
- if address_header_name in headers:
- address_value = header_value(headers, address_header_name)
-
- if "," in address_value:
- address_value = address_value.split(",")[0].strip()
-
- result_addr = [address_value, 0]
-
- if port_header_name:
- # We only want to parse the X-Forwarded-Port header if we also parsed the X-Forwarded-For
- # header to avoid inconsistent results.
- port_header_name = port_header_name.lower().encode("utf-8")
- if port_header_name in headers:
- port_value = header_value(headers, port_header_name)
- try:
- result_addr[1] = int(port_value)
- except ValueError:
- pass
-
- if proto_header_name:
- proto_header_name = proto_header_name.lower().encode("utf-8")
- if proto_header_name in headers:
- result_scheme = header_value(headers, proto_header_name)
-
- return result_addr, result_scheme
|