(
data_parts: &[String],
form_parts: &[(String, String, bool)],
headers: &[Header],
)
| 214 | let (key, value) = split_once(raw, ':')?; |
| 215 | let key = key.trim(); |
| 216 | let value = value.trim(); |
| 217 | if key.is_empty() { |
| 218 | None |
| 219 | } else { |
| 220 | Some(Header::new(key, value)) |
| 221 | } |
| 222 | } |
| 223 | |
| 224 | fn split_once(s: &str, sep: char) -> Option<(&str, &str)> { |
| 225 | let idx = s.find(sep)?; |
| 226 | Some((&s[..idx], &s[idx + sep.len_utf8()..])) |
| 227 | } |
| 228 | |
| 229 | fn header_value<'a>(headers: &'a [Header], name: &str) -> Option<&'a str> { |
| 230 | headers |
| 231 | .iter() |
| 232 | .find(|h| h.key.eq_ignore_ascii_case(name)) |
| 233 | .map(|h| h.value.as_str()) |
| 234 | } |
| 235 | |
| 236 | fn build_body( |
| 237 | data_parts: &[String], |
| 238 | form_parts: &[(String, String, bool)], |
| 239 | headers: &[Header], |
| 240 | ) -> RequestBody { |
| 241 | if !form_parts.is_empty() { |
| 242 | let fields = form_parts |
| 243 | .iter() |
| 244 | .map(|(k, v, is_file)| { |
| 245 | if *is_file { |
| 246 | crate::entities::MultipartField::file(k, v) |
| 247 | } else { |
| 248 | crate::entities::MultipartField::text(k, v) |
| 249 | } |
| 250 | }) |
| 251 | .collect::<Vec<_>>(); |
| 252 | return RequestBody::MultipartFormData(fields); |
| 253 | } |
| 254 | |
| 255 | if data_parts.is_empty() { |
| 256 | return RequestBody::None; |
| 257 | } |
| 258 | |
| 259 | let combined = data_parts.join("&"); |
| 260 | let content_type = header_value(headers, "Content-Type").unwrap_or(""); |
| 261 | |
| 262 | if content_type.contains("application/json") || looks_like_json(&combined) { |
| 263 | return RequestBody::Json(combined); |
| 264 | } |
| 265 | |
| 266 | if content_type.contains("application/x-www-form-urlencoded") |
no test coverage detected