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