Class: HeaderGuard::Middleware

Inherits:
Object
  • Object
show all
Defined in:
lib/header_guard/middleware.rb

Overview

The Rack middleware class responsible for injecting security headers.

Instance Method Summary collapse

Constructor Details

#initialize(app, options = {}) ⇒ Middleware

Initializes the middleware. It merges user-defined options over defaults.

Parameters:

  • app (Object)

    The next application in the Rack stack.

  • options (Hash) (defaults to: {})

    Configuration options for headers and CSP.



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/header_guard/middleware.rb', line 10

def initialize(app, options = {})
  @app = app
  
  # Use a copy of options for configuration extraction
  config = options.dup

  # Extract special configuration settings
  custom_csp = config.delete(:content_security_policy)
  @report_only = config.delete(:report_only) || false

  # 1. Start with DEFAULT_HEADERS (from header_guard.rb)
  # 2. Merge remaining options (which are custom headers) over the defaults.
  # THIS IS THE FIX: By merging 'config' (which now only contains headers)
  # over the defaults, the user's header values take precedence.
  @headers = DEFAULT_HEADERS.merge(config).freeze

  # Set the final CSP value and the header key based on report_only setting
  @csp_value = custom_csp || DEFAULT_CSP
  @csp_header_key = @report_only ? "Content-Security-Policy-Report-Only" : "Content-Security-Policy"
end

Instance Method Details

#call(env) ⇒ Object

The Rack application call method.



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/header_guard/middleware.rb', line 32

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

  # Only inject headers on successful (2xx) responses with HTML content.
  # Exclude redirects, errors, and non-HTML assets (like JSON or images).
  if (200..299).include?(status) && headers["Content-Type"]&.include?("text/html")
    
    # Inject the standard headers
    @headers.each do |key, value|
      # We use assignment (=) here, not `||=`, to ensure the middleware
      # overwrites any headers set by the application before it,
      # adhering to the strong security posture.
      headers[key] = value 
    end
    
    # Inject the configured CSP header
    headers[@csp_header_key] = @csp_value
  end

  [status, headers, body]
end