@@ -32,9 +32,15 @@ const CACHE_CONTROL_README: &str = "public,max-age=604800";
32
32
33
33
type StdPath = std:: path:: Path ;
34
34
35
+ #[ derive( Debug ) ]
36
+ pub struct StorageConfig {
37
+ backend : StorageBackend ,
38
+ cdn_prefix : Option < String > ,
39
+ }
40
+
35
41
#[ derive( Debug ) ]
36
42
#[ allow( clippy:: large_enum_variant) ]
37
- pub enum StorageConfig {
43
+ pub enum StorageBackend {
38
44
S3 { default : S3Config , index : S3Config } ,
39
45
LocalFileSystem { path : PathBuf } ,
40
46
InMemory ,
@@ -46,12 +52,14 @@ pub struct S3Config {
46
52
region : Option < String > ,
47
53
access_key : String ,
48
54
secret_key : SecretString ,
49
- cdn_prefix : Option < String > ,
50
55
}
51
56
52
57
impl StorageConfig {
53
58
pub fn in_memory ( ) -> Self {
54
- Self :: InMemory
59
+ Self {
60
+ backend : StorageBackend :: InMemory ,
61
+ cdn_prefix : None ,
62
+ }
55
63
}
56
64
57
65
pub fn from_environment ( ) -> Self {
@@ -70,18 +78,21 @@ impl StorageConfig {
70
78
region,
71
79
access_key : access_key. clone ( ) ,
72
80
secret_key : secret_key. clone ( ) ,
73
- cdn_prefix,
74
81
} ;
75
82
76
83
let index = S3Config {
77
84
bucket : index_bucket,
78
85
region : index_region,
79
86
access_key,
80
87
secret_key,
81
- cdn_prefix : None ,
82
88
} ;
83
89
84
- return Self :: S3 { default, index } ;
90
+ let backend = StorageBackend :: S3 { default, index } ;
91
+
92
+ return Self {
93
+ backend,
94
+ cdn_prefix,
95
+ } ;
85
96
}
86
97
87
98
let current_dir = std:: env:: current_dir ( )
@@ -90,16 +101,22 @@ impl StorageConfig {
90
101
91
102
let path = current_dir. join ( "local_uploads" ) ;
92
103
93
- Self :: LocalFileSystem { path }
104
+ let backend = StorageBackend :: LocalFileSystem { path } ;
105
+
106
+ Self {
107
+ backend,
108
+ cdn_prefix : None ,
109
+ }
94
110
}
95
111
}
96
112
97
113
pub struct Storage {
114
+ cdn_prefix : Option < String > ,
115
+
98
116
store : Box < dyn ObjectStore > ,
99
117
crate_upload_store : Box < dyn ObjectStore > ,
100
118
readme_upload_store : Box < dyn ObjectStore > ,
101
119
db_dump_upload_store : Box < dyn ObjectStore > ,
102
- cdn_prefix : String ,
103
120
104
121
index_store : Box < dyn ObjectStore > ,
105
122
index_upload_store : Box < dyn ObjectStore > ,
@@ -111,8 +128,10 @@ impl Storage {
111
128
}
112
129
113
130
pub fn from_config ( config : & StorageConfig ) -> Self {
114
- match config {
115
- StorageConfig :: S3 { default, index } => {
131
+ let cdn_prefix = config. cdn_prefix . clone ( ) ;
132
+
133
+ match & config. backend {
134
+ StorageBackend :: S3 { default, index } => {
116
135
let options = ClientOptions :: default ( ) ;
117
136
let store = build_s3 ( default, options) ;
118
137
@@ -126,20 +145,16 @@ impl Storage {
126
145
ClientOptions :: default ( ) . with_default_content_type ( CONTENT_TYPE_DB_DUMP ) ;
127
146
let db_dump_upload_store = build_s3 ( default, options) ;
128
147
129
- let cdn_prefix = match default. cdn_prefix . as_ref ( ) {
130
- None => panic ! ( "Missing S3_CDN environment variable" ) ,
131
- Some ( cdn_prefix) if !cdn_prefix. starts_with ( "https://" ) => {
132
- format ! ( "https://{cdn_prefix}" )
133
- }
134
- Some ( cdn_prefix) => cdn_prefix. clone ( ) ,
135
- } ;
136
-
137
148
let options = ClientOptions :: default ( ) ;
138
149
let index_store = build_s3 ( index, options) ;
139
150
140
151
let options = client_options ( CONTENT_TYPE_INDEX , CACHE_CONTROL_INDEX ) ;
141
152
let index_upload_store = build_s3 ( index, options) ;
142
153
154
+ if cdn_prefix. is_none ( ) {
155
+ panic ! ( "Missing S3_CDN environment variable" ) ;
156
+ }
157
+
143
158
Self {
144
159
store : Box :: new ( store) ,
145
160
crate_upload_store : Box :: new ( crate_upload_store) ,
@@ -151,7 +166,7 @@ impl Storage {
151
166
}
152
167
}
153
168
154
- StorageConfig :: LocalFileSystem { path } => {
169
+ StorageBackend :: LocalFileSystem { path } => {
155
170
warn ! ( ?path, "Using local file system for file storage" ) ;
156
171
157
172
let index_path = path. join ( "index" ) ;
@@ -176,13 +191,13 @@ impl Storage {
176
191
crate_upload_store : Box :: new ( store. clone ( ) ) ,
177
192
readme_upload_store : Box :: new ( store. clone ( ) ) ,
178
193
db_dump_upload_store : Box :: new ( store) ,
179
- cdn_prefix : "/" . into ( ) ,
194
+ cdn_prefix,
180
195
index_store : Box :: new ( index_store. clone ( ) ) ,
181
196
index_upload_store : Box :: new ( index_store) ,
182
197
}
183
198
}
184
199
185
- StorageConfig :: InMemory => {
200
+ StorageBackend :: InMemory => {
186
201
warn ! ( "Using in-memory file storage" ) ;
187
202
let store = ArcStore :: new ( InMemory :: new ( ) ) ;
188
203
@@ -191,7 +206,7 @@ impl Storage {
191
206
crate_upload_store : Box :: new ( store. clone ( ) ) ,
192
207
readme_upload_store : Box :: new ( store. clone ( ) ) ,
193
208
db_dump_upload_store : Box :: new ( store. clone ( ) ) ,
194
- cdn_prefix : "/" . into ( ) ,
209
+ cdn_prefix,
195
210
index_store : Box :: new ( PrefixStore :: new ( store. clone ( ) , "index" ) ) ,
196
211
index_upload_store : Box :: new ( PrefixStore :: new ( store, "index" ) ) ,
197
212
}
@@ -216,7 +231,13 @@ impl Storage {
216
231
}
217
232
218
233
fn with_cdn_prefix ( & self , path : & Path ) -> String {
219
- format ! ( "{}{}" , self . cdn_prefix, path)
234
+ match self . cdn_prefix . as_ref ( ) {
235
+ Some ( cdn_prefix) if !cdn_prefix. starts_with ( "https://" ) => {
236
+ format ! ( "https://{cdn_prefix}/{path}" )
237
+ }
238
+ Some ( cdn_prefix) => format ! ( "{cdn_prefix}/{path}" ) ,
239
+ None => format ! ( "/{path}" ) ,
240
+ }
220
241
}
221
242
222
243
#[ instrument( skip( self ) ) ]
0 commit comments