Skip to content

Commit 03c7869

Browse files
committed
add custom headers support
Signed-off-by: Luminita Voicu <[email protected]>
1 parent eb8b8cb commit 03c7869

File tree

1 file changed

+55
-7
lines changed

1 file changed

+55
-7
lines changed

src/common/headers.rs

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4+
use std::collections::HashMap;
45
use std::result::Result;
56

67
use crate::HttpHeaderError;
@@ -94,6 +95,8 @@ pub struct Headers {
9495
/// `Accept` header might be used by HTTP clients to enforce server responses with content
9596
/// formatted in a specific way.
9697
accept: MediaType,
98+
/// Hashmap reserved for storing custom headers.
99+
custom_entries: HashMap<String, String>,
97100
}
98101

99102
impl Default for Headers {
@@ -106,6 +109,7 @@ impl Default for Headers {
106109
// The default `Accept` media type is plain text. This is inclusive enough
107110
// for structured and unstructured text.
108111
accept: MediaType::PlainText,
112+
custom_entries: HashMap::default(),
109113
}
110114
}
111115
}
@@ -206,12 +210,11 @@ impl Headers {
206210
Header::AcceptEncoding => Encoding::try_from(entry[1].trim().as_bytes()),
207211
}
208212
} else {
209-
Err(RequestError::HeaderError(
210-
HttpHeaderError::UnsupportedValue(
211-
entry[0].to_string(),
212-
entry[1].to_string(),
213-
),
214-
))
213+
self.insert_custom_header(
214+
entry[0].trim().to_string(),
215+
entry[1].trim().to_string(),
216+
)?;
217+
Ok(())
215218
}
216219
}
217220
Err(utf8_err) => Err(RequestError::HeaderError(
@@ -289,6 +292,17 @@ impl Headers {
289292
pub fn set_accept(&mut self, media_type: MediaType) {
290293
self.accept = media_type;
291294
}
295+
296+
/// Insert a new custom header and value pair into the `HashMap`.
297+
pub fn insert_custom_header(&mut self, key: String, value: String) -> Result<(), RequestError> {
298+
self.custom_entries.insert(key, value);
299+
Ok(())
300+
}
301+
302+
/// Returns the custom header `HashMap`.
303+
pub fn custom_entries(&self) -> &HashMap<String, String> {
304+
&self.custom_entries
305+
}
292306
}
293307

294308
/// Wrapper over supported AcceptEncoding.
@@ -414,6 +428,7 @@ impl MediaType {
414428
#[cfg(test)]
415429
mod tests {
416430
use super::*;
431+
use std::collections::HashMap;
417432

418433
impl Headers {
419434
pub fn new(content_length: u32, expect: bool, chunked: bool) -> Self {
@@ -422,6 +437,7 @@ mod tests {
422437
expect,
423438
chunked,
424439
accept: MediaType::PlainText,
440+
custom_entries: HashMap::default(),
425441
}
426442
}
427443
}
@@ -433,6 +449,7 @@ mod tests {
433449
assert_eq!(headers.chunked(), false);
434450
assert_eq!(headers.expect(), false);
435451
assert_eq!(headers.accept(), MediaType::PlainText);
452+
assert_eq!(headers.custom_entries(), &HashMap::default());
436453
}
437454

438455
#[test]
@@ -512,6 +529,11 @@ mod tests {
512529
.unwrap();
513530
assert_eq!(headers.content_length, 55);
514531
assert_eq!(headers.accept, MediaType::ApplicationJson);
532+
assert_eq!(
533+
headers.custom_entries().get("Last-Modified").unwrap(),
534+
"Tue, 15 Nov 1994 12:45:26 GMT"
535+
);
536+
assert_eq!(headers.custom_entries().len(), 1);
515537

516538
// Valid headers. (${HEADER_NAME} : WHITESPACE ${HEADER_VALUE})
517539
// Any number of whitespace characters should be accepted including zero.
@@ -529,7 +551,17 @@ mod tests {
529551
.unwrap();
530552
assert_eq!(headers.content_length, 29);
531553

532-
// Valid headers.
554+
// Custom headers only.
555+
let headers = Headers::try_from(
556+
b"Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT\r\nfoo: bar\r\nbar: 15\r\n\r\n",
557+
)
558+
.unwrap();
559+
let custom_entries = headers.custom_entries();
560+
assert_eq!(custom_entries.get("foo").unwrap(), "bar");
561+
assert_eq!(custom_entries.get("bar").unwrap(), "15");
562+
assert_eq!(custom_entries.len(), 3);
563+
564+
// Valid headers, invalid value.
533565
assert_eq!(
534566
Headers::try_from(
535567
b"Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT\r\nContent-Length: -55\r\n\r\n"
@@ -656,6 +688,15 @@ mod tests {
656688
" identity;q=0".to_string()
657689
)))
658690
);
691+
692+
// Test custom header.
693+
assert_eq!(header.custom_entries().len(), 0);
694+
assert!(header.parse_header_line(b"Custom-Header: foo").is_ok());
695+
assert_eq!(
696+
header.custom_entries().get("Custom-Header").unwrap(),
697+
&"foo".to_string()
698+
);
699+
assert_eq!(header.custom_entries().len(), 1);
659700
}
660701

661702
#[test]
@@ -697,6 +738,13 @@ mod tests {
697738
// For Expect
698739
assert!(header.parse_header_line(b"Expect:100-continue").is_ok());
699740
assert!(header.parse_header_line(b"Expect: 100-continue").is_ok());
741+
742+
// Test that custom headers' names and values are trimmed before being stored
743+
// inside the HashMap.
744+
assert!(header.parse_header_line(b"Foo:bar").is_ok());
745+
assert_eq!(header.custom_entries().get("Foo").unwrap(), "bar");
746+
assert!(header.parse_header_line(b" Bar : foo ").is_ok());
747+
assert_eq!(header.custom_entries().get("Bar").unwrap(), "foo");
700748
}
701749

702750
#[test]

0 commit comments

Comments
 (0)