# frozen_string_literal: true

module Middleware
  class CspScriptNonceInjector
    PLACEHOLDER_HEADER = "Discourse-CSP-Nonce-Placeholder"

    def initialize(app, settings = {})
      @app = app
    end

    def call(env)
      status, headers, response = @app.call(env)

      if nonce_placeholder = headers.delete(PLACEHOLDER_HEADER)
        nonce = SecureRandom.alphanumeric(25)
        parts = []
        response.each { |part| parts << part.to_s.gsub(nonce_placeholder, nonce) }
        %w[Content-Security-Policy Content-Security-Policy-Report-Only].each do |name|
          next if headers[name].blank?
          headers[name] = headers[name].sub("script-src ", "script-src 'nonce-#{nonce}' ")
        end
        [status, headers, parts]
      else
        [status, headers, response]
      end
    end
  end
end