File: reporting_endpoints.rb

package info (click to toggle)
ruby-secure-headers 7.2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 556 kB
  • sloc: ruby: 4,196; makefile: 5
file content (54 lines) | stat: -rw-r--r-- 1,816 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# frozen_string_literal: true
module SecureHeaders
  class ReportingEndpointsConfigError < StandardError; end
  class ReportingEndpoints
    HEADER_NAME = "reporting-endpoints".freeze

    class << self
      # Public: generate a Reporting-Endpoints header.
      #
      # The config should be a Hash of endpoint names to URLs.
      # Example: { "csp-endpoint" => "https://example.com/reports" }
      #
      # Returns nil if config is OPT_OUT or nil, or a header name and
      # formatted header value based on the config.
      def make_header(config = nil)
        return if config.nil? || config == OPT_OUT
        validate_config!(config)
        [HEADER_NAME, format_endpoints(config)]
      end

      def validate_config!(config)
        case config
        when nil, OPT_OUT
          # valid
        when Hash
          config.each_pair do |name, url|
            if name.is_a?(Symbol)
              name = name.to_s
            end
            unless name.is_a?(String) && !name.empty?
              raise ReportingEndpointsConfigError.new("Endpoint name must be a non-empty string, got: #{name.inspect}")
            end
            unless url.is_a?(String) && !url.empty?
              raise ReportingEndpointsConfigError.new("Endpoint URL must be a non-empty string, got: #{url.inspect}")
            end
            unless url.start_with?("https://")
              raise ReportingEndpointsConfigError.new("Endpoint URLs must use https, got: #{url.inspect}")
            end
          end
        else
          raise TypeError.new("Must be a Hash of endpoint names to URLs. Found #{config.class}: #{config}")
        end
      end

      private

      def format_endpoints(config)
        config.map do |name, url|
          %{#{name}="#{url}"}
        end.join(", ")
      end
    end
  end
end