diff --git a/csp/contrib/formatted_policy.py b/csp/contrib/formatted_policy.py new file mode 100644 index 0000000..98ff6e6 --- /dev/null +++ b/csp/contrib/formatted_policy.py @@ -0,0 +1,36 @@ +from string import Formatter + +from django.conf import settings + +from csp.middleware import CSPMiddleware + + +class FormattedPolicyCSPMiddleware(CSPMiddleware): + """A CSP middleware that formats elements of the policy based on the + request and response and formatting functions defined in + CSP_POLICY_FORMATTERS.""" + + formatter = Formatter() + + def build_policy(self, request, response): + formatter = self.formatter + formatters = getattr( + settings, + 'CSP_POLICY_FORMATTERS', + {'host': lambda request, response: request.META['HTTP_HOST']}, + ) + all_replacements = {} + for (csp, report_only, exclude_prefixes) in super().build_policy( + request, response, + ): + format_kwargs = { + field_name for _, field_name, _, _ in formatter.parse(csp) + } + if format_kwargs: + for name in format_kwargs: + if name not in all_replacements: + all_replacements[name] = formatters[name]( + request, response, + ) + csp = formatter.format(csp, **all_replacements) + yield csp, report_only, exclude_prefixes