@@ -10,7 +10,7 @@ use crate::webserver::{
10
10
use anyhow:: { anyhow, Context } ;
11
11
use futures_util:: StreamExt ;
12
12
use mime_guess:: mime;
13
- use std:: { borrow:: Cow , ffi:: OsStr , str:: FromStr } ;
13
+ use std:: { borrow:: Cow , ffi:: OsStr , str:: FromStr , sync :: OnceLock } ;
14
14
15
15
super :: function_definition_macro:: sqlpage_functions! {
16
16
basic_auth_password( ( & RequestInfo ) ) ;
@@ -133,7 +133,7 @@ async fn fetch(
133
133
http_request : super :: http_fetch_request:: HttpFetchRequest < ' _ > ,
134
134
) -> anyhow:: Result < String > {
135
135
use awc:: http:: Method ;
136
- let client = make_http_client ( & request. app_state . config ) ;
136
+ let client = make_http_client ( & request. app_state . config ) ? ;
137
137
138
138
let method = if let Some ( method) = http_request. method {
139
139
Method :: from_str ( & method) ?
@@ -174,25 +174,34 @@ async fn fetch(
174
174
Ok ( response_str)
175
175
}
176
176
177
- fn make_http_client ( config : & crate :: app_config:: AppConfig ) -> awc:: Client {
177
+ static NATIVE_CERTS : OnceLock < std:: io:: Result < rustls:: RootCertStore > > = OnceLock :: new ( ) ;
178
+
179
+ fn make_http_client ( config : & crate :: app_config:: AppConfig ) -> anyhow:: Result < awc:: Client > {
178
180
let connector = if config. system_root_ca_certificates {
179
- let mut roots = rustls:: RootCertStore :: empty ( ) ;
180
- for cert in rustls_native_certs:: load_native_certs ( ) . expect ( "could not load platform certs" )
181
- {
182
- roots. add ( cert) . unwrap ( ) ;
183
- }
181
+ let roots = NATIVE_CERTS
182
+ . get_or_init ( || {
183
+ let certs = rustls_native_certs:: load_native_certs ( ) ?;
184
+ let mut roots = rustls:: RootCertStore :: empty ( ) ;
185
+ for cert in certs {
186
+ roots. add ( cert. clone ( ) ) . unwrap ( ) ;
187
+ }
188
+ Ok ( roots)
189
+ } )
190
+ . as_ref ( ) ?;
191
+
184
192
let tls_conf = rustls:: ClientConfig :: builder ( )
185
- . with_root_certificates ( roots)
193
+ . with_root_certificates ( roots. clone ( ) )
186
194
. with_no_client_auth ( ) ;
187
195
188
196
awc:: Connector :: new ( ) . rustls_0_22 ( std:: sync:: Arc :: new ( tls_conf) )
189
197
} else {
190
198
awc:: Connector :: new ( )
191
199
} ;
192
- awc:: Client :: builder ( )
200
+ let client = awc:: Client :: builder ( )
193
201
. connector ( connector)
194
202
. add_default_header ( ( awc:: http:: header:: USER_AGENT , env ! ( "CARGO_PKG_NAME" ) ) )
195
- . finish ( )
203
+ . finish ( ) ;
204
+ Ok ( client)
196
205
}
197
206
198
207
pub ( crate ) async fn hash_password ( password : Option < String > ) -> anyhow:: Result < Option < String > > {
0 commit comments