Skip to main content

httpsig/message_component/
component_name.rs

1use crate::error::{HttpSigError, HttpSigResult};
2use sfv::BareItem;
3
4/* ---------------------------------------------------------------- */
5#[derive(PartialEq, Eq, Hash, Debug, Clone)]
6/// Http message component identifier
7pub enum HttpMessageComponentName {
8  /// Http field component, which is in the form of `<field_name>` without being wrapped by double quotations
9  HttpField(String),
10  /// Derived component
11  Derived(DerivedComponentName),
12}
13
14impl TryFrom<&BareItem> for HttpMessageComponentName {
15  type Error = HttpSigError;
16  fn try_from(value: &BareItem) -> HttpSigResult<Self> {
17    match value {
18      BareItem::String(name) => {
19        if name.as_str().starts_with('@') {
20          Ok(Self::Derived(DerivedComponentName::from(name.as_str())))
21        } else {
22          Ok(Self::HttpField(name.to_string()))
23        }
24      }
25      _ => Err(HttpSigError::InvalidComponentName(format!(
26        "Invalid http message component name: {value:?}"
27      ))),
28    }
29  }
30}
31
32impl std::fmt::Display for HttpMessageComponentName {
33  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34    match self {
35      Self::HttpField(val) => write!(f, "\"{}\"", val),
36      Self::Derived(val) => write!(f, "\"{}\"", val),
37    }
38  }
39}
40
41/* ---------------------------------------------------------------- */
42#[derive(PartialEq, Eq, Clone, Hash, Debug)]
43/// Derive components from http message, which is expressed as @method, @path, @authority, etc. in @signature-params
44/// https://datatracker.ietf.org/doc/html/rfc9421#name-derived-components
45pub enum DerivedComponentName {
46  Method,
47  TargetUri,
48  Authority,
49  Scheme,
50  RequestTarget,
51  Path,
52  Query,
53  QueryParam,
54  Status,
55  SignatureParams,
56}
57impl AsRef<str> for DerivedComponentName {
58  fn as_ref(&self) -> &str {
59    match self {
60      Self::Method => "@method",
61      Self::TargetUri => "@target-uri",
62      Self::Authority => "@authority",
63      Self::Scheme => "@scheme",
64      Self::RequestTarget => "@request-target",
65      Self::Path => "@path",
66      Self::Query => "@query",
67      Self::QueryParam => "@query-param",
68      Self::Status => "@status",
69      Self::SignatureParams => "@signature-params",
70    }
71  }
72}
73impl From<DerivedComponentName> for String {
74  fn from(val: DerivedComponentName) -> Self {
75    val.as_ref().to_string()
76  }
77}
78impl From<&str> for DerivedComponentName {
79  fn from(val: &str) -> Self {
80    match val {
81      "@method" => Self::Method,
82      "@target-uri" => Self::TargetUri,
83      "@authority" => Self::Authority,
84      "@scheme" => Self::Scheme,
85      "@request-target" => Self::RequestTarget,
86      "@path" => Self::Path,
87      "@query" => Self::Query,
88      "@query-param" => Self::QueryParam,
89      "@status" => Self::Status,
90      "@signature-params" => Self::SignatureParams,
91      _ => panic!("Invalid derived component: {}", val),
92    }
93  }
94}
95
96impl std::fmt::Display for DerivedComponentName {
97  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98    write!(f, "{}", AsRef::<str>::as_ref(self))
99  }
100}