Class: Oximg::Server::UrlBuilder

Inherits:
Object
  • Object
show all
Defined in:
lib/oximg/server/url_builder.rb

Overview

Builds URLs for the two routes an oximg server mounts. Nothing here talks to the server: a URL is pure arithmetic over the config, so a Rails view can emit thousands of them without leaving the process.

Validation mirrors the server's own bounds and fails closed on the same inputs. That is not defence — the server validates regardless — it is so a typo surfaces at the call site with a name, instead of as a 400 in an tag nobody is watching.

Constant Summary collapse

MAX_DIMENSION =

The server's cap on either axis (src/main.rs); 0 means "unconstrained" on the positional route only.

8192
FORMATS =

Tokens the positional route's @fmt suffix accepts. "jxl" is reserved by the server for a future encoder and answers 400, so it is not offered here.

%w[jpg jpeg png webp avif].freeze
OPTION_FORMATS =

The options route additionally understands format=auto, which means "negotiate, else the source's own format".

(FORMATS + %w[auto]).freeze
UNSAFE =

Everything outside RFC 3986's unreserved set gets percent-encoded. "/" stays literal so S3-style prefixes remain readable, and "@" so the format token survives; both are legal in a path segment, and the server signs the decoded form either way.

%r{[^A-Za-z0-9\-._~/@]}

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ UrlBuilder

Returns a new instance of UrlBuilder.



33
34
35
# File 'lib/oximg/server/url_builder.rb', line 33

def initialize(config)
  @config = config
end

Instance Method Details

#options(source, width: nil, height: nil, quality: nil, format: nil) ⇒ Object

The Cloudflare-Images-compatible options route, {prefix}/width=750,quality=80/{file}. Requires the server to have OXIMG_OPTIONS_PREFIX set and the same prefix configured here. Options are emitted in a fixed order: the signature covers the list verbatim, so a stable order is also a stable cache key.



61
62
63
64
65
66
67
68
69
# File 'lib/oximg/server/url_builder.rb', line 61

def options(source, width: nil, height: nil, quality: nil, format: nil)
  prefix = @config.options_prefix
  unless prefix
    raise ConfigurationError,
      "options_prefix is not configured (set it to the server's OXIMG_OPTIONS_PREFIX)"
  end

  build("#{prefix}/#{option_list(width, height, quality, format)}/", source_path(source))
end

#resize(source, width: 0, height: 0, format: nil) ⇒ Object

The positional route: /resize/{w}/{h}/{file}, where the source is fitted within the box and never enlarged. A zero axis is unconstrained — width: 750 alone is exactly what an srcset w descriptor means.

builder.resize("photos/a.jpg", width: 750)
builder.resize("photos/a.jpg", width: 750, height: 500, format: :webp)


44
45
46
47
48
49
50
51
52
53
54
# File 'lib/oximg/server/url_builder.rb', line 44

def resize(source, width: 0, height: 0, format: nil)
  w = dimension(width, "width")
  h = dimension(height, "height")
  if w.zero? && h.zero?
    raise ArgumentError, "at least one of width/height must be non-zero"
  end

  file = source_path(source)
  file = "#{file}@#{token(format, FORMATS, "format")}" unless format.nil?
  build("/resize/#{w}/#{h}/", file)
end