aws_smithy_runtime_api/http/
error.rs
1use crate::box_error::BoxError;
9use http_02x::header::{InvalidHeaderName, InvalidHeaderValue};
10use http_02x::uri::InvalidUri;
11use std::error::Error;
12use std::fmt::{Debug, Display, Formatter};
13use std::str::Utf8Error;
14
15#[derive(Debug)]
16pub struct HttpError {
20 kind: Kind,
21 source: Option<BoxError>,
22}
23
24#[derive(Debug)]
25enum Kind {
26 InvalidExtensions,
27 InvalidHeaderName,
28 InvalidHeaderValue,
29 InvalidStatusCode,
30 InvalidUri,
31 InvalidUriParts,
32 MissingAuthority,
33 MissingScheme,
34 NonUtf8Header(NonUtf8Header),
35}
36
37#[derive(Debug)]
38pub(super) struct NonUtf8Header {
39 error: Utf8Error,
40 value: Vec<u8>,
41 name: Option<String>,
42}
43
44impl NonUtf8Header {
45 #[cfg(any(feature = "http-1x", feature = "http-02x"))]
46 pub(super) fn new(name: String, value: Vec<u8>, error: Utf8Error) -> Self {
47 Self {
48 error,
49 value,
50 name: Some(name),
51 }
52 }
53
54 pub(super) fn new_missing_name(value: Vec<u8>, error: Utf8Error) -> Self {
55 Self {
56 error,
57 value,
58 name: None,
59 }
60 }
61}
62
63impl HttpError {
64 pub(super) fn invalid_extensions() -> Self {
65 Self {
66 kind: Kind::InvalidExtensions,
67 source: None,
68 }
69 }
70
71 pub(super) fn invalid_header_name(err: InvalidHeaderName) -> Self {
72 Self {
73 kind: Kind::InvalidHeaderName,
74 source: Some(Box::new(err)),
75 }
76 }
77
78 pub(super) fn invalid_header_value(err: InvalidHeaderValue) -> Self {
79 Self {
80 kind: Kind::InvalidHeaderValue,
81 source: Some(Box::new(err)),
82 }
83 }
84
85 pub(super) fn invalid_status_code() -> Self {
86 Self {
87 kind: Kind::InvalidStatusCode,
88 source: None,
89 }
90 }
91
92 pub(super) fn invalid_uri(err: InvalidUri) -> Self {
93 Self {
94 kind: Kind::InvalidUri,
95 source: Some(Box::new(err)),
96 }
97 }
98
99 pub(super) fn invalid_uri_parts(err: http_02x::Error) -> Self {
100 Self {
101 kind: Kind::InvalidUriParts,
102 source: Some(Box::new(err)),
103 }
104 }
105
106 pub(super) fn missing_authority() -> Self {
107 Self {
108 kind: Kind::MissingAuthority,
109 source: None,
110 }
111 }
112
113 pub(super) fn missing_scheme() -> Self {
114 Self {
115 kind: Kind::MissingScheme,
116 source: None,
117 }
118 }
119
120 pub(super) fn non_utf8_header(non_utf8_header: NonUtf8Header) -> Self {
121 Self {
122 kind: Kind::NonUtf8Header(non_utf8_header),
123 source: None,
124 }
125 }
126}
127
128impl Display for HttpError {
129 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
130 use Kind::*;
131 match &self.kind {
132 InvalidExtensions => write!(f, "Extensions were provided during initialization. This prevents the request format from being converted."),
133 InvalidHeaderName => write!(f, "invalid header name"),
134 InvalidHeaderValue => write!(f, "invalid header value"),
135 InvalidStatusCode => write!(f, "invalid HTTP status code"),
136 InvalidUri => write!(f, "endpoint is not a valid URI"),
137 InvalidUriParts => write!(f, "endpoint parts are not valid"),
138 MissingAuthority => write!(f, "endpoint must contain authority"),
139 MissingScheme => write!(f, "endpoint must contain scheme"),
140 NonUtf8Header(hv) => {
141 let key = hv.name.as_deref().unwrap_or("<unknown>");
143 let value = String::from_utf8_lossy(&hv.value);
144 let index = hv.error.valid_up_to();
145 write!(f, "header `{key}={value}` contains non-UTF8 octet at index {index}")
146 },
147 }
148 }
149}
150
151impl Error for HttpError {
152 fn source(&self) -> Option<&(dyn Error + 'static)> {
153 self.source.as_ref().map(|err| err.as_ref() as _)
154 }
155}