axum_static_s3/
builder.rs

1use std::sync::Arc;
2
3use aws_sdk_s3::Client as S3Client;
4use aws_config::SdkConfig as AwsSdkConfig;
5
6use crate::S3Origin;
7
8use super::S3OriginInner;
9
10
11pub struct S3OriginBuilder {
12    bucket: Option<String>,
13    bucket_prefix: Option<String>,
14    s3_client: Option<S3Client>,
15    aws_sdk_config: Option<AwsSdkConfig>,
16    prune_path: usize,
17    max_size: Option<i64>,
18}
19
20
21impl S3OriginBuilder {
22    pub fn new() -> Self {
23        Self {
24            bucket: None,
25            bucket_prefix: None,
26            s3_client: None,
27            aws_sdk_config: None,
28            prune_path: 0,
29            max_size: None,
30        }
31    }
32
33    /// Set the bucket name.
34    /// 
35    /// This is required.
36    /// 
37    pub fn bucket(mut self, bucket: impl Into<String>) -> Self {
38        self.bucket = Some(bucket.into());
39        self
40    }
41
42    /// Set the bucket prefix.
43    /// 
44    /// This is optional, and defaults to an empty string.
45    /// 
46    pub fn prefix(mut self, prefix: impl Into<String>) -> Self {
47        self.bucket_prefix = Some(prefix.into());
48        self
49    }
50
51    /// Set the S3 client.
52    /// 
53    /// This is optional, and defaults to a new client created from the AWS SDK config.
54    /// 
55    pub fn client(mut self, client: S3Client) -> Self {
56        self.s3_client = Some(client);
57        self
58    }
59
60    /// Number of path components to remove from the request path.
61    /// 
62    /// This is useful for removing the bucket and prefix from the request path.
63    /// 
64    /// For example, if the request path is `/stage/my-app/static/deployment/index.html`,
65    /// and the prune_path is 3, then the search key will be `{bucket}/{bucket_prefix/}deployment/index.html`.
66    /// 
67    pub fn prune_path(mut self, prune_path: usize) -> Self {
68        self.prune_path = prune_path;
69        self
70    }
71
72    /// Set the AWS SDK config.
73    /// 
74    /// This is optional, and defaults to a new client created from the AWS SDK config.
75    /// If `client` is not provided, the AWS SDK config **must** be provided.
76    /// 
77    pub fn config(mut self, config: AwsSdkConfig) -> Self {
78        self.aws_sdk_config = Some(config);
79        self
80    }
81
82    /// Set the maximum size of the file to serve.
83    /// 
84    /// This is optional, and defaults to no maximum size.
85    /// If the origin returns a file larger than the maximum size, an HTTP 413 (Payload Too Large) is returned.
86    /// 
87    pub fn max_size(mut self, max_size: i64) -> Self {
88        self.max_size = Some(max_size);
89        self
90    }
91
92    /// Build the S3 origin.
93    /// 
94    /// This will return an error a required parameter is not provided.
95    /// 
96    pub fn build(self) -> Result<S3Origin, &'static str> {
97        let bucket = self.bucket.ok_or("bucket is required")?;
98        let bucket_prefix = self.bucket_prefix.unwrap_or_default();
99        
100        let s3_client = if let Some(client) = self.s3_client {
101            client
102        } else if let Some(config) = self.aws_sdk_config {
103            S3Client::new(&config)
104        } else {
105            return Err("either s3_client or aws_sdk_config must be provided");
106        };
107
108        Ok(S3Origin {
109            inner: Arc::new(S3OriginInner {
110                bucket,
111                bucket_prefix,
112                s3_client: Arc::new(s3_client),
113                prune_path: self.prune_path,
114                max_size: self.max_size,
115            })
116        })
117    }
118}
119impl Default for S3OriginBuilder {
120    fn default() -> Self {
121        Self::new()
122    }
123}