1use crate::{pushpin::PushpinRedirectInfo, wiggle_abi::types::FastlyStatus};
4use std::error::Error as StdError;
5use std::io;
6use url::Url;
7use wiggle::GuestError;
8
9#[derive(Debug, thiserror::Error)]
10#[non_exhaustive]
11pub enum Error {
12 #[error("Buffer length error: {buf} too long to fit in {len}")]
14 BufferLengthError {
15 buf: &'static str,
16 len: &'static str,
17 },
18
19 #[error("Fatal error: [{0}]")]
22 FatalError(String),
23
24 #[error("Expected a valid Wasm file")]
26 FileFormat,
27
28 #[error("Expected a valid wastime's profiling strategy")]
29 ProfilingStrategy,
30
31 #[error(transparent)]
32 FastlyConfig(#[from] FastlyConfigError),
33
34 #[error("Could not determine address from backend URL: {0}")]
35 BackendUrl(Url),
36
37 #[error("Guest error: [{0}]")]
42 GuestError(#[from] wiggle::GuestError),
43
44 #[error(transparent)]
45 HandleError(#[from] HandleError),
46
47 #[error(transparent)]
48 HyperError(#[from] hyper::Error),
49
50 #[error(transparent)]
51 Infallible(#[from] std::convert::Infallible),
52
53 #[error("Invalid argument given")]
55 InvalidArgument,
56
57 #[error(transparent)]
58 InvalidHeaderName(#[from] http::header::InvalidHeaderName),
59
60 #[error(transparent)]
61 InvalidHeaderValue(#[from] http::header::InvalidHeaderValue),
62
63 #[error(transparent)]
64 InvalidMethod(#[from] http::method::InvalidMethod),
65
66 #[error(transparent)]
67 InvalidStatusCode(#[from] http::status::InvalidStatusCode),
68
69 #[error(transparent)]
70 InvalidUri(#[from] http::uri::InvalidUri),
71
72 #[error(transparent)]
73 IoError(#[from] std::io::Error),
74
75 #[error("Limit exceeded: {msg}")]
76 LimitExceeded { msg: &'static str },
77
78 #[error("Missing downstream metadata for request")]
79 MissingDownstreamMetadata,
80
81 #[error(transparent)]
82 Other(#[from] anyhow::Error),
83
84 #[error("Unsupported operation: {msg}")]
85 Unsupported { msg: &'static str },
86
87 #[error("Downstream response already sending")]
89 DownstreamRespSending,
90
91 #[error("Unexpected error sending a chunk to a streaming body")]
92 StreamingChunkSend,
93
94 #[error("Unknown backend: {0}")]
95 UnknownBackend(String),
96
97 #[error(transparent)]
98 DictionaryError(#[from] crate::wiggle_abi::DictionaryError),
99
100 #[error(transparent)]
101 DeviceDetectionError(#[from] crate::wiggle_abi::DeviceDetectionError),
102
103 #[error(transparent)]
104 ObjectStoreError(#[from] crate::object_store::ObjectStoreError),
105
106 #[error(transparent)]
107 KvStoreError(#[from] crate::object_store::KvStoreError),
108
109 #[error(transparent)]
110 SecretStoreError(#[from] crate::wiggle_abi::SecretStoreError),
111
112 #[error{"Expected UTF-8"}]
113 Utf8Expected(#[from] std::str::Utf8Error),
114
115 #[error{"Unsupported ABI version"}]
116 AbiVersionMismatch,
117
118 #[error(transparent)]
119 DownstreamRequestError(#[from] DownstreamRequestError),
120
121 #[error("{0} is not currently supported for local testing")]
122 NotAvailable(&'static str),
123
124 #[error("Could not load native certificates: {0}")]
125 BadCerts(std::io::Error),
126
127 #[error("No CA certificates available")]
128 TlsNoCAAvailable,
129
130 #[error("No valid CA certificates found in provided certificate bundle")]
131 TlsNoValidCACerts,
132
133 #[error("Invalid or missing host for TLS connection")]
134 TlsInvalidHost,
135
136 #[error("TLS certificate validation failed")]
137 TlsCertificateValidationFailed,
138
139 #[error("Could not generate new backend name from '{0}'")]
140 BackendNameRegistryError(String),
141
142 #[error(transparent)]
143 HttpError(#[from] http::Error),
144
145 #[error("Object Store '{0}' does not exist")]
146 UnknownObjectStore(String),
147
148 #[error("Invalid Object Store `key` value used: {0}.")]
149 ObjectStoreKeyValidationError(#[from] crate::object_store::KeyValidationError),
150
151 #[error("Unfinished streaming body")]
152 UnfinishedStreamingBody,
153
154 #[error("Shared memory not supported yet")]
155 SharedMemory,
156
157 #[error("Value absent from structure")]
158 ValueAbsent,
159
160 #[error("String conversion error")]
161 ToStr(#[from] http::header::ToStrError),
162
163 #[error("invalid client certificate")]
164 InvalidClientCert(#[from] crate::config::ClientCertError),
165
166 #[error("Invalid response to ALPN request; wanted '{0}', got '{1}'")]
167 InvalidAlpnResponse(&'static str, String),
168
169 #[error("Resource temporarily unavailable")]
170 Again,
171
172 #[error("cache error: {0}")]
173 CacheError(crate::cache::Error),
174}
175
176impl Error {
177 pub fn to_fastly_status(&self) -> FastlyStatus {
184 match self {
185 Error::BufferLengthError { .. } => FastlyStatus::Buflen,
186 Error::InvalidArgument => FastlyStatus::Inval,
187 Error::ValueAbsent => FastlyStatus::None,
188 Error::Unsupported { .. } | Error::NotAvailable(_) => FastlyStatus::Unsupported,
189 Error::HandleError { .. } => FastlyStatus::Badf,
190 Error::InvalidStatusCode { .. } => FastlyStatus::Inval,
191 Error::UnknownBackend(_) | Error::InvalidClientCert(_) => FastlyStatus::Inval,
192 Error::HyperError(e) if e.is_parse() => FastlyStatus::Httpinvalid,
194 Error::HyperError(e) if e.is_user() => FastlyStatus::Httpuser,
195 Error::HyperError(e) if e.is_incomplete_message() => FastlyStatus::Httpincomplete,
196 Error::HyperError(e)
197 if e.source()
198 .and_then(|e| e.downcast_ref::<io::Error>())
199 .map(|ioe| ioe.kind())
200 == Some(io::ErrorKind::UnexpectedEof) =>
201 {
202 FastlyStatus::Httpincomplete
203 }
204 Error::HyperError(_) => FastlyStatus::Error,
205 Error::GuestError(e) => Self::guest_error_fastly_status(e),
207 Error::DictionaryError(e) => e.to_fastly_status(),
209 Error::DeviceDetectionError(e) => e.to_fastly_status(),
210 Error::ObjectStoreError(e) => e.into(),
211 Error::KvStoreError(e) => e.into(),
212 Error::SecretStoreError(e) => e.into(),
213 Error::Again => FastlyStatus::Again,
214 Error::LimitExceeded { .. } => FastlyStatus::Limitexceeded,
215 Error::CacheError(e) => e.into(),
216 Error::AbiVersionMismatch
218 | Error::BackendUrl(_)
219 | Error::BadCerts(_)
220 | Error::TlsNoCAAvailable
221 | Error::TlsNoValidCACerts
222 | Error::TlsInvalidHost
223 | Error::TlsCertificateValidationFailed
224 | Error::DownstreamRequestError(_)
225 | Error::DownstreamRespSending
226 | Error::FastlyConfig(_)
227 | Error::FatalError(_)
228 | Error::FileFormat
229 | Error::Infallible(_)
230 | Error::InvalidHeaderName(_)
231 | Error::InvalidHeaderValue(_)
232 | Error::InvalidMethod(_)
233 | Error::InvalidUri(_)
234 | Error::IoError(_)
235 | Error::MissingDownstreamMetadata
236 | Error::Other(_)
237 | Error::ProfilingStrategy
238 | Error::StreamingChunkSend
239 | Error::Utf8Expected(_)
240 | Error::BackendNameRegistryError(_)
241 | Error::HttpError(_)
242 | Error::UnknownObjectStore(_)
243 | Error::ObjectStoreKeyValidationError(_)
244 | Error::UnfinishedStreamingBody
245 | Error::SharedMemory
246 | Error::ToStr(_)
247 | Error::InvalidAlpnResponse(_, _) => FastlyStatus::Error,
248 }
249 }
250
251 fn guest_error_fastly_status(e: &GuestError) -> FastlyStatus {
252 use GuestError::*;
253 match e {
254 PtrNotAligned { .. } => FastlyStatus::Badalign,
255 InvalidFlagValue { .. }
258 | InvalidEnumValue { .. }
259 | PtrOutOfBounds { .. }
260 | PtrOverflow
261 | InvalidUtf8 { .. }
262 | TryFromIntError { .. } => FastlyStatus::Inval,
263 SliceLengthsDiffer => FastlyStatus::Error,
266 InFunc { err, .. } => Self::guest_error_fastly_status(err),
269 }
270 }
271}
272
273#[derive(Debug, thiserror::Error)]
275pub enum HandleError {
276 #[error("Invalid request handle: {0}")]
278 InvalidRequestHandle(crate::wiggle_abi::types::RequestHandle),
279
280 #[error("Invalid response handle: {0}")]
282 InvalidResponseHandle(crate::wiggle_abi::types::ResponseHandle),
283
284 #[error("Invalid body handle: {0}")]
286 InvalidBodyHandle(crate::wiggle_abi::types::BodyHandle),
287
288 #[error("Invalid endpoint handle: {0}")]
290 InvalidEndpointHandle(crate::wiggle_abi::types::EndpointHandle),
291
292 #[error("Invalid pending request promise handle: {0}")]
294 InvalidPendingRequestHandle(crate::wiggle_abi::types::PendingRequestHandle),
295
296 #[error("Invalid pending downstream request handle: {0}")]
298 InvalidPendingDownstreamHandle(crate::wiggle_abi::types::AsyncItemHandle),
299
300 #[error("Invalid pending KV lookup handle: {0}")]
302 InvalidPendingKvLookupHandle(crate::wiggle_abi::types::PendingKvLookupHandle),
303
304 #[error("Invalid pending KV insert handle: {0}")]
306 InvalidPendingKvInsertHandle(crate::wiggle_abi::types::PendingKvInsertHandle),
307
308 #[error("Invalid pending KV delete handle: {0}")]
310 InvalidPendingKvDeleteHandle(crate::wiggle_abi::types::PendingKvDeleteHandle),
311
312 #[error("Invalid pending KV list handle: {0}")]
314 InvalidPendingKvListHandle(crate::wiggle_abi::types::PendingKvListHandle),
315
316 #[error("Invalid dictionary handle: {0}")]
318 InvalidDictionaryHandle(crate::wiggle_abi::types::DictionaryHandle),
319
320 #[error("Invalid object-store handle: {0}")]
322 InvalidObjectStoreHandle(crate::wiggle_abi::types::ObjectStoreHandle),
323
324 #[error("Invalid secret store handle: {0}")]
326 InvalidSecretStoreHandle(crate::wiggle_abi::types::SecretStoreHandle),
327
328 #[error("Invalid secret handle: {0}")]
330 InvalidSecretHandle(crate::wiggle_abi::types::SecretHandle),
331
332 #[error("Invalid async item handle: {0}")]
334 InvalidAsyncItemHandle(crate::wiggle_abi::types::AsyncItemHandle),
335
336 #[error("Invalid acl handle: {0}")]
338 InvalidAclHandle(crate::wiggle_abi::types::AclHandle),
339
340 #[error("Invalid cache handle: {0}")]
342 InvalidCacheHandle(crate::wiggle_abi::types::CacheHandle),
343}
344
345#[derive(Debug, thiserror::Error)]
353pub(crate) enum ExecutionError {
354 #[error("WebAssembly execution trapped: {0}")]
360 WasmTrap(anyhow::Error),
361
362 #[error("Error creating context: {0}")]
364 Context(anyhow::Error),
365
366 #[error("Error type-checking WebAssembly instantiation: {0}")]
368 Typechecking(anyhow::Error),
369
370 #[error("Error instantiating WebAssembly: {0}")]
372 Instantiation(anyhow::Error),
373}
374
375#[derive(Debug, thiserror::Error)]
377pub enum FastlyConfigError {
378 #[error("error reading '{path}': {err}")]
380 IoError {
381 path: String,
382 #[source]
383 err: std::io::Error,
384 },
385
386 #[error("invalid configuration for '{name}': {err}")]
387 InvalidDeviceDetectionDefinition {
388 name: String,
389 #[source]
390 err: DeviceDetectionConfigError,
391 },
392
393 #[error("invalid configuration for '{name}': {err}")]
394 InvalidGeolocationDefinition {
395 name: String,
396 #[source]
397 err: GeolocationConfigError,
398 },
399
400 #[error("invalid configuration for '{name}': {err}")]
401 InvalidAclDefinition {
402 name: String,
403 #[source]
404 err: AclConfigError,
405 },
406
407 #[error("invalid configuration for '{name}': {err}")]
408 InvalidBackendDefinition {
409 name: String,
410 #[source]
411 err: BackendConfigError,
412 },
413
414 #[error("invalid configuration for '{name}': {err}")]
415 InvalidDictionaryDefinition {
416 name: String,
417 #[source]
418 err: DictionaryConfigError,
419 },
420
421 #[error("invalid configuration for '{name}': {err}")]
422 InvalidObjectStoreDefinition {
423 name: String,
424 #[source]
425 err: ObjectStoreConfigError,
426 },
427
428 #[error("invalid configuration for '{name}': {err}")]
429 InvalidSecretStoreDefinition {
430 name: String,
431 #[source]
432 err: SecretStoreConfigError,
433 },
434
435 #[error("invalid configuration for '{name}': {err}")]
436 InvalidShieldingSiteDefinition {
437 name: String,
438 #[source]
439 err: ShieldingSiteConfigError,
440 },
441
442 #[error("error parsing `fastly.toml`: {0}")]
446 InvalidFastlyToml(#[from] toml::de::Error),
447
448 #[error("unsupported manifest version {0}; max supported version is {1}")]
451 UnsupportedManifestVersion(u32, u32),
452}
453
454#[derive(Debug, thiserror::Error)]
456pub enum AclConfigError {
457 #[error(transparent)]
459 IoError(std::io::Error),
460
461 #[error(transparent)]
463 JsonError(serde_json::error::Error),
464
465 #[error("acl must be a TOML table or string")]
466 InvalidType,
467
468 #[error("missing 'file' field")]
469 MissingFile,
470}
471
472#[derive(Debug, thiserror::Error)]
474pub enum BackendConfigError {
475 #[error("definition was not provided as a TOML table")]
476 InvalidEntryType,
477
478 #[error("invalid override_host: {0}")]
479 InvalidOverrideHost(#[from] http::header::InvalidHeaderValue),
480
481 #[error("'override_host' field is empty")]
482 EmptyOverrideHost,
483
484 #[error("'override_host' field was not a string")]
485 InvalidOverrideHostEntry,
486
487 #[error("'cert_host' field is empty")]
488 EmptyCertHost,
489
490 #[error("'cert_host' field was not a string")]
491 InvalidCertHostEntry,
492
493 #[error("'ca_certificate' field is empty")]
494 EmptyCACert,
495
496 #[error("'ca_certificate' field was invalid: {0}")]
497 InvalidCACertEntry(String),
498
499 #[error("'use_sni' field was not a boolean")]
500 InvalidUseSniEntry,
501
502 #[error("'grpc' field was not a boolean")]
503 InvalidGrpcEntry,
504
505 #[error(
506 "'health' field has invalid value '{0}' (expected 'unknown', 'healthy', or 'unhealthy')"
507 )]
508 InvalidHealthEntry(String),
509
510 #[error("invalid url: {0}")]
511 InvalidUrl(#[from] http::uri::InvalidUri),
512
513 #[error("'url' field was not a string")]
514 InvalidUrlEntry,
515
516 #[error("no default definition provided")]
517 MissingDefault,
518
519 #[error("missing 'url' field")]
520 MissingUrl,
521
522 #[error("unrecognized key '{0}'")]
523 UnrecognizedKey(String),
524
525 #[error(transparent)]
526 ClientCertError(#[from] crate::config::ClientCertError),
527}
528
529#[derive(Debug, thiserror::Error)]
531pub enum DictionaryConfigError {
532 #[error(transparent)]
534 IoError(std::io::Error),
535
536 #[error("'contents' was not provided as a TOML table")]
537 InvalidContentsType,
538
539 #[error("inline dictionary value was not a string")]
540 InvalidInlineEntryType,
541
542 #[error("definition was not provided as a TOML table")]
543 InvalidEntryType,
544
545 #[error("'name' field was not a string")]
546 InvalidNameEntry,
547
548 #[error(
549 "'{0}' is not a valid format for the dictionary. Supported format(s) are: 'inline-toml', 'json'."
550 )]
551 InvalidDictionaryFormat(String),
552
553 #[error("'file' field is empty")]
554 EmptyFileEntry,
555
556 #[error("'format' field is empty")]
557 EmptyFormatEntry,
558
559 #[error("'file' field was not a string")]
560 InvalidFileEntry,
561
562 #[error("'format' field was not a string")]
563 InvalidFormatEntry,
564
565 #[error("missing 'contents' field")]
566 MissingContents,
567
568 #[error("no default definition provided")]
569 MissingDefault,
570
571 #[error("missing 'name' field")]
572 MissingName,
573
574 #[error("missing 'file' field")]
575 MissingFile,
576
577 #[error("missing 'format' field")]
578 MissingFormat,
579
580 #[error("unrecognized key '{0}'")]
581 UnrecognizedKey(String),
582
583 #[error("Item key named '{key}' is too long, max size is {size}")]
584 DictionaryItemKeyTooLong { key: String, size: i32 },
585
586 #[error("too many items, max amount is {size}")]
587 DictionaryCountTooLong { size: i32 },
588
589 #[error(
590 "Item value under key named '{key}' is of the wrong format. The value is expected to be a JSON String"
591 )]
592 DictionaryItemValueWrongFormat { key: String },
593
594 #[error("Item value named '{key}' is too long, max size is {size}")]
595 DictionaryItemValueTooLong { key: String, size: i32 },
596
597 #[error(
598 "The file is of the wrong format. The file is expected to contain a single JSON Object"
599 )]
600 DictionaryFileWrongFormat,
601}
602
603#[derive(Debug, thiserror::Error)]
605pub enum DeviceDetectionConfigError {
606 #[error(transparent)]
608 IoError(std::io::Error),
609
610 #[error("definition was not provided as a TOML table")]
611 InvalidEntryType,
612
613 #[error("missing 'file' field")]
614 MissingFile,
615
616 #[error("'file' field is empty")]
617 EmptyFileEntry,
618
619 #[error("missing 'user_agents' field")]
620 MissingUserAgents,
621
622 #[error("inline device detection value was not a string")]
623 InvalidInlineEntryType,
624
625 #[error("'file' field was not a string")]
626 InvalidFileEntry,
627
628 #[error("'user_agents' was not provided as a TOML table")]
629 InvalidUserAgentsType,
630
631 #[error("unrecognized key '{0}'")]
632 UnrecognizedKey(String),
633
634 #[error("missing 'format' field")]
635 MissingFormat,
636
637 #[error("'format' field was not a string")]
638 InvalidFormatEntry,
639
640 #[error(
641 "'{0}' is not a valid format for the device detection mapping. Supported format(s) are: 'inline-toml', 'json'."
642 )]
643 InvalidDeviceDetectionMappingFormat(String),
644
645 #[error(
646 "The file is of the wrong format. The file is expected to contain a single JSON Object"
647 )]
648 DeviceDetectionFileWrongFormat,
649
650 #[error("'format' field is empty")]
651 EmptyFormatEntry,
652
653 #[error(
654 "Item value under key named '{key}' is of the wrong format. The value is expected to be a JSON String"
655 )]
656 DeviceDetectionItemValueWrongFormat { key: String },
657}
658
659#[derive(Debug, thiserror::Error)]
661pub enum GeolocationConfigError {
662 #[error(transparent)]
664 IoError(std::io::Error),
665
666 #[error("definition was not provided as a TOML table")]
667 InvalidEntryType,
668
669 #[error("missing 'file' field")]
670 MissingFile,
671
672 #[error("'file' field is empty")]
673 EmptyFileEntry,
674
675 #[error("missing 'addresses' field")]
676 MissingAddresses,
677
678 #[error("inline geolocation value was not a string")]
679 InvalidInlineEntryType,
680
681 #[error("'file' field was not a string")]
682 InvalidFileEntry,
683
684 #[error("'addresses' was not provided as a TOML table")]
685 InvalidAddressesType,
686
687 #[error("unrecognized key '{0}'")]
688 UnrecognizedKey(String),
689
690 #[error("missing 'format' field")]
691 MissingFormat,
692
693 #[error("'format' field was not a string")]
694 InvalidFormatEntry,
695
696 #[error("IP address not valid: '{0}'")]
697 InvalidAddressEntry(String),
698
699 #[error(
700 "'{0}' is not a valid format for the geolocation mapping. Supported format(s) are: 'inline-toml', 'json'."
701 )]
702 InvalidGeolocationMappingFormat(String),
703
704 #[error(
705 "The file is of the wrong format. The file is expected to contain a single JSON Object"
706 )]
707 GeolocationFileWrongFormat,
708
709 #[error("'format' field is empty")]
710 EmptyFormatEntry,
711
712 #[error(
713 "Item value under key named '{key}' is of the wrong format. The value is expected to be a JSON String"
714 )]
715 GeolocationItemValueWrongFormat { key: String },
716}
717
718#[derive(Debug, thiserror::Error)]
720pub enum ObjectStoreConfigError {
721 #[error(transparent)]
723 IoError(std::io::Error),
724 #[error("The `file` and `data` keys for the object `{0}` are set. Only one can be used.")]
725 FileAndData(String),
726 #[error("The `file` or `data` key for the object `{0}` is not set. One must be used.")]
727 NoFileOrData(String),
728 #[error("The `data` value for the object `{0}` is not a string.")]
729 DataNotAString(String),
730 #[error("The `metadata` value for the object `{0}` is not a string.")]
731 MetadataNotAString(String),
732 #[error("The `file` value for the object `{0}` is not a string.")]
733 FileNotAString(String),
734 #[error("The `key` key for an object is not set. It must be used.")]
735 NoKey,
736 #[error("The `key` value for an object is not a string.")]
737 KeyNotAString,
738 #[error("There is no array of objects for the given store.")]
739 NotAnArray,
740 #[error("There is an object in the given store that is not a table of keys.")]
741 NotATable,
742 #[error("There was an error when manipulating the ObjectStore: {0}.")]
743 ObjectStoreError(#[from] crate::object_store::ObjectStoreError),
744 #[error("There was an error when manipulating the KvStore: {0}.")]
745 KvStoreError(#[from] crate::object_store::KvStoreError),
746 #[error("Invalid `key` value used: {0}.")]
747 KeyValidationError(#[from] crate::object_store::KeyValidationError),
748 #[error("'{0}' is not a valid format for the config store. Supported format(s) are: 'json'.")]
749 InvalidFileFormat(String),
750 #[error("When using a top-level 'file' to load data, both 'file' and 'format' must be set.")]
751 OnlyOneFormatOrFileSet,
752 #[error(
753 "The file is of the wrong format. The file is expected to contain a single JSON Object."
754 )]
755 FileWrongFormat,
756 #[error(
757 "Item value under key named '{key}' is of the wrong format. The value is expected to be a JSON String."
758 )]
759 FileValueWrongFormat { key: String },
760 #[error(
761 "Item value under key named '{key}' is of the wrong format. 'data' and 'file' are mutually exclusive."
762 )]
763 BothDataAndFilePresent { key: String },
764 #[error(
765 "Item value under key named '{key}' is of the wrong format. One of 'data' or 'file' must be present."
766 )]
767 MissingDataOrFile { key: String },
768}
769
770#[derive(Debug, thiserror::Error)]
772pub enum SecretStoreConfigError {
773 #[error(transparent)]
775 IoError(std::io::Error),
776
777 #[error("'{0}' is not a valid format for the secret store. Supported format(s) are: 'json'.")]
778 InvalidFileFormat(String),
779 #[error("When using a top-level 'file' to load data, both 'file' and 'format' must be set.")]
780 OnlyOneFormatOrFileSet,
781 #[error(
782 "The file is of the wrong format. The file is expected to contain a single JSON object."
783 )]
784 FileWrongFormat,
785 #[error(
786 "More than one of `file`, `data`, or `env` keys for the object `{0}` are set. Only one can be used."
787 )]
788 FileDataEnvExclusive(String),
789 #[error("None of `file`, `data`, or `env` keys for the object `{0}` is set. One must be used.")]
790 FileDataEnvNotSet(String),
791 #[error("The `data` value for the object `{0}` is not a string.")]
792 DataNotAString(String),
793 #[error("The `file` value for the object `{0}` is not a string.")]
794 FileNotAString(String),
795 #[error("The `env` value for the object `{0}` is not a string.")]
796 EnvNotAString(String),
797
798 #[error("The `key` key for an object is not set. It must be used.")]
799 NoKey,
800 #[error("The `key` value for an object is not a string.")]
801 KeyNotAString,
802
803 #[error("There is no array of objects for the given store.")]
804 NotAnArray,
805 #[error("There is an object in the given store that is not a table of keys.")]
806 NotATable,
807
808 #[error("Invalid secret store name: {0}")]
809 InvalidSecretStoreName(String),
810
811 #[error("Invalid secret name: {0}")]
812 InvalidSecretName(String),
813}
814
815#[derive(Debug, thiserror::Error)]
817pub enum ShieldingSiteConfigError {
818 #[error(
819 "Illegal TOML value for shielding site; must be either the string 'local' or a table containing an encrypted and unencrypted URL."
820 )]
821 IllegalSiteValue,
822
823 #[error("Illegal TOML string for shielding site; must be 'local'")]
824 IllegalSiteString,
825
826 #[error(
827 "Illegal table for shielding site; must have exactly one key named 'encrypted', and one named 'unencrypted'"
828 )]
829 IllegalSiteDefinition,
830
831 #[error("Illegal URL ({url}): {error}")]
832 IllegalUrl { url: String, error: url::ParseError },
833}
834
835#[derive(Debug, thiserror::Error)]
837pub enum DownstreamRequestError {
838 #[error("Request HOST header is missing or invalid")]
839 InvalidHost,
840
841 #[error("Request URL is invalid")]
842 InvalidUrl,
843}
844
845#[derive(Debug, thiserror::Error)]
848pub enum NonHttpResponse {
849 #[error("graceful Pushpin redirect")]
850 PushpinRedirect(PushpinRedirectInfo),
851 }