Skip to main content

aws_lambda_events/event/s3/
object_lambda.rs

1#[cfg(feature = "builders")]
2use bon::Builder;
3use http::HeaderMap;
4use serde::{de::DeserializeOwned, Deserialize, Serialize};
5use serde_json::Value;
6use std::collections::HashMap;
7
8use crate::custom_serde::{deserialize_headers, serialize_headers};
9
10/// `S3ObjectLambdaEvent` contains data coming from S3 object lambdas
11/// See: <https://docs.aws.amazon.com/AmazonS3/latest/userguide/olap-writing-lambda.html>
12#[non_exhaustive]
13#[cfg_attr(feature = "builders", derive(Builder))]
14#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
15#[serde(rename_all = "camelCase")]
16pub struct S3ObjectLambdaEvent<P = Value>
17where
18    P: DeserializeOwned,
19    P: Serialize,
20{
21    pub x_amz_request_id: String,
22    pub get_object_context: Option<GetObjectContext>,
23    pub head_object_context: Option<HeadObjectContext>,
24    pub list_objects_context: Option<ListObjectsContext>,
25    pub list_objects_v2_context: Option<ListObjectsV2Context>,
26    #[serde(default, bound = "")]
27    pub configuration: Configuration<P>,
28    pub user_request: UserRequest,
29    pub user_identity: UserIdentity,
30    pub protocol_version: String,
31    /// Catchall to catch any additional fields that were present but not explicitly defined by this struct.
32    /// Enabled with Cargo feature `catch-all-fields`.
33    /// If `catch-all-fields` is disabled, any additional fields that are present will be ignored.
34    #[cfg(feature = "catch-all-fields")]
35    #[cfg_attr(docsrs, doc(cfg(feature = "catch-all-fields")))]
36    #[serde(flatten)]
37    #[cfg_attr(feature = "builders", builder(default))]
38    pub other: serde_json::Map<String, Value>,
39}
40
41/// `GetObjectContext` contains the input and output details
42/// for connections to Amazon S3 and S3 Object Lambda
43#[non_exhaustive]
44#[cfg_attr(feature = "builders", derive(Builder))]
45#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
46#[serde(rename_all = "camelCase")]
47pub struct GetObjectContext {
48    pub input_s3_url: String,
49    pub output_route: String,
50    pub output_token: String,
51    /// Catchall to catch any additional fields that were present but not explicitly defined by this struct.
52    /// Enabled with Cargo feature `catch-all-fields`.
53    /// If `catch-all-fields` is disabled, any additional fields that are present will be ignored.
54    #[cfg(feature = "catch-all-fields")]
55    #[cfg_attr(docsrs, doc(cfg(feature = "catch-all-fields")))]
56    #[serde(flatten)]
57    #[cfg_attr(feature = "builders", builder(default))]
58    pub other: serde_json::Map<String, Value>,
59}
60
61/// `HeadObjectContext`
62/// for connections to Amazon S3 and S3 Object Lambda
63#[non_exhaustive]
64#[cfg_attr(feature = "builders", derive(Builder))]
65#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
66#[serde(rename_all = "camelCase")]
67pub struct HeadObjectContext {
68    pub input_s3_url: String,
69    /// Catchall to catch any additional fields that were present but not explicitly defined by this struct.
70    /// Enabled with Cargo feature `catch-all-fields`.
71    /// If `catch-all-fields` is disabled, any additional fields that are present will be ignored.
72    #[cfg(feature = "catch-all-fields")]
73    #[cfg_attr(docsrs, doc(cfg(feature = "catch-all-fields")))]
74    #[serde(flatten)]
75    #[cfg_attr(feature = "builders", builder(default))]
76    pub other: serde_json::Map<String, Value>,
77}
78
79/// `ListObjectsContext`
80/// for connections to Amazon S3 and S3 Object Lambda
81#[non_exhaustive]
82#[cfg_attr(feature = "builders", derive(Builder))]
83#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
84#[serde(rename_all = "camelCase")]
85pub struct ListObjectsContext {
86    pub input_s3_url: String,
87    /// Catchall to catch any additional fields that were present but not explicitly defined by this struct.
88    /// Enabled with Cargo feature `catch-all-fields`.
89    /// If `catch-all-fields` is disabled, any additional fields that are present will be ignored.
90    #[cfg(feature = "catch-all-fields")]
91    #[cfg_attr(docsrs, doc(cfg(feature = "catch-all-fields")))]
92    #[serde(flatten)]
93    #[cfg_attr(feature = "builders", builder(default))]
94    pub other: serde_json::Map<String, Value>,
95}
96
97/// `ListObjectsV2Context`
98/// for connections to Amazon S3 and S3 Object Lambda
99#[non_exhaustive]
100#[cfg_attr(feature = "builders", derive(Builder))]
101#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
102#[serde(rename_all = "camelCase")]
103pub struct ListObjectsV2Context {
104    pub input_s3_url: String,
105    /// Catchall to catch any additional fields that were present but not explicitly defined by this struct.
106    /// Enabled with Cargo feature `catch-all-fields`.
107    /// If `catch-all-fields` is disabled, any additional fields that are present will be ignored.
108    #[cfg(feature = "catch-all-fields")]
109    #[cfg_attr(docsrs, doc(cfg(feature = "catch-all-fields")))]
110    #[serde(flatten)]
111    #[cfg_attr(feature = "builders", builder(default))]
112    pub other: serde_json::Map<String, Value>,
113}
114
115/// `Configuration` contains information about the Object Lambda access point
116#[non_exhaustive]
117#[cfg_attr(feature = "builders", derive(Builder))]
118#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
119#[serde(rename_all = "camelCase")]
120pub struct Configuration<P = Value>
121where
122    P: DeserializeOwned,
123    P: Serialize,
124{
125    pub access_point_arn: String,
126    pub supporting_access_point_arn: String,
127    #[serde(default, bound = "")]
128    pub payload: P,
129    /// Catchall to catch any additional fields that were present but not explicitly defined by this struct.
130    /// Enabled with Cargo feature `catch-all-fields`.
131    /// If `catch-all-fields` is disabled, any additional fields that are present will be ignored.
132    #[cfg(feature = "catch-all-fields")]
133    #[cfg_attr(docsrs, doc(cfg(feature = "catch-all-fields")))]
134    #[serde(flatten)]
135    #[cfg_attr(feature = "builders", builder(default))]
136    pub other: serde_json::Map<String, Value>,
137}
138
139/// `UserRequest` contains information about the original call to S3 Object Lambda
140#[non_exhaustive]
141#[cfg_attr(feature = "builders", derive(Builder))]
142#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
143#[serde(rename_all = "camelCase")]
144pub struct UserRequest {
145    pub url: String,
146    #[serde(deserialize_with = "deserialize_headers", default)]
147    #[serde(serialize_with = "serialize_headers")]
148    pub headers: HeaderMap,
149    /// Catchall to catch any additional fields that were present but not explicitly defined by this struct.
150    /// Enabled with Cargo feature `catch-all-fields`.
151    /// If `catch-all-fields` is disabled, any additional fields that are present will be ignored.
152    #[cfg(feature = "catch-all-fields")]
153    #[cfg_attr(docsrs, doc(cfg(feature = "catch-all-fields")))]
154    #[serde(flatten)]
155    #[cfg_attr(feature = "builders", builder(default))]
156    pub other: serde_json::Map<String, Value>,
157}
158
159/// `UserIdentity` contains details about the identity that made the call to S3 Object Lambda
160#[non_exhaustive]
161#[cfg_attr(feature = "builders", derive(Builder))]
162#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
163#[serde(rename_all = "camelCase")]
164pub struct UserIdentity {
165    pub r#type: String,
166    pub principal_id: String,
167    pub arn: String,
168    pub account_id: String,
169    pub access_key_id: String,
170    pub session_context: Option<SessionContext>,
171    /// Catchall to catch any additional fields that were present but not explicitly defined by this struct.
172    /// Enabled with Cargo feature `catch-all-fields`.
173    /// If `catch-all-fields` is disabled, any additional fields that are present will be ignored.
174    #[cfg(feature = "catch-all-fields")]
175    #[cfg_attr(docsrs, doc(cfg(feature = "catch-all-fields")))]
176    #[serde(flatten)]
177    #[cfg_attr(feature = "builders", builder(default))]
178    pub other: serde_json::Map<String, Value>,
179}
180
181#[non_exhaustive]
182#[cfg_attr(feature = "builders", derive(Builder))]
183#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
184#[serde(rename_all = "camelCase")]
185pub struct SessionContext {
186    pub attributes: HashMap<String, String>,
187    #[serde(default)]
188    pub session_issuer: Option<SessionIssuer>,
189    /// Catchall to catch any additional fields that were present but not explicitly defined by this struct.
190    /// Enabled with Cargo feature `catch-all-fields`.
191    /// If `catch-all-fields` is disabled, any additional fields that are present will be ignored.
192    #[cfg(feature = "catch-all-fields")]
193    #[cfg_attr(docsrs, doc(cfg(feature = "catch-all-fields")))]
194    #[serde(flatten)]
195    #[cfg_attr(feature = "builders", builder(default))]
196    pub other: serde_json::Map<String, Value>,
197}
198
199#[non_exhaustive]
200#[cfg_attr(feature = "builders", derive(Builder))]
201#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
202#[serde(rename_all = "camelCase")]
203pub struct SessionIssuer {
204    pub r#type: String,
205    pub principal_id: String,
206    pub arn: String,
207    pub account_id: String,
208    pub user_name: String,
209    /// Catchall to catch any additional fields that were present but not explicitly defined by this struct.
210    /// Enabled with Cargo feature `catch-all-fields`.
211    /// If `catch-all-fields` is disabled, any additional fields that are present will be ignored.
212    #[cfg(feature = "catch-all-fields")]
213    #[cfg_attr(docsrs, doc(cfg(feature = "catch-all-fields")))]
214    #[serde(flatten)]
215    #[cfg_attr(feature = "builders", builder(default))]
216    pub other: serde_json::Map<String, Value>,
217}
218
219#[cfg(test)]
220mod test {
221    use super::*;
222
223    #[test]
224    #[cfg(feature = "s3")]
225    fn example_object_lambda_event_get_object_assumed_role() {
226        let data = include_bytes!("../../fixtures/example-s3-object-lambda-event-get-object-assumed-role.json");
227        let parsed: S3ObjectLambdaEvent = serde_json::from_slice(data).unwrap();
228        let output: String = serde_json::to_string(&parsed).unwrap();
229        let reparsed: S3ObjectLambdaEvent = serde_json::from_slice(output.as_bytes()).unwrap();
230        assert_eq!(parsed, reparsed);
231    }
232
233    #[test]
234    #[cfg(feature = "s3")]
235    fn example_object_lambda_event_get_object_iam() {
236        let data = include_bytes!("../../fixtures/example-s3-object-lambda-event-get-object-iam.json");
237        let parsed: S3ObjectLambdaEvent = serde_json::from_slice(data).unwrap();
238        let output: String = serde_json::to_string(&parsed).unwrap();
239        let reparsed: S3ObjectLambdaEvent = serde_json::from_slice(output.as_bytes()).unwrap();
240        assert_eq!(parsed, reparsed);
241    }
242
243    #[test]
244    #[cfg(feature = "s3")]
245    fn example_object_lambda_event_head_object_iam() {
246        let data = include_bytes!("../../fixtures/example-s3-object-lambda-event-head-object-iam.json");
247        let parsed: S3ObjectLambdaEvent = serde_json::from_slice(data).unwrap();
248        let output: String = serde_json::to_string(&parsed).unwrap();
249        let reparsed: S3ObjectLambdaEvent = serde_json::from_slice(output.as_bytes()).unwrap();
250        assert_eq!(parsed, reparsed);
251    }
252
253    #[test]
254    #[cfg(feature = "s3")]
255    fn example_object_lambda_event_list_objects_iam() {
256        let data = include_bytes!("../../fixtures/example-s3-object-lambda-event-list-objects-iam.json");
257        let parsed: S3ObjectLambdaEvent = serde_json::from_slice(data).unwrap();
258        let output: String = serde_json::to_string(&parsed).unwrap();
259        let reparsed: S3ObjectLambdaEvent = serde_json::from_slice(output.as_bytes()).unwrap();
260        assert_eq!(parsed, reparsed);
261    }
262
263    #[test]
264    #[cfg(feature = "s3")]
265    fn example_object_lambda_event_list_objects_v2_iam() {
266        let data = include_bytes!("../../fixtures/example-s3-object-lambda-event-list-objects-v2-iam.json");
267        let parsed: S3ObjectLambdaEvent = serde_json::from_slice(data).unwrap();
268        let output: String = serde_json::to_string(&parsed).unwrap();
269        let reparsed: S3ObjectLambdaEvent = serde_json::from_slice(output.as_bytes()).unwrap();
270        assert_eq!(parsed, reparsed);
271    }
272}