|
| 1 | +//! Platform-neutral Image Optimizer request metadata. |
| 2 | +//! |
| 3 | +//! These DTOs describe the closed image transformation set that Trusted Server |
| 4 | +//! attaches to an outbound asset proxy request. They intentionally avoid Fastly |
| 5 | +//! SDK types so the profile-table logic can stay in core while the Fastly |
| 6 | +//! adapter remains responsible for translating metadata into |
| 7 | +//! `fastly::image_optimizer::ImageOptimizerOptions`. |
| 8 | +//! |
| 9 | +//! Unsupported adapters should reject requests carrying this metadata rather |
| 10 | +//! than silently dropping transformations. |
| 11 | +
|
| 12 | +/// Platform-neutral Image Optimizer options for an upstream request. |
| 13 | +/// |
| 14 | +/// Core code stores only a closed transformation set here. The Fastly adapter is |
| 15 | +/// responsible for translating these values to SDK-specific |
| 16 | +/// `ImageOptimizerOptions`, while adapters without Image Optimizer support |
| 17 | +/// should reject requests carrying this metadata. |
| 18 | +#[derive(Debug, Clone, PartialEq, Eq)] |
| 19 | +pub struct PlatformImageOptimizerOptions { |
| 20 | + /// Image Optimizer processing region understood by the target adapter. |
| 21 | + pub region: String, |
| 22 | + /// Whether non-IO query parameters should be preserved on the origin request. |
| 23 | + pub preserve_query_string_on_origin_request: bool, |
| 24 | + /// Transformation parameters to apply. |
| 25 | + pub params: PlatformImageOptimizerParams, |
| 26 | +} |
| 27 | + |
| 28 | +impl PlatformImageOptimizerOptions { |
| 29 | + /// Create Image Optimizer options for the given region and params. |
| 30 | + #[must_use] |
| 31 | + pub fn new(region: impl Into<String>, params: PlatformImageOptimizerParams) -> Self { |
| 32 | + Self { |
| 33 | + region: region.into(), |
| 34 | + preserve_query_string_on_origin_request: false, |
| 35 | + params, |
| 36 | + } |
| 37 | + } |
| 38 | + |
| 39 | + /// Preserve non-IO query parameters on the origin request. |
| 40 | + /// |
| 41 | + /// Asset routes with profile-table IO reject arbitrary query preservation by |
| 42 | + /// default because client query parameters can otherwise become additional |
| 43 | + /// Image Optimizer inputs. |
| 44 | + #[must_use] |
| 45 | + pub fn with_preserve_query_string_on_origin_request(mut self, preserve: bool) -> Self { |
| 46 | + self.preserve_query_string_on_origin_request = preserve; |
| 47 | + self |
| 48 | + } |
| 49 | +} |
| 50 | + |
| 51 | +/// Platform-neutral subset of image transformation parameters. |
| 52 | +/// |
| 53 | +/// This intentionally mirrors only the parameters accepted by asset-route |
| 54 | +/// profile tables: format, quality, resize filter, dimensions, and crop. Client |
| 55 | +/// query strings are converted into this closed set before the request reaches a |
| 56 | +/// platform adapter. |
| 57 | +#[derive(Debug, Default, Clone, PartialEq, Eq)] |
| 58 | +pub struct PlatformImageOptimizerParams { |
| 59 | + /// Output format such as `auto` or `webp`. |
| 60 | + pub format: Option<String>, |
| 61 | + /// Output quality from 0 to 100. |
| 62 | + pub quality: Option<u32>, |
| 63 | + /// Resize filter such as `bicubic`. |
| 64 | + pub resize_filter: Option<String>, |
| 65 | + /// Output width in pixels. |
| 66 | + pub width: Option<u32>, |
| 67 | + /// Output height in pixels. |
| 68 | + pub height: Option<u32>, |
| 69 | + /// Crop transformation. |
| 70 | + pub crop: Option<PlatformImageOptimizerCrop>, |
| 71 | +} |
| 72 | + |
| 73 | +impl PlatformImageOptimizerParams { |
| 74 | + /// Merge another param set into this one, with `other` taking precedence. |
| 75 | + pub fn merge_from(&mut self, other: Self) { |
| 76 | + if other.format.is_some() { |
| 77 | + self.format = other.format; |
| 78 | + } |
| 79 | + if other.quality.is_some() { |
| 80 | + self.quality = other.quality; |
| 81 | + } |
| 82 | + if other.resize_filter.is_some() { |
| 83 | + self.resize_filter = other.resize_filter; |
| 84 | + } |
| 85 | + if other.width.is_some() { |
| 86 | + self.width = other.width; |
| 87 | + } |
| 88 | + if other.height.is_some() { |
| 89 | + self.height = other.height; |
| 90 | + } |
| 91 | + if other.crop.is_some() { |
| 92 | + self.crop = other.crop; |
| 93 | + } |
| 94 | + } |
| 95 | +} |
| 96 | + |
| 97 | +/// Platform-neutral crop transformation. |
| 98 | +#[derive(Debug, Clone, PartialEq, Eq)] |
| 99 | +pub struct PlatformImageOptimizerCrop { |
| 100 | + /// Aspect-ratio width component. |
| 101 | + pub width: u32, |
| 102 | + /// Aspect-ratio height component. |
| 103 | + pub height: u32, |
| 104 | + /// Optional crop focus mode. |
| 105 | + pub mode: Option<PlatformImageOptimizerCropMode>, |
| 106 | + /// Optional x-axis crop offset bucket. |
| 107 | + pub offset_x: Option<u32>, |
| 108 | + /// Optional y-axis crop offset bucket. |
| 109 | + pub offset_y: Option<u32>, |
| 110 | +} |
| 111 | + |
| 112 | +impl PlatformImageOptimizerCrop { |
| 113 | + /// Create a bare aspect-ratio crop. |
| 114 | + #[must_use] |
| 115 | + pub fn aspect_ratio(width: u32, height: u32) -> Self { |
| 116 | + Self { |
| 117 | + width, |
| 118 | + height, |
| 119 | + mode: None, |
| 120 | + offset_x: None, |
| 121 | + offset_y: None, |
| 122 | + } |
| 123 | + } |
| 124 | + |
| 125 | + /// Returns true when no focus mode or explicit offsets have been applied. |
| 126 | + #[must_use] |
| 127 | + pub fn is_bare_aspect_ratio(&self) -> bool { |
| 128 | + self.mode.is_none() && self.offset_x.is_none() && self.offset_y.is_none() |
| 129 | + } |
| 130 | +} |
| 131 | + |
| 132 | +/// Platform-neutral crop focus mode. |
| 133 | +#[derive(Debug, Clone, Copy, PartialEq, Eq)] |
| 134 | +pub enum PlatformImageOptimizerCropMode { |
| 135 | + /// Use Fastly IO smart crop mode. |
| 136 | + Smart, |
| 137 | +} |
0 commit comments