1#![forbid(unsafe_code)]
64#![warn(missing_docs, missing_debug_implementations)]
65#![doc(html_logo_url = "https://actix.rs/img/logo.png")]
66#![doc(html_favicon_url = "https://actix.rs/favicon.ico")]
67#![cfg_attr(docsrs, feature(doc_auto_cfg))]
68
69use std::{
70 env, fmt,
71 fs::File,
72 io::{Read as _, Write as _},
73 path::Path,
74 time::Duration,
75};
76
77use actix_http::{Request, Response};
78use actix_service::IntoServiceFactory;
79use actix_web::{
80 body::MessageBody,
81 dev::{AppConfig, ServiceFactory},
82 http::KeepAlive as ActixKeepAlive,
83 Error as WebError, HttpServer,
84};
85use serde::{de, Deserialize};
86
87#[macro_use]
88mod error;
89mod parse;
90mod settings;
91
92#[cfg(feature = "openssl")]
93pub use self::settings::Tls;
94pub use self::{
95 error::Error,
96 parse::Parse,
97 settings::{
98 ActixSettings, Address, Backlog, KeepAlive, MaxConnectionRate, MaxConnections, Mode,
99 NumWorkers, Timeout,
100 },
101};
102
103type AsResult<T> = std::result::Result<T, Error>;
105
106#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize)]
108#[serde(bound = "A: Deserialize<'de>")]
109pub struct BasicSettings<A> {
110 pub actix: ActixSettings,
112
113 pub application: A,
115}
116
117pub type Settings = BasicSettings<NoSettings>;
119
120#[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize)]
122#[non_exhaustive]
123pub struct NoSettings {}
124
125impl<A> BasicSettings<A>
126where
127 A: de::DeserializeOwned,
128{
129 pub(crate) const DEFAULT_TOML_TEMPLATE: &'static str = include_str!("./defaults.toml");
134
135 pub fn parse_toml<P>(filepath: P) -> AsResult<Self>
140 where
141 P: AsRef<Path>,
142 {
143 let filepath = filepath.as_ref();
144
145 if !filepath.exists() {
146 Self::write_toml_file(filepath)?;
147 }
148
149 let mut f = File::open(filepath)?;
150 let len_guess = f.metadata().map(|md| md.len()).unwrap_or(128);
151
152 let mut contents = String::with_capacity(len_guess as usize);
153 f.read_to_string(&mut contents)?;
154
155 Ok(toml::from_str::<Self>(&contents)?)
156 }
157
158 pub fn from_default_template() -> Self {
160 Self::from_template(Self::DEFAULT_TOML_TEMPLATE).unwrap()
161 }
162
163 pub fn from_template(template: &str) -> AsResult<Self> {
165 Ok(toml::from_str(template)?)
166 }
167
168 pub fn write_toml_file<P>(filepath: P) -> AsResult<()>
175 where
176 P: AsRef<Path>,
177 {
178 let filepath = filepath.as_ref();
179
180 if filepath.exists() {
181 return Err(Error::FileExists(filepath.to_path_buf()));
182 }
183
184 let mut file = File::create(filepath)?;
185 file.write_all(Self::DEFAULT_TOML_TEMPLATE.trim().as_bytes())?;
186 file.flush()?;
187
188 Ok(())
189 }
190
191 pub fn override_field<F, V>(field: &mut F, value: V) -> AsResult<()>
206 where
207 F: Parse,
208 V: AsRef<str>,
209 {
210 *field = F::parse(value.as_ref())?;
211 Ok(())
212 }
213
214 pub fn override_field_with_env_var<F, N>(field: &mut F, var_name: N) -> AsResult<()>
231 where
232 F: Parse,
233 N: AsRef<str>,
234 {
235 match env::var(var_name.as_ref()) {
236 Err(env::VarError::NotPresent) => Ok(()),
237 Err(var_error) => Err(Error::from(var_error)),
238 Ok(value) => Self::override_field(field, value),
239 }
240 }
241}
242
243pub trait ApplySettings<S>: Sized {
245 #[deprecated = "Prefer `try_apply_settings()`."]
255 fn apply_settings(self, settings: &S) -> Self {
256 self.try_apply_settings(settings)
257 .expect("Could not apply settings")
258 }
259
260 fn try_apply_settings(self, settings: &S) -> AsResult<Self>;
266}
267
268impl<F, I, S, B> ApplySettings<ActixSettings> for HttpServer<F, I, S, B>
269where
270 F: Fn() -> I + Send + Clone + 'static,
271 I: IntoServiceFactory<S, Request>,
272 S: ServiceFactory<Request, Config = AppConfig> + 'static,
273 S::Error: Into<WebError> + 'static,
274 S::InitError: fmt::Debug,
275 S::Response: Into<Response<B>> + 'static,
276 S::Future: 'static,
277 B: MessageBody + 'static,
278{
279 fn apply_settings(self, settings: &ActixSettings) -> Self {
280 self.try_apply_settings(settings).unwrap()
281 }
282
283 fn try_apply_settings(mut self, settings: &ActixSettings) -> AsResult<Self> {
284 for Address { host, port } in &settings.hosts {
285 #[cfg(feature = "openssl")]
286 {
287 if settings.tls.enabled {
288 self = self.bind_openssl(
289 format!("{}:{}", host, port),
290 settings.tls.get_ssl_acceptor_builder()?,
291 )?;
292 } else {
293 self = self.bind(format!("{host}:{port}"))?;
294 }
295 }
296
297 #[cfg(not(feature = "openssl"))]
298 {
299 self = self.bind(format!("{host}:{port}"))?;
300 }
301 }
302
303 self = match settings.num_workers {
304 NumWorkers::Default => self,
305 NumWorkers::Manual(n) => self.workers(n),
306 };
307
308 self = match settings.backlog {
309 Backlog::Default => self,
310 Backlog::Manual(n) => self.backlog(n as u32),
311 };
312
313 self = match settings.max_connections {
314 MaxConnections::Default => self,
315 MaxConnections::Manual(n) => self.max_connections(n),
316 };
317
318 self = match settings.max_connection_rate {
319 MaxConnectionRate::Default => self,
320 MaxConnectionRate::Manual(n) => self.max_connection_rate(n),
321 };
322
323 self = match settings.keep_alive {
324 KeepAlive::Default => self,
325 KeepAlive::Disabled => self.keep_alive(ActixKeepAlive::Disabled),
326 KeepAlive::Os => self.keep_alive(ActixKeepAlive::Os),
327 KeepAlive::Seconds(n) => self.keep_alive(Duration::from_secs(n as u64)),
328 };
329
330 self = match settings.client_timeout {
331 Timeout::Default => self,
332 Timeout::Milliseconds(n) => {
333 self.client_request_timeout(Duration::from_millis(n as u64))
334 }
335 Timeout::Seconds(n) => self.client_request_timeout(Duration::from_secs(n as u64)),
336 };
337
338 self = match settings.client_shutdown {
339 Timeout::Default => self,
340 Timeout::Milliseconds(n) => {
341 self.client_disconnect_timeout(Duration::from_millis(n as u64))
342 }
343 Timeout::Seconds(n) => self.client_disconnect_timeout(Duration::from_secs(n as u64)),
344 };
345
346 self = match settings.shutdown_timeout {
347 Timeout::Default => self,
348 Timeout::Milliseconds(_) => self.shutdown_timeout(1),
349 Timeout::Seconds(n) => self.shutdown_timeout(n as u64),
350 };
351
352 Ok(self)
353 }
354}
355
356impl<F, I, S, B, A> ApplySettings<BasicSettings<A>> for HttpServer<F, I, S, B>
357where
358 F: Fn() -> I + Send + Clone + 'static,
359 I: IntoServiceFactory<S, Request>,
360 S: ServiceFactory<Request, Config = AppConfig> + 'static,
361 S::Error: Into<WebError> + 'static,
362 S::InitError: fmt::Debug,
363 S::Response: Into<Response<B>> + 'static,
364 S::Future: 'static,
365 B: MessageBody + 'static,
366 A: de::DeserializeOwned,
367{
368 fn apply_settings(self, settings: &BasicSettings<A>) -> Self {
369 self.try_apply_settings(&settings.actix).unwrap()
370 }
371
372 fn try_apply_settings(self, settings: &BasicSettings<A>) -> AsResult<Self> {
373 self.try_apply_settings(&settings.actix)
374 }
375}
376
377#[cfg(test)]
378mod tests {
379 use actix_web::App;
380
381 use super::*;
382
383 #[test]
384 fn apply_settings() {
385 let settings = Settings::parse_toml("Server.toml").unwrap();
386 let server = HttpServer::new(App::new).try_apply_settings(&settings);
387 assert!(server.is_ok());
388 }
389
390 #[test]
391 fn override_field_hosts() {
392 let mut settings = Settings::from_default_template();
393
394 assert_eq!(
395 settings.actix.hosts,
396 vec![Address {
397 host: "0.0.0.0".into(),
398 port: 9000
399 },]
400 );
401
402 Settings::override_field(
403 &mut settings.actix.hosts,
404 r#"[
405 ["0.0.0.0", 1234],
406 ["localhost", 2345]
407 ]"#,
408 )
409 .unwrap();
410
411 assert_eq!(
412 settings.actix.hosts,
413 vec![
414 Address {
415 host: "0.0.0.0".into(),
416 port: 1234
417 },
418 Address {
419 host: "localhost".into(),
420 port: 2345
421 },
422 ]
423 );
424 }
425
426 #[test]
427 fn override_field_with_env_var_hosts() {
428 let mut settings = Settings::from_default_template();
429
430 assert_eq!(
431 settings.actix.hosts,
432 vec![Address {
433 host: "0.0.0.0".into(),
434 port: 9000
435 },]
436 );
437
438 std::env::set_var(
439 "OVERRIDE__HOSTS",
440 r#"[
441 ["0.0.0.0", 1234],
442 ["localhost", 2345]
443 ]"#,
444 );
445
446 Settings::override_field_with_env_var(&mut settings.actix.hosts, "OVERRIDE__HOSTS")
447 .unwrap();
448
449 assert_eq!(
450 settings.actix.hosts,
451 vec![
452 Address {
453 host: "0.0.0.0".into(),
454 port: 1234
455 },
456 Address {
457 host: "localhost".into(),
458 port: 2345
459 },
460 ]
461 );
462 }
463
464 #[test]
465 fn override_field_mode() {
466 let mut settings = Settings::from_default_template();
467 assert_eq!(settings.actix.mode, Mode::Development);
468 Settings::override_field(&mut settings.actix.mode, "production").unwrap();
469 assert_eq!(settings.actix.mode, Mode::Production);
470 }
471
472 #[test]
473 fn override_field_with_env_var_mode() {
474 let mut settings = Settings::from_default_template();
475 assert_eq!(settings.actix.mode, Mode::Development);
476 std::env::set_var("OVERRIDE__MODE", "production");
477 Settings::override_field_with_env_var(&mut settings.actix.mode, "OVERRIDE__MODE").unwrap();
478 assert_eq!(settings.actix.mode, Mode::Production);
479 }
480
481 #[test]
482 fn override_field_enable_compression() {
483 let mut settings = Settings::from_default_template();
484 assert!(settings.actix.enable_compression);
485 Settings::override_field(&mut settings.actix.enable_compression, "false").unwrap();
486 assert!(!settings.actix.enable_compression);
487 }
488
489 #[test]
490 fn override_field_with_env_var_enable_compression() {
491 let mut settings = Settings::from_default_template();
492 assert!(settings.actix.enable_compression);
493 std::env::set_var("OVERRIDE__ENABLE_COMPRESSION", "false");
494 Settings::override_field_with_env_var(
495 &mut settings.actix.enable_compression,
496 "OVERRIDE__ENABLE_COMPRESSION",
497 )
498 .unwrap();
499 assert!(!settings.actix.enable_compression);
500 }
501
502 #[test]
503 fn override_field_enable_log() {
504 let mut settings = Settings::from_default_template();
505 assert!(settings.actix.enable_log);
506 Settings::override_field(&mut settings.actix.enable_log, "false").unwrap();
507 assert!(!settings.actix.enable_log);
508 }
509
510 #[test]
511 fn override_field_with_env_var_enable_log() {
512 let mut settings = Settings::from_default_template();
513 assert!(settings.actix.enable_log);
514 std::env::set_var("OVERRIDE__ENABLE_LOG", "false");
515 Settings::override_field_with_env_var(
516 &mut settings.actix.enable_log,
517 "OVERRIDE__ENABLE_LOG",
518 )
519 .unwrap();
520 assert!(!settings.actix.enable_log);
521 }
522
523 #[test]
524 fn override_field_num_workers() {
525 let mut settings = Settings::from_default_template();
526 assert_eq!(settings.actix.num_workers, NumWorkers::Default);
527 Settings::override_field(&mut settings.actix.num_workers, "42").unwrap();
528 assert_eq!(settings.actix.num_workers, NumWorkers::Manual(42));
529 }
530
531 #[test]
532 fn override_field_with_env_var_num_workers() {
533 let mut settings = Settings::from_default_template();
534 assert_eq!(settings.actix.num_workers, NumWorkers::Default);
535 std::env::set_var("OVERRIDE__NUM_WORKERS", "42");
536 Settings::override_field_with_env_var(
537 &mut settings.actix.num_workers,
538 "OVERRIDE__NUM_WORKERS",
539 )
540 .unwrap();
541 assert_eq!(settings.actix.num_workers, NumWorkers::Manual(42));
542 }
543
544 #[test]
545 fn override_field_backlog() {
546 let mut settings = Settings::from_default_template();
547 assert_eq!(settings.actix.backlog, Backlog::Default);
548 Settings::override_field(&mut settings.actix.backlog, "42").unwrap();
549 assert_eq!(settings.actix.backlog, Backlog::Manual(42));
550 }
551
552 #[test]
553 fn override_field_with_env_var_backlog() {
554 let mut settings = Settings::from_default_template();
555 assert_eq!(settings.actix.backlog, Backlog::Default);
556 std::env::set_var("OVERRIDE__BACKLOG", "42");
557 Settings::override_field_with_env_var(&mut settings.actix.backlog, "OVERRIDE__BACKLOG")
558 .unwrap();
559 assert_eq!(settings.actix.backlog, Backlog::Manual(42));
560 }
561
562 #[test]
563 fn override_field_max_connections() {
564 let mut settings = Settings::from_default_template();
565 assert_eq!(settings.actix.max_connections, MaxConnections::Default);
566 Settings::override_field(&mut settings.actix.max_connections, "42").unwrap();
567 assert_eq!(settings.actix.max_connections, MaxConnections::Manual(42));
568 }
569
570 #[test]
571 fn override_field_with_env_var_max_connections() {
572 let mut settings = Settings::from_default_template();
573 assert_eq!(settings.actix.max_connections, MaxConnections::Default);
574 std::env::set_var("OVERRIDE__MAX_CONNECTIONS", "42");
575 Settings::override_field_with_env_var(
576 &mut settings.actix.max_connections,
577 "OVERRIDE__MAX_CONNECTIONS",
578 )
579 .unwrap();
580 assert_eq!(settings.actix.max_connections, MaxConnections::Manual(42));
581 }
582
583 #[test]
584 fn override_field_max_connection_rate() {
585 let mut settings = Settings::from_default_template();
586 assert_eq!(
587 settings.actix.max_connection_rate,
588 MaxConnectionRate::Default
589 );
590 Settings::override_field(&mut settings.actix.max_connection_rate, "42").unwrap();
591 assert_eq!(
592 settings.actix.max_connection_rate,
593 MaxConnectionRate::Manual(42)
594 );
595 }
596
597 #[test]
598 fn override_field_with_env_var_max_connection_rate() {
599 let mut settings = Settings::from_default_template();
600 assert_eq!(
601 settings.actix.max_connection_rate,
602 MaxConnectionRate::Default
603 );
604 std::env::set_var("OVERRIDE__MAX_CONNECTION_RATE", "42");
605 Settings::override_field_with_env_var(
606 &mut settings.actix.max_connection_rate,
607 "OVERRIDE__MAX_CONNECTION_RATE",
608 )
609 .unwrap();
610 assert_eq!(
611 settings.actix.max_connection_rate,
612 MaxConnectionRate::Manual(42)
613 );
614 }
615
616 #[test]
617 fn override_field_keep_alive() {
618 let mut settings = Settings::from_default_template();
619 assert_eq!(settings.actix.keep_alive, KeepAlive::Default);
620 Settings::override_field(&mut settings.actix.keep_alive, "42 seconds").unwrap();
621 assert_eq!(settings.actix.keep_alive, KeepAlive::Seconds(42));
622 }
623
624 #[test]
625 fn override_field_with_env_var_keep_alive() {
626 let mut settings = Settings::from_default_template();
627 assert_eq!(settings.actix.keep_alive, KeepAlive::Default);
628 std::env::set_var("OVERRIDE__KEEP_ALIVE", "42 seconds");
629 Settings::override_field_with_env_var(
630 &mut settings.actix.keep_alive,
631 "OVERRIDE__KEEP_ALIVE",
632 )
633 .unwrap();
634 assert_eq!(settings.actix.keep_alive, KeepAlive::Seconds(42));
635 }
636
637 #[test]
638 fn override_field_client_timeout() {
639 let mut settings = Settings::from_default_template();
640 assert_eq!(settings.actix.client_timeout, Timeout::Default);
641 Settings::override_field(&mut settings.actix.client_timeout, "42 seconds").unwrap();
642 assert_eq!(settings.actix.client_timeout, Timeout::Seconds(42));
643 }
644
645 #[test]
646 fn override_field_with_env_var_client_timeout() {
647 let mut settings = Settings::from_default_template();
648 assert_eq!(settings.actix.client_timeout, Timeout::Default);
649 std::env::set_var("OVERRIDE__CLIENT_TIMEOUT", "42 seconds");
650 Settings::override_field_with_env_var(
651 &mut settings.actix.client_timeout,
652 "OVERRIDE__CLIENT_TIMEOUT",
653 )
654 .unwrap();
655 assert_eq!(settings.actix.client_timeout, Timeout::Seconds(42));
656 }
657
658 #[test]
659 fn override_field_client_shutdown() {
660 let mut settings = Settings::from_default_template();
661 assert_eq!(settings.actix.client_shutdown, Timeout::Default);
662 Settings::override_field(&mut settings.actix.client_shutdown, "42 seconds").unwrap();
663 assert_eq!(settings.actix.client_shutdown, Timeout::Seconds(42));
664 }
665
666 #[test]
667 fn override_field_with_env_var_client_shutdown() {
668 let mut settings = Settings::from_default_template();
669 assert_eq!(settings.actix.client_shutdown, Timeout::Default);
670 std::env::set_var("OVERRIDE__CLIENT_SHUTDOWN", "42 seconds");
671 Settings::override_field_with_env_var(
672 &mut settings.actix.client_shutdown,
673 "OVERRIDE__CLIENT_SHUTDOWN",
674 )
675 .unwrap();
676 assert_eq!(settings.actix.client_shutdown, Timeout::Seconds(42));
677 }
678
679 #[test]
680 fn override_field_shutdown_timeout() {
681 let mut settings = Settings::from_default_template();
682 assert_eq!(settings.actix.shutdown_timeout, Timeout::Default);
683 Settings::override_field(&mut settings.actix.shutdown_timeout, "42 seconds").unwrap();
684 assert_eq!(settings.actix.shutdown_timeout, Timeout::Seconds(42));
685 }
686
687 #[test]
688 fn override_field_with_env_var_shutdown_timeout() {
689 let mut settings = Settings::from_default_template();
690 assert_eq!(settings.actix.shutdown_timeout, Timeout::Default);
691 std::env::set_var("OVERRIDE__SHUTDOWN_TIMEOUT", "42 seconds");
692 Settings::override_field_with_env_var(
693 &mut settings.actix.shutdown_timeout,
694 "OVERRIDE__SHUTDOWN_TIMEOUT",
695 )
696 .unwrap();
697 assert_eq!(settings.actix.shutdown_timeout, Timeout::Seconds(42));
698 }
699
700 #[cfg(feature = "openssl")]
701 #[test]
702 fn override_field_tls_enabled() {
703 let mut settings = Settings::from_default_template();
704 assert!(!settings.actix.tls.enabled);
705 Settings::override_field(&mut settings.actix.tls.enabled, "true").unwrap();
706 assert!(settings.actix.tls.enabled);
707 }
708
709 #[cfg(feature = "openssl")]
710 #[test]
711 fn override_field_with_env_var_tls_enabled() {
712 let mut settings = Settings::from_default_template();
713 assert!(!settings.actix.tls.enabled);
714 std::env::set_var("OVERRIDE__TLS_ENABLED", "true");
715 Settings::override_field_with_env_var(
716 &mut settings.actix.tls.enabled,
717 "OVERRIDE__TLS_ENABLED",
718 )
719 .unwrap();
720 assert!(settings.actix.tls.enabled);
721 }
722
723 #[cfg(feature = "openssl")]
724 #[test]
725 fn override_field_tls_certificate() {
726 let mut settings = Settings::from_default_template();
727 assert_eq!(
728 settings.actix.tls.certificate,
729 Path::new("path/to/cert/cert.pem")
730 );
731 Settings::override_field(
732 &mut settings.actix.tls.certificate,
733 "/overridden/path/to/cert/cert.pem",
734 )
735 .unwrap();
736 assert_eq!(
737 settings.actix.tls.certificate,
738 Path::new("/overridden/path/to/cert/cert.pem")
739 );
740 }
741
742 #[cfg(feature = "openssl")]
743 #[test]
744 fn override_field_with_env_var_tls_certificate() {
745 let mut settings = Settings::from_default_template();
746 assert_eq!(
747 settings.actix.tls.certificate,
748 Path::new("path/to/cert/cert.pem")
749 );
750 std::env::set_var(
751 "OVERRIDE__TLS_CERTIFICATE",
752 "/overridden/path/to/cert/cert.pem",
753 );
754 Settings::override_field_with_env_var(
755 &mut settings.actix.tls.certificate,
756 "OVERRIDE__TLS_CERTIFICATE",
757 )
758 .unwrap();
759 assert_eq!(
760 settings.actix.tls.certificate,
761 Path::new("/overridden/path/to/cert/cert.pem")
762 );
763 }
764
765 #[cfg(feature = "openssl")]
766 #[test]
767 fn override_field_tls_private_key() {
768 let mut settings = Settings::from_default_template();
769 assert_eq!(
770 settings.actix.tls.private_key,
771 Path::new("path/to/cert/key.pem")
772 );
773 Settings::override_field(
774 &mut settings.actix.tls.private_key,
775 "/overridden/path/to/cert/key.pem",
776 )
777 .unwrap();
778 assert_eq!(
779 settings.actix.tls.private_key,
780 Path::new("/overridden/path/to/cert/key.pem")
781 );
782 }
783
784 #[cfg(feature = "openssl")]
785 #[test]
786 fn override_field_with_env_var_tls_private_key() {
787 let mut settings = Settings::from_default_template();
788 assert_eq!(
789 settings.actix.tls.private_key,
790 Path::new("path/to/cert/key.pem")
791 );
792 std::env::set_var(
793 "OVERRIDE__TLS_PRIVATE_KEY",
794 "/overridden/path/to/cert/key.pem",
795 );
796 Settings::override_field_with_env_var(
797 &mut settings.actix.tls.private_key,
798 "OVERRIDE__TLS_PRIVATE_KEY",
799 )
800 .unwrap();
801 assert_eq!(
802 settings.actix.tls.private_key,
803 Path::new("/overridden/path/to/cert/key.pem")
804 );
805 }
806
807 #[test]
808 fn override_extended_field_with_custom_type() {
809 #[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
810 struct NestedSetting {
811 foo: String,
812 bar: bool,
813 }
814
815 #[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
816 #[serde(rename_all = "kebab-case")]
817 struct AppSettings {
818 example_name: String,
819 nested_field: NestedSetting,
820 }
821
822 type CustomSettings = BasicSettings<AppSettings>;
823
824 let mut settings = CustomSettings::from_template(
825 &(CustomSettings::DEFAULT_TOML_TEMPLATE.to_string()
826 + "\nexample-name = \"example value\""
828 + "\nnested-field = { foo = \"foo\", bar = false }"),
829 )
830 .unwrap();
831
832 assert_eq!(
833 settings.application,
834 AppSettings {
835 example_name: "example value".into(),
836 nested_field: NestedSetting {
837 foo: "foo".into(),
838 bar: false,
839 },
840 }
841 );
842
843 CustomSettings::override_field(
844 &mut settings.application.example_name,
845 "/overridden/path/to/cert/key.pem",
846 )
847 .unwrap();
848
849 assert_eq!(
850 settings.application,
851 AppSettings {
852 example_name: "/overridden/path/to/cert/key.pem".into(),
853 nested_field: NestedSetting {
854 foo: "foo".into(),
855 bar: false,
856 },
857 }
858 );
859 }
860}