Skip to content

Commit 0d2c14c

Browse files
authored
Merge pull request #8 from junkurihara/deps/sfv-0.14
deps: sfv-0.14
2 parents 806c3df + 985566a commit 0d2c14c

File tree

8 files changed

+65
-46
lines changed

8 files changed

+65
-46
lines changed

httpsig-hyper/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ indexmap = { version = "2.11.1" }
2525

2626
# content digest with rfc8941 structured field values
2727
sha2 = { version = "0.10.9", default-features = false }
28-
sfv = { version = "0.10.4" }
28+
sfv = { version = "0.14.0" }
2929

3030
# encoding
3131
base64 = { version = "0.22.1" }

httpsig-hyper/src/hyper_content_digest.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ use bytes::Bytes;
55
use http::{Request, Response};
66
use http_body::Body;
77
use http_body_util::{combinators::BoxBody, BodyExt, Full};
8-
use sfv::FromStr;
98
use sha2::Digest;
109
use std::future::Future;
10+
use std::str::FromStr;
1111

1212
// hyper's http specific extension to generate and verify http signature
1313

@@ -209,20 +209,21 @@ async fn extract_content_digest(header_map: &http::HeaderMap) -> HyperDigestResu
209209
.get(CONTENT_DIGEST_HEADER)
210210
.ok_or(HyperDigestError::NoDigestHeader("No content-digest header".to_string()))?
211211
.to_str()?;
212-
let indexmap = sfv::Parser::parse_dictionary(content_digest_header.as_bytes())
212+
let indexmap = sfv::Parser::new(content_digest_header)
213+
.parse::<sfv::Dictionary>()
213214
.map_err(|e| HyperDigestError::InvalidHeaderValue(e.to_string()))?;
214215
if indexmap.len() != 1 {
215216
return Err(HyperDigestError::InvalidHeaderValue(
216217
"Content-Digest header should have only one value".to_string(),
217218
));
218219
};
219220
let (cd_type, cd) = indexmap.iter().next().unwrap();
220-
let cd_type = ContentDigestType::from_str(cd_type)
221+
let cd_type = ContentDigestType::from_str(cd_type.as_str())
221222
.map_err(|e| HyperDigestError::InvalidHeaderValue(format!("Invalid Content-Digest type: {e}")))?;
222223
if !matches!(
223224
cd,
224225
sfv::ListEntry::Item(sfv::Item {
225-
bare_item: sfv::BareItem::ByteSeq(_),
226+
bare_item: sfv::BareItem::ByteSequence(_),
226227
..
227228
})
228229
) {
@@ -233,7 +234,7 @@ async fn extract_content_digest(header_map: &http::HeaderMap) -> HyperDigestResu
233234

234235
let cd = match cd {
235236
sfv::ListEntry::Item(sfv::Item {
236-
bare_item: sfv::BareItem::ByteSeq(cd),
237+
bare_item: sfv::BareItem::ByteSequence(cd),
237238
..
238239
}) => cd,
239240
_ => unreachable!(),

httpsig/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ bytes = { version = "1.10.1" }
4545
base64 = { version = "0.22.1" }
4646

4747
# for rfc8941 structured field values
48-
sfv = { version = "0.10.4" }
48+
sfv = { version = "0.14.0" }
4949

5050
[dev-dependencies]
5151
rand-085 = { package = "rand", version = "0.8.5" } # testing only

httpsig/src/message_component/component_id.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,17 @@ impl TryFrom<&str> for HttpMessageComponentId {
3535
/// But accept string in the form of `<name>` (without double quotations) when no param is given
3636
fn try_from(val: &str) -> HttpSigResult<Self> {
3737
let val = val.trim();
38-
let item = if !val.starts_with('"') && !val.ends_with('"') && !val.is_empty() && !val.contains('"') {
38+
let item: sfv::Item = if !val.starts_with('"') && !val.ends_with('"') && !val.is_empty() && !val.contains('"') {
3939
// maybe insufficient, but it's enough for now
40-
Parser::parse_item(format!("\"{val}\"").as_bytes()).map_err(|e| HttpSigError::ParseSFVError(e.to_string()))?
40+
Parser::new(format!("\"{val}\"").as_str())
41+
.parse()
42+
.map_err(|e| HttpSigError::ParseSFVError(e.to_string()))?
43+
// Parser::parse_item(format!("\"{val}\"").as_bytes()).map_err(|e| HttpSigError::ParseSFVError(e.to_string()))?
4144
} else {
42-
Parser::parse_item(val.as_bytes()).map_err(|e| HttpSigError::ParseSFVError(e.to_string()))?
45+
Parser::new(val)
46+
.parse()
47+
.map_err(|e| HttpSigError::ParseSFVError(e.to_string()))?
48+
// Parser::parse_item(val.as_bytes()).map_err(|e| HttpSigError::ParseSFVError(e.to_string()))?
4349
};
4450

4551
let res = Self {

httpsig/src/message_component/component_name.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ impl TryFrom<&BareItem> for HttpMessageComponentName {
1616
fn try_from(value: &BareItem) -> HttpSigResult<Self> {
1717
match value {
1818
BareItem::String(name) => {
19-
if name.starts_with('@') {
19+
if name.as_str().starts_with('@') {
2020
Ok(Self::Derived(DerivedComponentName::from(name.as_str())))
2121
} else {
2222
Ok(Self::HttpField(name.to_string()))

httpsig/src/message_component/component_param.rs

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::error::{HttpSigError, HttpSigResult};
2-
use sfv::{Parser, SerializeValue};
2+
use sfv::{FieldType, Parser};
33

44
type IndexSet<K> = indexmap::IndexSet<K, rustc_hash::FxBuildHasher>;
55

@@ -46,13 +46,13 @@ impl TryFrom<(&str, &sfv::BareItem)> for HttpMessageComponentParam {
4646
"tr" => Ok(Self::Tr),
4747
"req" => Ok(Self::Req),
4848
"name" => {
49-
let name = val.as_str().ok_or(HttpSigError::InvalidComponentParam(
49+
let name = val.as_string().ok_or(HttpSigError::InvalidComponentParam(
5050
"Invalid http field param: name".to_string(),
5151
))?;
5252
Ok(Self::Name(name.to_string()))
5353
}
5454
"key" => {
55-
let key = val.as_str().ok_or(HttpSigError::InvalidComponentParam(
55+
let key = val.as_string().ok_or(HttpSigError::InvalidComponentParam(
5656
"Invalid http field param: key".to_string(),
5757
))?;
5858
Ok(Self::Key(key.to_string()))
@@ -106,10 +106,10 @@ pub(super) fn handle_params_sf(field_values: &mut [String]) -> HttpSigResult<()>
106106
let parsed_list = field_values
107107
.iter()
108108
.map(|v| {
109-
if let Ok(list) = Parser::parse_list(v.as_bytes()) {
110-
list.serialize_value()
111-
} else if let Ok(dict) = Parser::parse_dictionary(v.as_bytes()) {
112-
dict.serialize_value()
109+
if let Ok(list) = Parser::new(v).parse::<sfv::List>() {
110+
list.serialize().ok_or("Failed to serialize structured field value for sf")
111+
} else if let Ok(dict) = Parser::new(v).parse::<sfv::Dictionary>() {
112+
dict.serialize().ok_or("Failed to serialize structured field value for sf")
113113
} else {
114114
Err("invalid structured field value for sf")
115115
}
@@ -129,7 +129,8 @@ pub(super) fn handle_params_sf(field_values: &mut [String]) -> HttpSigResult<()>
129129
pub(super) fn handle_params_key_into(field_values: &[String], key: &str) -> HttpSigResult<Vec<String>> {
130130
let dicts = field_values
131131
.iter()
132-
.map(|v| Parser::parse_dictionary(v.as_bytes()))
132+
.map(|v| Parser::new(v.as_str()).parse() as Result<sfv::Dictionary, _>)
133+
// Parser::parse_dictionary(v.as_bytes()))
133134
.collect::<Result<Vec<_>, _>>()
134135
.map_err(|e| HttpSigError::InvalidComponentParam(format!("Failed to parse structured field value: {e}")))?;
135136

@@ -138,11 +139,12 @@ pub(super) fn handle_params_key_into(field_values: &[String], key: &str) -> Http
138139
.filter_map(|dict| {
139140
dict.get(key).map(|v| {
140141
let sfvalue: sfv::List = vec![v.clone()];
141-
sfvalue.serialize_value()
142+
// sfvalue.serialize_value()
143+
sfvalue.serialize()
142144
})
143145
})
144-
.collect::<Result<Vec<_>, _>>()
145-
.map_err(|e| HttpSigError::InvalidComponentParam(format!("Failed to serialize structured field value: {e}")))?;
146+
.collect::<Option<Vec<_>>>()
147+
.ok_or_else(|| HttpSigError::InvalidComponentParam(format!("Failed to serialize structured field value")))?;
146148

147149
Ok(found_entries)
148150
}
@@ -157,19 +159,19 @@ mod tests {
157159
fn parser_test() {
158160
// Parsing structured field value of Item type.
159161
let item_header_input = "12.445;foo=bar";
160-
let item = Parser::parse_item(item_header_input.as_bytes()).unwrap();
161-
assert_eq!(item.serialize_value().unwrap(), item_header_input);
162+
let item = Parser::new(item_header_input).parse::<sfv::Item>().unwrap();
163+
assert_eq!(item.serialize(), item_header_input);
162164

163165
// Parsing structured field value of List type.
164166
let list_header_input = " 1; a=tok, (\"foo\" \"bar\" );baz, ( )";
165-
let list = Parser::parse_list(list_header_input.as_bytes()).unwrap();
166-
assert_eq!(list.serialize_value().unwrap(), "1;a=tok, (\"foo\" \"bar\");baz, ()");
167+
let list = Parser::new(list_header_input).parse::<sfv::List>().unwrap();
168+
assert_eq!(list.serialize().unwrap(), "1;a=tok, (\"foo\" \"bar\");baz, ()");
167169

168170
// Parsing structured field value of Dictionary type.
169171
let dict_header_input = "a=?0, b, c; foo=bar, rating=1.5, fruits=(apple pear), d";
170-
let dict = Parser::parse_dictionary(dict_header_input.as_bytes()).unwrap();
172+
let dict = Parser::new(dict_header_input).parse::<sfv::Dictionary>().unwrap();
171173
assert_eq!(
172-
dict.serialize_value().unwrap(),
174+
dict.serialize().unwrap(),
173175
"a=?0, b, c;foo=bar, rating=1.5, fruits=(apple pear), d"
174176
);
175177
}

httpsig/src/signature_base.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ use crate::{
66
signature_params::HttpSignatureParams,
77
};
88
use base64::{engine::general_purpose, Engine as _};
9-
use rustc_hash::FxBuildHasher;
109
use indexmap::IndexMap;
10+
use rustc_hash::FxBuildHasher;
1111
use sfv::{BareItem, Item, ListEntry, Parser};
1212

1313
/// IndexMap of signature name and HttpSignatureHeaders
@@ -30,10 +30,16 @@ pub struct HttpSignatureHeaders {
3030
impl HttpSignatureHeaders {
3131
/// Generates (possibly multiple) HttpSignatureHeaders from signature and signature-input header values
3232
pub fn try_parse(signature_header: &str, signature_input_header: &str) -> HttpSigResult<HttpSignatureHeadersMap> {
33-
let signature_input =
34-
Parser::parse_dictionary(signature_input_header.as_bytes()).map_err(|e| HttpSigError::ParseSFVError(e.to_string()))?;
35-
let signature =
36-
Parser::parse_dictionary(signature_header.as_bytes()).map_err(|e| HttpSigError::ParseSFVError(e.to_string()))?;
33+
let signature_input: sfv::Dictionary = Parser::new(signature_input_header)
34+
.parse()
35+
.map_err(|e| HttpSigError::ParseSFVError(e.to_string()))?;
36+
let signature: sfv::Dictionary = Parser::new(signature_header)
37+
.parse()
38+
.map_err(|e| HttpSigError::ParseSFVError(e.to_string()))?;
39+
// let signature_input =
40+
// Parser::parse_dictionary(signature_input_header.as_bytes()).map_err(|e| HttpSigError::ParseSFVError(e.to_string()))?;
41+
// let signature =
42+
// Parser::parse_dictionary(signature_header.as_bytes()).map_err(|e| HttpSigError::ParseSFVError(e.to_string()))?;
3743

3844
if signature.len() != signature_input.len() {
3945
return Err(HttpSigError::BuildSignatureHeaderError(
@@ -50,7 +56,7 @@ impl HttpSignatureHeaders {
5056
matches!(
5157
v,
5258
ListEntry::Item(Item {
53-
bare_item: BareItem::ByteSeq(_),
59+
bare_item: BareItem::ByteSequence(_),
5460
..
5561
})
5662
)
@@ -73,7 +79,7 @@ impl HttpSignatureHeaders {
7379

7480
let signature_bytes = match signature.get(k) {
7581
Some(ListEntry::Item(Item {
76-
bare_item: BareItem::ByteSeq(v),
82+
bare_item: BareItem::ByteSequence(v),
7783
..
7884
})) => v,
7985
_ => unreachable!(),

httpsig/src/signature_params.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::{
77
};
88
use base64::{engine::general_purpose, Engine as _};
99
use rand::Rng;
10-
use sfv::{ListEntry, Parser, SerializeValue};
10+
use sfv::{FieldType, ListEntry, Parser};
1111
use std::time::{SystemTime, UNIX_EPOCH};
1212

1313
const DEFAULT_DURATION: u64 = 300;
@@ -167,9 +167,10 @@ impl TryFrom<&ListEntry> for HttpSignatureParams {
167167
.items
168168
.iter()
169169
.map(|v| {
170-
v.serialize_value()
171-
.map_err(|e| HttpSigError::ParseSFVError(e.to_string()))
172-
.and_then(|v| HttpMessageComponentId::try_from(v.as_str()))
170+
HttpMessageComponentId::try_from(v.serialize().as_str())
171+
// v.serialize_value()
172+
// .map_err(|e| HttpSigError::ParseSFVError(e.to_string()))
173+
// .and_then(|v| HttpMessageComponentId::try_from(v.as_str()))
173174
})
174175
.collect::<Result<Vec<_>, _>>()?;
175176

@@ -193,12 +194,12 @@ impl TryFrom<&ListEntry> for HttpSignatureParams {
193194
.params
194195
.iter()
195196
.for_each(|(key, bare_item)| match key.as_str() {
196-
"created" => params.created = bare_item.as_int().map(|v| v as u64),
197-
"expires" => params.expires = bare_item.as_int().map(|v| v as u64),
198-
"nonce" => params.nonce = bare_item.as_str().map(|v| v.to_string()),
199-
"alg" => params.alg = bare_item.as_str().map(|v| v.to_string()),
200-
"keyid" => params.keyid = bare_item.as_str().map(|v| v.to_string()),
201-
"tag" => params.tag = bare_item.as_str().map(|v| v.to_string()),
197+
"created" => params.created = bare_item.as_integer().map(|v| v.try_into().unwrap()),
198+
"expires" => params.expires = bare_item.as_integer().map(|v| v.try_into().unwrap()),
199+
"nonce" => params.nonce = bare_item.as_string().map(|v| v.to_string()),
200+
"alg" => params.alg = bare_item.as_string().map(|v| v.to_string()),
201+
"keyid" => params.keyid = bare_item.as_string().map(|v| v.to_string()),
202+
"tag" => params.tag = bare_item.as_string().map(|v| v.to_string()),
202203
_ => {
203204
error!("Ignore invalid signature parameter: {}", key)
204205
}
@@ -211,7 +212,10 @@ impl TryFrom<&str> for HttpSignatureParams {
211212
type Error = HttpSigError;
212213
/// Convert from string to HttpSignatureParams
213214
fn try_from(value: &str) -> HttpSigResult<Self> {
214-
let sfv_parsed = Parser::parse_list(value.as_bytes()).map_err(|e| HttpSigError::ParseSFVError(e.to_string()))?;
215+
let sfv_parsed: sfv::List = Parser::new(value)
216+
.parse()
217+
.map_err(|e| HttpSigError::ParseSFVError(e.to_string()))?;
218+
// let sfv_parsed = Parser::parse_list(value.as_bytes()).map_err(|e| HttpSigError::ParseSFVError(e.to_string()))?;
215219
if sfv_parsed.len() != 1 || !matches!(sfv_parsed[0], ListEntry::InnerList(_)) {
216220
return Err(HttpSigError::InvalidSignatureParams("Invalid signature params".to_string()));
217221
}

0 commit comments

Comments
 (0)