Module: ScreenshotScout::Internal::Serializer

Defined in:
lib/screenshotscout/internal/serializer.rb

Overview

Converts CaptureOptions into the API's exact ordered wire representation.

Constant Summary collapse

WIRE_NAMES =
{
  format: "format",
  response_type: "response_type",
  country: "country",
  proxy: "proxy",
  geolocation_latitude: "geolocation_latitude",
  geolocation_longitude: "geolocation_longitude",
  geolocation_accuracy: "geolocation_accuracy",
  cookies: "cookies",
  headers: "headers",
  timeout: "timeout",
  wait_until: "wait_until",
  navigation_timeout: "navigation_timeout",
  delay: "delay",
  device: "device",
  device_viewport_width: "device_viewport_width",
  device_viewport_height: "device_viewport_height",
  device_scale_factor: "device_scale_factor",
  device_is_mobile: "device_is_mobile",
  device_has_touch: "device_has_touch",
  device_user_agent: "device_user_agent",
  timezone: "timezone",
  media_type: "media_type",
  color_scheme: "color_scheme",
  reduced_motion: "reduced_motion",
  full_page: "full_page",
  full_page_pre_scroll: "full_page_pre_scroll",
  full_page_pre_scroll_step: "full_page_pre_scroll_step",
  full_page_pre_scroll_step_delay: "full_page_pre_scroll_step_delay",
  full_page_max_height: "full_page_max_height",
  block_cookie_banners: "block_cookie_banners",
  block_ads: "block_ads",
  block_chat_widgets: "block_chat_widgets",
  hide_selectors: "hide_selectors",
  click_selectors: "click_selectors",
  click_all_selectors: "click_all_selectors",
  inject_css: "inject_css",
  inject_js: "inject_js",
  bypass_csp: "bypass_csp",
  selector: "selector",
  clip_x: "clip_x",
  clip_y: "clip_y",
  clip_width: "clip_width",
  clip_height: "clip_height",
  image_width: "image_width",
  image_height: "image_height",
  image_mode: "image_mode",
  image_anchor: "image_anchor",
  image_allow_upscale: "image_allow_upscale",
  image_background: "image_background",
  image_quality: "image_quality",
  pdf_paper_format: "pdf_paper_format",
  pdf_landscape: "pdf_landscape",
  pdf_print_background: "pdf_print_background",
  pdf_margin: "pdf_margin",
  pdf_margin_top: "pdf_margin_top",
  pdf_margin_right: "pdf_margin_right",
  pdf_margin_bottom: "pdf_margin_bottom",
  pdf_margin_left: "pdf_margin_left",
  pdf_scale: "pdf_scale",
  cache: "cache",
  cache_ttl: "cache_ttl",
  cache_key: "cache_key",
  storage_mode: "storage_mode",
  storage_endpoint: "storage_endpoint",
  storage_bucket: "storage_bucket",
  storage_region: "storage_region",
  storage_object_key: "storage_object_key"
}.freeze
REPEATED_OPTIONS =
%i[
  cookies headers hide_selectors click_selectors click_all_selectors inject_css inject_js
].freeze

Class Method Summary collapse

Class Method Details

.build_canonical_query(pairs, access_key) ⇒ Object



112
113
114
115
116
117
118
119
120
121
# File 'lib/screenshotscout/internal/serializer.rb', line 112

def build_canonical_query(pairs, access_key)
  indexed = (pairs + [WirePair.new(name: "access_key", value: access_key)]).each_with_index.map do |pair, index|
    [pair, index]
  end
  indexed.sort! do |(left, left_index), (right, right_index)|
    comparison = left.name <=> right.name
    comparison.zero? ? left_index <=> right_index : comparison
  end
  encode_query(indexed.map(&:first))
end

.encode_query(pairs) ⇒ Object



123
124
125
# File 'lib/screenshotscout/internal/serializer.rb', line 123

def encode_query(pairs)
  pairs.map { |pair| "#{form_encode(pair.name)}=#{form_encode(pair.value)}" }.join("&")
end

.serialize(target_url, options) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/screenshotscout/internal/serializer.rb', line 86

def serialize(target_url, options)
  url = string_value(target_url, :url, target: true)
  unless options.nil? || options.is_a?(CaptureOptions)
    raise SerializationError, "Capture options must be a ScreenshotScout::CaptureOptions instance when provided."
  end

  pairs = [WirePair.new(name: "url", value: url)]
  body = { "url" => url }
  WIRE_NAMES.each do |property, wire_name|
    value = options&.public_send(property)
    next if value.nil?

    if REPEATED_OPTIONS.include?(property)
      append_repeated(pairs, body, property, wire_name, value)
    else
      append_scalar(pairs, body, property, wire_name, value)
    end
  end

  SerializedCaptureOptions.new(pairs: pairs.freeze, body: body.freeze)
rescue Error
  raise
rescue StandardError => e
  raise SerializationError.new("Capture options could not be serialized."), cause: e
end