Class: Datastar::CompressionConfig

Inherits:
Object
  • Object
show all
Defined in:
lib/datastar/compression_config.rb

Overview

Immutable value object that holds an ordered list of pre-built compressors and negotiates the best one for a given request.

Use CompressionConfig.build to create instances from user-facing configuration values. The first compressor in the list is preferred when the client supports multiple.

Examples:

Via global configuration

Datastar.configure do |config|
  config.compression = true                            # [:br, :gzip] with default options
  config.compression = [:br, :gzip]                    # preferred = first in list
  config.compression = [[:br, { quality: 5 }], :gzip]  # per-encoder options
end

Per-request negotiation (used internally by Dispatcher)

compressor = Datastar.config.compression.negotiate(request)
compressor.prepare_response(response)
socket = compressor.wrap_socket(raw_socket)

Constant Summary collapse

ACCEPT_ENCODING =
'HTTP_ACCEPT_ENCODING'
BLANK_HASH =
{}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(compressors) ⇒ CompressionConfig

Returns a new instance of CompressionConfig.

Parameters:



101
102
103
104
# File 'lib/datastar/compression_config.rb', line 101

def initialize(compressors)
  @compressors = compressors.freeze
  freeze
end

Class Method Details

.build(input) ⇒ CompressionConfig

Build a Datastar::CompressionConfig from various user-facing input forms.

Examples:

Disable compression

CompressionConfig.build(false)

Enable all supported encodings

CompressionConfig.build(true)

Gzip only, with custom level

CompressionConfig.build([[:gzip, { level: 1 }]])

Parameters:

  • input (Boolean, Array<Symbol, Array(Symbol, Hash)>, CompressionConfig)
    • false / nil — compression disabled (empty compressor list)

    • true — enable :br and :gzip with default options

    • Array<Symbol> — enable listed encodings with default options, e.g. [:gzip]

    • Array<Array(Symbol, Hash)> — enable with per-encoder options, e.g. [[:br, { quality: 5 }], :gzip]

    • CompressionConfig — returned as-is

Returns:

Raises:

  • (ArgumentError)

    if input is not a recognised form

  • (LoadError)

    if a requested encoder’s gem is not available (e.g. brotli)



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/datastar/compression_config.rb', line 59

def self.build(input)
  case input
  when CompressionConfig
    input
  when false, nil
    new([])
  when true
    new([build_compressor(:br), build_compressor(:gzip)])
  when Array
    compressors = input.map do |entry|
      case entry
      when Symbol
        build_compressor(entry)
      when Array
        name, options = entry
        build_compressor(name, options || BLANK_HASH)
      else
        raise ArgumentError, "Invalid compression entry: #{entry.inspect}. Expected Symbol or [Symbol, Hash]."
      end
    end
    new(compressors)
  else
    raise ArgumentError, "Invalid compression value: #{input.inspect}. Expected true, false, or Array."
  end
end

Instance Method Details

#enabled?Boolean

Whether any compressors are configured.

Examples:

CompressionConfig.build(false).enabled? # => false
CompressionConfig.build(true).enabled?  # => true

Returns:

  • (Boolean)


113
114
115
# File 'lib/datastar/compression_config.rb', line 113

def enabled?
  @compressors.any?
end

#negotiate(request) ⇒ Compressor::Gzip, ...

Negotiate compression with the client based on the Accept-Encoding header.

Iterates the configured compressors in order (first = preferred) and returns the first one whose encoding the client accepts. Returns Datastar::Compressor::NONE when compression is disabled, the header is absent, or no match is found.

No objects are created per-request — compressors are pre-built and reused.

Examples:

config = CompressionConfig.build([:gzip, :br])
compressor = config.negotiate(request)
compressor.prepare_response(response)
socket = compressor.wrap_socket(raw_socket)

Parameters:

  • request (Rack::Request)

Returns:



133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/datastar/compression_config.rb', line 133

def negotiate(request)
  return Compressor::NONE unless enabled?

  accepted = parse_accept_encoding(request.get_header(ACCEPT_ENCODING).to_s)
  return Compressor::NONE if accepted.empty?

  @compressors.each do |compressor|
    return compressor if accepted.include?(compressor.encoding)
  end

  Compressor::NONE
end