Skip to main content

async_nats/
header.rs

1// Copyright 2020-2023 The NATS Authors
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14// NOTE(thomastaylor312): This clippy lint is coming from serialize and deserialize and is likely a
15// false positive due to the bytes crate, see
16// https://rust-lang.github.io/rust-clippy/master/index.html#/mutable_key_type for more details.
17// Sorry to make this global to this module, rather than on the `HeaderMap` struct, but because it
18// is coming from the derive, it didn't work to set it on the struct.
19#![allow(clippy::mutable_key_type)]
20
21//! NATS [Message][crate::Message] headers, modeled loosely after the `http::header` crate.
22
23use std::{collections::HashMap, fmt, slice::Iter, str::FromStr};
24
25use bytes::Bytes;
26use serde::{Deserialize, Deserializer, Serialize, Serializer};
27
28/// A struct for handling NATS headers.
29/// Has a similar API to `http::header`, but properly serializes and deserializes
30/// according to NATS requirements.
31///
32/// # Examples
33///
34/// ```
35/// # #[tokio::main]
36/// # async fn main() -> Result<(), async_nats::Error> {
37/// let client = async_nats::connect("demo.nats.io").await?;
38/// let mut headers = async_nats::HeaderMap::new();
39/// headers.insert("Key", "Value");
40/// client
41///     .publish_with_headers("subject", headers, "payload".into())
42///     .await?;
43/// # Ok(())
44/// # }
45/// ```
46
47#[derive(Clone, PartialEq, Eq, Debug, Default)]
48pub struct HeaderMap {
49    inner: HashMap<HeaderName, Vec<HeaderValue>>,
50}
51
52/// Helper enum for backward-compatible deserialization using serde's untagged feature
53/// This is required because of the bug #1470 where the client incorrectly serialized
54/// headers with an "inner" wrapper.
55#[derive(Deserialize)]
56#[serde(untagged)]
57enum HeaderMapHelper {
58    // Legacy format with "inner" wrapper
59    Legacy {
60        inner: HashMap<HeaderName, Vec<HeaderValue>>,
61    },
62    // Proper format - direct HashMap
63    Current(HashMap<HeaderName, Vec<HeaderValue>>),
64}
65
66impl<'de> Deserialize<'de> for HeaderMap {
67    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
68    where
69        D: Deserializer<'de>,
70    {
71        // Use the untagged enum to automatically try both formats
72        let helper = HeaderMapHelper::deserialize(deserializer)?;
73
74        Ok(match helper {
75            HeaderMapHelper::Legacy { inner } => HeaderMap { inner },
76            HeaderMapHelper::Current(inner) => HeaderMap { inner },
77        })
78    }
79}
80
81impl Serialize for HeaderMap {
82    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
83    where
84        S: Serializer,
85    {
86        // Serialize as the new format (direct HashMap without "inner" wrapper)
87        self.inner.serialize(serializer)
88    }
89}
90
91impl FromIterator<(HeaderName, HeaderValue)> for HeaderMap {
92    fn from_iter<T: IntoIterator<Item = (HeaderName, HeaderValue)>>(iter: T) -> Self {
93        let mut header_map = HeaderMap::new();
94        for (key, value) in iter {
95            header_map.insert(key, value);
96        }
97        header_map
98    }
99}
100
101impl HeaderMap {
102    pub fn iter(&self) -> std::collections::hash_map::Iter<'_, HeaderName, Vec<HeaderValue>> {
103        self.inner.iter()
104    }
105}
106
107pub struct GetAll<'a, T> {
108    inner: Iter<'a, T>,
109}
110
111impl<'a, T> Iterator for GetAll<'a, T> {
112    type Item = &'a T;
113
114    fn next(&mut self) -> Option<Self::Item> {
115        self.inner.next()
116    }
117}
118
119impl HeaderMap {
120    /// Create an empty `HeaderMap`.
121    ///
122    /// # Examples
123    ///
124    /// ```
125    /// # use async_nats::HeaderMap;
126    /// let map = HeaderMap::new();
127    ///
128    /// assert!(map.is_empty());
129    /// ```
130    pub fn new() -> Self {
131        HeaderMap::default()
132    }
133
134    /// Returns true if the map contains no elements.
135    ///
136    /// # Examples
137    ///
138    /// ```
139    /// # use async_nats::HeaderMap;
140    /// # use async_nats::header::NATS_SUBJECT;
141    /// let mut map = HeaderMap::new();
142    ///
143    /// assert!(map.is_empty());
144    ///
145    /// map.insert(NATS_SUBJECT, "FOO.BAR");
146    ///
147    /// assert!(!map.is_empty());
148    /// ```
149    pub fn is_empty(&self) -> bool {
150        self.inner.is_empty()
151    }
152
153    pub fn len(&self) -> usize {
154        self.inner.len()
155    }
156}
157
158impl HeaderMap {
159    /// Inserts a new value to a [HeaderMap].
160    ///
161    /// # Examples
162    ///
163    /// ```
164    /// use async_nats::HeaderMap;
165    ///
166    /// let mut headers = HeaderMap::new();
167    /// headers.insert("Key", "Value");
168    /// ```
169    pub fn insert<K: IntoHeaderName, V: IntoHeaderValue>(&mut self, name: K, value: V) {
170        self.inner
171            .insert(name.into_header_name(), vec![value.into_header_value()]);
172    }
173
174    /// Appends a new value to the list of values to a given key.
175    /// If the key did not exist, it will be inserted with provided value.
176    ///
177    /// # Examples
178    ///
179    /// ```
180    /// use async_nats::HeaderMap;
181    ///
182    /// let mut headers = HeaderMap::new();
183    /// headers.append("Key", "Value");
184    /// headers.append("Key", "Another");
185    pub fn append<K: IntoHeaderName, V: IntoHeaderValue>(&mut self, name: K, value: V) {
186        let key = name.into_header_name();
187        let v = self.inner.get_mut(&key);
188        match v {
189            Some(v) => {
190                v.push(value.into_header_value());
191            }
192            None => {
193                self.insert(key, value.into_header_value());
194            }
195        }
196    }
197
198    /// Gets a value for a given key. If key is not found, [Option::None] is returned.
199    ///
200    /// # Examples
201    ///
202    /// ```
203    /// # use async_nats::HeaderMap;
204    ///
205    /// let mut headers = HeaderMap::new();
206    /// headers.append("Key", "Value");
207    /// let values = headers.get("Key").unwrap();
208    /// ```
209    pub fn get<K: IntoHeaderName>(&self, key: K) -> Option<&HeaderValue> {
210        self.inner
211            .get(&key.into_header_name())
212            .and_then(|x| x.first())
213    }
214
215    /// Gets a last value for a given key. If key is not found, [Option::None] is returned.
216    ///
217    /// # Examples
218    ///
219    /// ```
220    /// # use async_nats::HeaderMap;
221    ///
222    /// let mut headers = HeaderMap::new();
223    /// headers.append("Key", "Value");
224    /// let values = headers.get_last("Key").unwrap();
225    /// ```
226    pub fn get_last<K: IntoHeaderName>(&self, key: K) -> Option<&HeaderValue> {
227        self.inner
228            .get(&key.into_header_name())
229            .and_then(|x| x.last())
230    }
231
232    /// Gets an iterator to the values for a given key.
233    ///
234    /// # Examples
235    ///
236    /// ```
237    /// # use async_nats::HeaderMap;
238    ///
239    /// let mut headers = HeaderMap::new();
240    /// headers.append("Key", "Value1");
241    /// headers.append("Key", "Value2");
242    /// let mut values = headers.get_all("Key");
243    /// let value1 = values.next();
244    /// let value2 = values.next();
245    /// ```
246    pub fn get_all<K: IntoHeaderName>(&self, key: K) -> GetAll<'_, HeaderValue> {
247        let inner = self
248            .inner
249            .get(&key.into_header_name())
250            .map(|x| x.iter())
251            .unwrap_or([].iter());
252
253        GetAll { inner }
254    }
255
256    pub(crate) fn to_bytes(&self) -> Vec<u8> {
257        let mut buf = vec![];
258        buf.extend_from_slice(b"NATS/1.0\r\n");
259        for (k, vs) in &self.inner {
260            for v in vs.iter() {
261                buf.extend_from_slice(k.as_str().as_bytes());
262                buf.extend_from_slice(b": ");
263                buf.extend_from_slice(v.inner.as_bytes());
264                buf.extend_from_slice(b"\r\n");
265            }
266        }
267        buf.extend_from_slice(b"\r\n");
268        buf
269    }
270}
271
272/// Represents NATS header field value.
273///
274/// # Examples
275///
276/// ```
277/// # use async_nats::HeaderMap;
278///
279/// let mut headers = HeaderMap::new();
280/// headers.insert("Key", "Value");
281/// headers.insert("Another", "AnotherValue");
282/// ```
283#[derive(Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize)]
284#[serde(transparent)]
285pub struct HeaderValue {
286    inner: String,
287}
288
289impl fmt::Display for HeaderValue {
290    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
291        fmt::Display::fmt(&self.as_str(), f)
292    }
293}
294
295impl AsRef<[u8]> for HeaderValue {
296    fn as_ref(&self) -> &[u8] {
297        self.inner.as_ref()
298    }
299}
300
301impl AsRef<str> for HeaderValue {
302    fn as_ref(&self) -> &str {
303        self.as_str()
304    }
305}
306
307impl From<i16> for HeaderValue {
308    fn from(v: i16) -> Self {
309        Self {
310            inner: v.to_string(),
311        }
312    }
313}
314
315impl From<i32> for HeaderValue {
316    fn from(v: i32) -> Self {
317        Self {
318            inner: v.to_string(),
319        }
320    }
321}
322
323impl From<i64> for HeaderValue {
324    fn from(v: i64) -> Self {
325        Self {
326            inner: v.to_string(),
327        }
328    }
329}
330
331impl From<isize> for HeaderValue {
332    fn from(v: isize) -> Self {
333        Self {
334            inner: v.to_string(),
335        }
336    }
337}
338
339impl From<u16> for HeaderValue {
340    fn from(v: u16) -> Self {
341        Self {
342            inner: v.to_string(),
343        }
344    }
345}
346
347impl From<u32> for HeaderValue {
348    fn from(v: u32) -> Self {
349        Self {
350            inner: v.to_string(),
351        }
352    }
353}
354
355impl From<u64> for HeaderValue {
356    fn from(v: u64) -> Self {
357        Self {
358            inner: v.to_string(),
359        }
360    }
361}
362
363impl From<usize> for HeaderValue {
364    fn from(v: usize) -> Self {
365        Self {
366            inner: v.to_string(),
367        }
368    }
369}
370
371impl FromStr for HeaderValue {
372    type Err = ParseHeaderValueError;
373
374    fn from_str(s: &str) -> Result<Self, Self::Err> {
375        if s.contains(['\r', '\n']) {
376            return Err(ParseHeaderValueError);
377        }
378
379        Ok(HeaderValue {
380            inner: s.to_string(),
381        })
382    }
383}
384
385impl From<&str> for HeaderValue {
386    fn from(v: &str) -> Self {
387        assert!(
388            !v.contains(['\r', '\n']),
389            "invalid header value: cannot contain '\\r' or '\\n'"
390        );
391        Self {
392            inner: v.to_string(),
393        }
394    }
395}
396
397impl From<String> for HeaderValue {
398    fn from(inner: String) -> Self {
399        assert!(
400            !inner.contains(['\r', '\n']),
401            "invalid header value: cannot contain '\\r' or '\\n'"
402        );
403        Self { inner }
404    }
405}
406
407impl HeaderValue {
408    pub fn new() -> Self {
409        HeaderValue::default()
410    }
411
412    pub fn as_str(&self) -> &str {
413        self.inner.as_str()
414    }
415}
416
417#[derive(Debug, Clone)]
418pub struct ParseHeaderValueError;
419
420impl fmt::Display for ParseHeaderValueError {
421    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
422        write!(
423            f,
424            r#"invalid character found in header value (value cannot contain '\r' or '\n')"#
425        )
426    }
427}
428
429impl std::error::Error for ParseHeaderValueError {}
430
431pub trait IntoHeaderName {
432    fn into_header_name(self) -> HeaderName;
433}
434
435impl IntoHeaderName for &str {
436    fn into_header_name(self) -> HeaderName {
437        assert!(
438            !self.contains(|c: char| c == ':' || (c as u8) < 33 || (c as u8) > 126),
439            "invalid header name: cannot contain control characters, non-ASCII, or ':'"
440        );
441        match StandardHeader::from_bytes(self.as_bytes()) {
442            Some(v) => HeaderName {
443                inner: HeaderRepr::Standard(v),
444            },
445            None => HeaderName {
446                inner: HeaderRepr::Custom(self.into()),
447            },
448        }
449    }
450}
451
452impl IntoHeaderName for String {
453    fn into_header_name(self) -> HeaderName {
454        assert!(
455            !self.contains(|c: char| c == ':' || (c as u8) < 33 || (c as u8) > 126),
456            "invalid header name: cannot contain control characters, non-ASCII, or ':'"
457        );
458        match StandardHeader::from_bytes(self.as_bytes()) {
459            Some(v) => HeaderName {
460                inner: HeaderRepr::Standard(v),
461            },
462            None => HeaderName {
463                inner: HeaderRepr::Custom(self.into()),
464            },
465        }
466    }
467}
468
469impl IntoHeaderName for HeaderName {
470    fn into_header_name(self) -> HeaderName {
471        self
472    }
473}
474
475pub trait IntoHeaderValue {
476    fn into_header_value(self) -> HeaderValue;
477}
478
479impl IntoHeaderValue for &str {
480    fn into_header_value(self) -> HeaderValue {
481        HeaderValue::from(self)
482    }
483}
484
485impl IntoHeaderValue for String {
486    fn into_header_value(self) -> HeaderValue {
487        HeaderValue::from(self)
488    }
489}
490
491impl IntoHeaderValue for HeaderValue {
492    fn into_header_value(self) -> HeaderValue {
493        self
494    }
495}
496
497macro_rules! standard_headers {
498    (
499        $(
500            $(#[$docs:meta])*
501            ($variant:ident, $constant:ident, $bytes:literal);
502        )+
503    ) => {
504        #[allow(clippy::enum_variant_names)]
505        #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
506        enum StandardHeader {
507            $(
508                $variant,
509            )+
510        }
511
512        $(
513            $(#[$docs])*
514            pub const $constant: HeaderName = HeaderName {
515                inner: HeaderRepr::Standard(StandardHeader::$variant),
516            };
517        )+
518
519        impl StandardHeader {
520            #[inline]
521            fn as_str(&self) -> &'static str {
522                match *self {
523                    $(
524                    StandardHeader::$variant => unsafe { std::str::from_utf8_unchecked( $bytes ) },
525                    )+
526                }
527            }
528
529            const fn from_bytes(bytes: &[u8]) -> Option<StandardHeader> {
530                match bytes {
531                    $(
532                        $bytes => Some(StandardHeader::$variant),
533                    )+
534                    _ => None,
535                }
536            }
537        }
538
539        #[cfg(test)]
540        mod standard_header_tests {
541            use super::HeaderName;
542            use std::str::{self, FromStr};
543
544            const TEST_HEADERS: &'static [(&'static HeaderName, &'static [u8])] = &[
545                $(
546                (&super::$constant, $bytes),
547                )+
548            ];
549
550            #[test]
551            fn from_str() {
552                for &(header, bytes) in TEST_HEADERS {
553                    let utf8 = str::from_utf8(bytes).expect("string constants isn't utf8");
554                    assert_eq!(HeaderName::from_str(utf8).unwrap(), *header);
555                }
556            }
557        }
558    }
559}
560
561// Generate constants for all standard NATS headers.
562standard_headers! {
563    /// The name of the stream the message belongs to.
564    (NatsStream, NATS_STREAM, b"Nats-Stream");
565    /// The sequence number of the message within the stream.
566    (NatsSequence, NATS_SEQUENCE, b"Nats-Sequence");
567    /// The timestamp of when the message was sent.
568    (NatsTimeStamp, NATS_TIME_STAMP, b"Nats-Time-Stamp");
569    /// The subject of the message, used for routing and filtering messages.
570    (NatsSubject, NATS_SUBJECT, b"Nats-Subject");
571    /// A unique identifier for the message.
572    (NatsMessageId, NATS_MESSAGE_ID, b"Nats-Msg-Id");
573    /// The last known stream the message was part of.
574    (NatsLastStream, NATS_LAST_STREAM, b"Nats-Last-Stream");
575    /// The last known consumer that processed the message.
576    (NatsLastConsumer, NATS_LAST_CONSUMER, b"Nats-Last-Consumer");
577    /// The last known sequence number of the message.
578    (NatsLastSequence, NATS_LAST_SEQUENCE, b"Nats-Last-Sequence");
579    /// The expected last sequence number of the subject.
580    (NatsExpectedLastSubjectSequence, NATS_EXPECTED_LAST_SUBJECT_SEQUENCE, b"Nats-Expected-Last-Subject-Sequence");
581    /// The expected last message ID within the stream.
582    (NatsExpectedLastMessageId, NATS_EXPECTED_LAST_MESSAGE_ID, b"Nats-Expected-Last-Msg-Id");
583    /// The expected last sequence number within the stream.
584    (NatsExpectedLastSequence, NATS_EXPECTED_LAST_SEQUENCE, b"Nats-Expected-Last-Sequence");
585    /// The expected stream the message should be part of.
586    (NatsExpectedStream, NATS_EXPECTED_STREAM, b"Nats-Expected-Stream");
587    /// Sets the TTL for a single message.
588    (NatsMessageTtl, NATS_MESSAGE_TTL, b"Nats-TTL");
589    /// Reason why the delete marked on a stream with enabled markers was put.
590    (NatsMarkerReason, NATS_MARKER_REASON, b"Nats-Marker-Reason");
591}
592
593#[derive(Debug, Hash, PartialEq, Eq, Clone)]
594struct CustomHeader {
595    bytes: Bytes,
596}
597
598impl CustomHeader {
599    #[inline]
600    pub(crate) const fn from_static(value: &'static str) -> CustomHeader {
601        CustomHeader {
602            bytes: Bytes::from_static(value.as_bytes()),
603        }
604    }
605
606    #[inline]
607    pub(crate) fn as_str(&self) -> &str {
608        unsafe { std::str::from_utf8_unchecked(self.bytes.as_ref()) }
609    }
610}
611
612impl From<String> for CustomHeader {
613    #[inline]
614    fn from(value: String) -> CustomHeader {
615        CustomHeader {
616            bytes: Bytes::from(value),
617        }
618    }
619}
620
621impl<'a> From<&'a str> for CustomHeader {
622    #[inline]
623    fn from(value: &'a str) -> CustomHeader {
624        CustomHeader {
625            bytes: Bytes::copy_from_slice(value.as_bytes()),
626        }
627    }
628}
629
630#[derive(Debug, Hash, PartialEq, Eq, Clone)]
631enum HeaderRepr {
632    Standard(StandardHeader),
633    Custom(CustomHeader),
634}
635
636/// Defines a NATS header field name
637///
638/// Header field names identify the header. Header sets may include multiple
639/// headers with the same name.
640///
641/// # Representation
642///
643/// `HeaderName` represents standard header names using an `enum`, as such they
644/// will not require an allocation for storage.
645#[derive(Clone, PartialEq, Eq, Hash, Debug)]
646pub struct HeaderName {
647    inner: HeaderRepr,
648}
649
650impl HeaderName {
651    /// Converts a static string to a NATS header name.
652    #[inline]
653    pub const fn from_static(value: &'static str) -> HeaderName {
654        if let Some(standard) = StandardHeader::from_bytes(value.as_bytes()) {
655            return HeaderName {
656                inner: HeaderRepr::Standard(standard),
657            };
658        }
659
660        HeaderName {
661            inner: HeaderRepr::Custom(CustomHeader::from_static(value)),
662        }
663    }
664
665    /// Returns a `str` representation of the header.
666    #[inline]
667    fn as_str(&self) -> &str {
668        match self.inner {
669            HeaderRepr::Standard(v) => v.as_str(),
670            HeaderRepr::Custom(ref v) => v.as_str(),
671        }
672    }
673}
674
675impl FromStr for HeaderName {
676    type Err = ParseHeaderNameError;
677
678    fn from_str(s: &str) -> Result<Self, Self::Err> {
679        if s.contains(|c: char| c == ':' || (c as u8) < 33 || (c as u8) > 126) {
680            return Err(ParseHeaderNameError);
681        }
682
683        match StandardHeader::from_bytes(s.as_ref()) {
684            Some(v) => Ok(HeaderName {
685                inner: HeaderRepr::Standard(v),
686            }),
687            None => Ok(HeaderName {
688                inner: HeaderRepr::Custom(CustomHeader::from(s)),
689            }),
690        }
691    }
692}
693
694impl fmt::Display for HeaderName {
695    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
696        fmt::Display::fmt(&self.as_str(), f)
697    }
698}
699
700impl AsRef<[u8]> for HeaderName {
701    fn as_ref(&self) -> &[u8] {
702        self.as_str().as_bytes()
703    }
704}
705
706impl AsRef<str> for HeaderName {
707    fn as_ref(&self) -> &str {
708        self.as_str()
709    }
710}
711
712impl Serialize for HeaderName {
713    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
714    where
715        S: serde::Serializer,
716    {
717        serializer.serialize_str(self.as_str())
718    }
719}
720
721impl<'de> Deserialize<'de> for HeaderName {
722    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
723    where
724        D: serde::Deserializer<'de>,
725    {
726        String::deserialize(deserializer)?
727            .parse()
728            .map_err(serde::de::Error::custom)
729    }
730}
731
732#[derive(Debug, Clone)]
733pub struct ParseHeaderNameError;
734
735impl std::fmt::Display for ParseHeaderNameError {
736    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
737        write!(f, "invalid header name (name cannot contain non-ascii alphanumeric characters other than '-')")
738    }
739}
740
741impl std::error::Error for ParseHeaderNameError {}
742
743#[cfg(test)]
744mod tests {
745    use super::{HeaderMap, HeaderName, HeaderValue, IntoHeaderName, IntoHeaderValue};
746    use std::str::{from_utf8, FromStr};
747
748    #[test]
749    fn try_from() {
750        let mut headers = HeaderMap::new();
751        headers.insert("name", "something".parse::<HeaderValue>().unwrap());
752        headers.insert("name", "something2");
753    }
754
755    #[test]
756    fn append() {
757        let mut headers = HeaderMap::new();
758        headers.append("Key", "value");
759        headers.append("Key", "second_value");
760
761        let mut result = headers.get_all("Key");
762
763        assert_eq!(
764            result.next().unwrap(),
765            &HeaderValue::from_str("value").unwrap()
766        );
767
768        assert_eq!(
769            result.next().unwrap(),
770            &HeaderValue::from_str("second_value").unwrap()
771        );
772
773        assert_eq!(result.next(), None);
774    }
775
776    #[test]
777    fn get_string() {
778        let mut headers = HeaderMap::new();
779        headers.append("Key", "value");
780        headers.append("Key", "other");
781
782        assert_eq!(headers.get("Key").unwrap().to_string(), "value");
783
784        let key: String = headers.get("Key").unwrap().as_str().into();
785        assert_eq!(key, "value".to_string());
786
787        let key: String = headers.get("Key").unwrap().as_str().to_owned();
788        assert_eq!(key, "value".to_string());
789
790        assert_eq!(headers.get("Key").unwrap().as_str(), "value");
791
792        let key: String = headers.get_last("Key").unwrap().as_str().into();
793        assert_eq!(key, "other".to_string());
794    }
795
796    #[test]
797    fn insert() {
798        let mut headers = HeaderMap::new();
799        headers.insert("Key", "Value");
800
801        let mut result = headers.get_all("Key");
802
803        assert_eq!(
804            result.next().unwrap(),
805            &HeaderValue::from_str("Value").unwrap()
806        );
807        assert_eq!(result.next(), None);
808    }
809
810    #[test]
811    fn serialize() {
812        let mut headers = HeaderMap::new();
813        headers.append("Key", "value");
814        headers.append("Key", "second_value");
815        headers.insert("Second", "SecondValue");
816
817        let bytes = headers.to_bytes();
818
819        println!("bytes: {:?}", from_utf8(&bytes));
820    }
821
822    #[test]
823    fn is_empty() {
824        let mut headers = HeaderMap::new();
825        assert!(headers.is_empty());
826
827        headers.append("Key", "value");
828        headers.append("Key", "second_value");
829        headers.insert("Second", "SecondValue");
830        assert!(!headers.is_empty());
831    }
832
833    #[test]
834    fn parse_value() {
835        assert!("Foo\r".parse::<HeaderValue>().is_err());
836        assert!("Foo\n".parse::<HeaderValue>().is_err());
837        assert!("Foo\r\n".parse::<HeaderValue>().is_err());
838    }
839
840    #[test]
841    fn valid_header_name() {
842        let valid_header_name = "X-Custom-Header";
843        let parsed_header = HeaderName::from_str(valid_header_name);
844
845        assert!(
846            parsed_header.is_ok(),
847            "Expected Ok(HeaderName), but got an error: {:?}",
848            parsed_header.err()
849        );
850    }
851
852    #[test]
853    fn dollar_header_name() {
854        let valid_header_name = "$X_Custom_Header";
855        let parsed_header = HeaderName::from_str(valid_header_name);
856
857        assert!(
858            parsed_header.is_ok(),
859            "Expected Ok(HeaderName), but got an error: {:?}",
860            parsed_header.err()
861        );
862    }
863
864    #[test]
865    fn invalid_header_name_with_space() {
866        let invalid_header_name = "X Custom Header";
867        let parsed_header = HeaderName::from_str(invalid_header_name);
868
869        assert!(
870            parsed_header.is_err(),
871            "Expected Err(InvalidHeaderNameError), but got Ok: {:?}",
872            parsed_header.ok()
873        );
874    }
875
876    #[test]
877    fn invalid_header_name_with_special_chars() {
878        let invalid_header_name = "X-Header:";
879        let parsed_header = HeaderName::from_str(invalid_header_name);
880
881        assert!(
882            parsed_header.is_err(),
883            "Expected Err(InvalidHeaderNameError), but got Ok: {:?}",
884            parsed_header.ok()
885        );
886    }
887
888    #[test]
889    fn from_static_eq() {
890        let a = HeaderName::from_static("NATS-Stream");
891        let b = HeaderName::from_static("NATS-Stream");
892
893        assert_eq!(a, b);
894    }
895
896    #[test]
897    fn header_name_serde() {
898        let raw = "Nats-Stream";
899        let raw_json = "\"Nats-Stream\"";
900        let header = HeaderName::from_static(raw);
901
902        // ser/de of HeaderName should be the same as raw string
903        assert_eq!(serde_json::to_string(&header).unwrap(), raw_json);
904        assert_eq!(
905            serde_json::from_str::<HeaderName>(raw_json).unwrap(),
906            header
907        );
908    }
909
910    #[test]
911    fn header_name_from_string() {
912        let string = "NATS-Stream".to_string();
913        let name = string.into_header_name();
914
915        assert_eq!("NATS-Stream", name.as_str());
916    }
917
918    #[test]
919    fn header_value_from_string_with_trait() {
920        let string = "some value".to_string();
921
922        let value = string.into_header_value();
923
924        assert_eq!("some value", value.as_str());
925    }
926
927    #[test]
928    fn header_value_from_string() {
929        let string = "some value".to_string();
930
931        let value: HeaderValue = string.into();
932
933        assert_eq!("some value", value.as_str());
934    }
935
936    #[test]
937    fn header_map_backward_compatible_deserialization() {
938        // Test new format (direct HashMap) - this is how it should serialize now
939        let new_format_json =
940            r#"{"Content-Type": ["application/json"], "Authorization": ["Bearer token"]}"#;
941        let header_map: HeaderMap = serde_json::from_str(new_format_json).unwrap();
942
943        assert_eq!(
944            header_map.get("Content-Type").unwrap().as_str(),
945            "application/json"
946        );
947        assert_eq!(
948            header_map.get("Authorization").unwrap().as_str(),
949            "Bearer token"
950        );
951
952        // Test legacy format (with "inner" wrapper) - this is the old format that should still work
953        let legacy_format_json = r#"{"inner": {"Content-Type": ["application/json"], "Authorization": ["Bearer token"]}}"#;
954        let header_map_legacy: HeaderMap = serde_json::from_str(legacy_format_json).unwrap();
955
956        assert_eq!(
957            header_map_legacy.get("Content-Type").unwrap().as_str(),
958            "application/json"
959        );
960        assert_eq!(
961            header_map_legacy.get("Authorization").unwrap().as_str(),
962            "Bearer token"
963        );
964
965        // Both should be equal after deserialization
966        assert_eq!(header_map, header_map_legacy);
967    }
968
969    #[test]
970    fn header_map_serialization_new_format() {
971        // Test that serialization uses the new format (no "inner" wrapper)
972        let mut headers = HeaderMap::new();
973        headers.insert("Content-Type", "application/json");
974        headers.insert("Authorization", "Bearer token");
975
976        let serialized = serde_json::to_string(&headers).unwrap();
977
978        // Should not contain "inner" key
979        assert!(!serialized.contains("inner"));
980
981        // Should be able to deserialize back
982        let deserialized: HeaderMap = serde_json::from_str(&serialized).unwrap();
983        assert_eq!(headers, deserialized);
984    }
985
986    #[test]
987    fn header_map_roundtrip_compatibility() {
988        // Test that we can roundtrip both formats
989        let mut original = HeaderMap::new();
990        original.insert("X-Custom-Header", "custom-value");
991        original.append("Multi-Value", "value1");
992        original.append("Multi-Value", "value2");
993
994        // Serialize using new format
995        let new_serialized = serde_json::to_string(&original).unwrap();
996        let new_deserialized: HeaderMap = serde_json::from_str(&new_serialized).unwrap();
997        assert_eq!(original, new_deserialized);
998
999        // Manually create legacy format JSON
1000        let legacy_json = format!(r#"{{"inner": {}}}"#, new_serialized);
1001        let legacy_deserialized: HeaderMap = serde_json::from_str(&legacy_json).unwrap();
1002        assert_eq!(original, legacy_deserialized);
1003    }
1004
1005    #[test]
1006    fn header_map_invalid_format_error() {
1007        // Test that invalid JSON returns proper error
1008        let invalid_json = r#"{"not_inner_or_direct": {"Content-Type": ["application/json"]}}"#;
1009        let result = serde_json::from_str::<HeaderMap>(invalid_json);
1010        assert!(result.is_err());
1011
1012        let error_message = result.unwrap_err().to_string();
1013        // With untagged enum, serde will report that data doesn't match any variant
1014        assert!(error_message.contains("did not match any variant"));
1015    }
1016
1017    #[test]
1018    fn header_map_empty_cases() {
1019        // Test empty HeaderMap serialization/deserialization
1020        let empty = HeaderMap::new();
1021        let serialized = serde_json::to_string(&empty).unwrap();
1022        assert_eq!(serialized, "{}");
1023
1024        let deserialized: HeaderMap = serde_json::from_str("{}").unwrap();
1025        assert!(deserialized.is_empty());
1026
1027        // Test legacy empty format
1028        let legacy_empty = r#"{"inner": {}}"#;
1029        let legacy_deserialized: HeaderMap = serde_json::from_str(legacy_empty).unwrap();
1030        assert!(legacy_deserialized.is_empty());
1031    }
1032
1033    #[test]
1034    fn header_map_mixed_legacy_detection() {
1035        // Test that an "inner" header name doesn't confuse the deserializer
1036        // This would be a new format where "inner" is a legitimate header name
1037        let json_with_inner_header =
1038            r#"{"inner": ["some-value"], "Other-Header": ["other-value"]}"#;
1039        let header_map: HeaderMap = serde_json::from_str(json_with_inner_header).unwrap();
1040
1041        // Should have two headers
1042        assert_eq!(header_map.len(), 2);
1043        assert_eq!(header_map.get("inner").unwrap().as_str(), "some-value");
1044        assert_eq!(
1045            header_map.get("Other-Header").unwrap().as_str(),
1046            "other-value"
1047        );
1048    }
1049
1050    #[test]
1051    #[should_panic(expected = "invalid header value")]
1052    fn header_value_from_str_rejects_cr() {
1053        let _: HeaderValue = "value\rwith\rcr".into();
1054    }
1055
1056    #[test]
1057    #[should_panic(expected = "invalid header value")]
1058    fn header_value_from_str_rejects_lf() {
1059        let _: HeaderValue = "value\nwith\nlf".into();
1060    }
1061
1062    #[test]
1063    #[should_panic(expected = "invalid header value")]
1064    fn header_value_from_string_rejects_crlf() {
1065        let _: HeaderValue = "injected\r\nPUB attack 0\r\n\r\n".to_string().into();
1066    }
1067
1068    #[test]
1069    #[should_panic(expected = "invalid header value")]
1070    fn header_value_into_trait_rejects_crlf() {
1071        let mut headers = HeaderMap::new();
1072        headers.insert("Key", "value\r\nPUB attack 0\r\n\r\n");
1073    }
1074
1075    #[test]
1076    #[should_panic(expected = "invalid header name")]
1077    fn header_name_into_trait_rejects_cr() {
1078        let mut headers = HeaderMap::new();
1079        headers.insert("Bad\rName", "value");
1080    }
1081
1082    #[test]
1083    #[should_panic(expected = "invalid header name")]
1084    fn header_name_into_trait_rejects_lf() {
1085        let mut headers = HeaderMap::new();
1086        headers.insert("Bad\nName", "value");
1087    }
1088
1089    #[test]
1090    #[should_panic(expected = "invalid header name")]
1091    fn header_name_into_trait_rejects_space() {
1092        let mut headers = HeaderMap::new();
1093        headers.insert("Bad Name", "value");
1094    }
1095
1096    #[test]
1097    #[should_panic(expected = "invalid header name")]
1098    fn header_name_into_trait_rejects_colon() {
1099        let mut headers = HeaderMap::new();
1100        headers.insert("Bad:Name", "value");
1101    }
1102
1103    #[test]
1104    #[should_panic(expected = "invalid header name")]
1105    fn header_name_from_string_rejects_control_chars() {
1106        let name = "Bad\x00Name".to_string();
1107        name.into_header_name();
1108    }
1109
1110    #[test]
1111    fn valid_header_values_still_work() {
1112        let _: HeaderValue = "normal value".into();
1113        let _: HeaderValue = "value with special chars !@#$%^&*()".into();
1114        let _: HeaderValue = "".into();
1115        let _: HeaderValue = String::from("string value").into();
1116    }
1117
1118    #[test]
1119    fn valid_header_names_still_work() {
1120        let mut headers = HeaderMap::new();
1121        headers.insert("X-Custom-Header", "value");
1122        headers.insert("Another-Header", "value");
1123        headers.insert("$dollar", "value");
1124        headers.insert("Nats-Stream", "value");
1125        assert_eq!(headers.get("Nats-Stream").unwrap().as_str(), "value");
1126    }
1127
1128    #[test]
1129    fn header_map_large_headers() {
1130        // Test with many headers
1131        let mut headers = HeaderMap::new();
1132        for i in 0..100 {
1133            headers.insert(format!("Header-{}", i), format!("Value-{}", i));
1134        }
1135
1136        let serialized = serde_json::to_string(&headers).unwrap();
1137        let deserialized: HeaderMap = serde_json::from_str(&serialized).unwrap();
1138
1139        assert_eq!(headers.len(), deserialized.len());
1140        for i in 0..100 {
1141            assert_eq!(
1142                deserialized
1143                    .get(format!("Header-{}", i).as_str())
1144                    .unwrap()
1145                    .as_str(),
1146                format!("Value-{}", i)
1147            );
1148        }
1149    }
1150}