Skip to content

Commit f6db203

Browse files
committed
perf: use static strings for static error messages
1 parent 2b5da9b commit f6db203

9 files changed

Lines changed: 117 additions & 110 deletions

File tree

httpsig-hyper/src/error.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::borrow::Cow;
2+
13
use httpsig::prelude::HttpSigError;
24
use thiserror::Error;
35

@@ -9,7 +11,7 @@ pub type HyperSigResult<T> = std::result::Result<T, HyperSigError>;
911
pub enum HyperSigError {
1012
/// No signature headers found
1113
#[error("No signature headers found: {0}")]
12-
NoSignatureHeaders(String),
14+
NoSignatureHeaders(&'static str),
1315

1416
/// Failed to parse signature headers
1517
#[error("Failed to stringify signature headers: {0}")]
@@ -21,15 +23,15 @@ pub enum HyperSigError {
2123

2224
/// Invalid component name
2325
#[error("Invalid component name: {0}")]
24-
InvalidComponentName(String),
26+
InvalidComponentName(Cow<'static, str>),
2527

2628
/// Invalid component param
2729
#[error("Invalid component param: {0}")]
2830
InvalidComponentParam(String),
2931

3032
/// Invalid signature
3133
#[error("Invalid signature: {0}")]
32-
InvalidSignature(String),
34+
InvalidSignature(&'static str),
3335

3436
/// Inherited from HttpSigError
3537
#[error("HttpSigError: {0}")]

httpsig-hyper/src/hyper_http.rs

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ where
337337
{
338338
if !self.has_message_signature() {
339339
return Err(HyperSigError::NoSignatureHeaders(
340-
"The request does not have signature and signature-input headers".to_string(),
340+
"The request does not have signature and signature-input headers",
341341
));
342342
}
343343
let map_signature_with_base = self.extract_signatures()?;
@@ -468,7 +468,7 @@ where
468468
{
469469
if !self.has_message_signature() {
470470
return Err(HyperSigError::NoSignatureHeaders(
471-
"The response does not have signature and signature-input headers".to_string(),
471+
"The response does not have signature and signature-input headers",
472472
));
473473
}
474474
let map_signature_with_base = self.extract_signatures(req_for_param)?;
@@ -615,8 +615,8 @@ fn get_alg_key_ids_inner<B>(
615615
let alg = headers
616616
.signature_params()
617617
.alg
618-
.clone()
619-
.map(|a| AlgorithmName::from_str(&a))
618+
.as_ref()
619+
.map(|a| AlgorithmName::from_str(a))
620620
.transpose()
621621
.ok()
622622
.flatten();
@@ -646,11 +646,11 @@ fn extract_signatures_inner<B1, B2>(
646646
) -> HyperSigResult<IndexMap<SignatureName, (HttpSignatureBase, HttpSignatureHeaders)>> {
647647
let signature_headers_map = extract_signature_headers_with_name(req_or_res)?;
648648
let extracted = signature_headers_map
649-
.iter()
649+
.into_iter()
650650
.filter_map(|(name, headers)| {
651651
build_signature_base(req_or_res, headers.signature_params(), req_for_param)
652652
.ok()
653-
.map(|base| (name.clone(), (base, headers.clone())))
653+
.map(|base| (name, (base, headers)))
654654
})
655655
.collect();
656656
Ok(extracted)
@@ -679,7 +679,7 @@ where
679679
async move {
680680
if filtered.is_empty() {
681681
return Err(HyperSigError::NoSignatureHeaders(
682-
"No signature as appropriate target for verification".to_string(),
682+
"No signature as appropriate target for verification",
683683
));
684684
}
685685
// check if any one of the signature headers is valid
@@ -690,9 +690,7 @@ where
690690
if !successful_sig_names.is_empty() {
691691
Ok(successful_sig_names.first().unwrap().clone())
692692
} else {
693-
Err(HyperSigError::InvalidSignature(
694-
"Invalid signature for the verifying key".to_string(),
695-
))
693+
Err(HyperSigError::InvalidSignature("Invalid signature for the verifying key"))
696694
}
697695
}
698696
});
@@ -712,16 +710,14 @@ impl<B> RequestOrResponse<'_, B> {
712710
fn method(&self) -> HyperSigResult<&http::Method> {
713711
match self {
714712
RequestOrResponse::Request(req) => Ok(req.method()),
715-
_ => Err(HyperSigError::InvalidComponentName(
716-
"`method` is only for request".to_string(),
717-
)),
713+
_ => Err(HyperSigError::InvalidComponentName("`method` is only for request".into())),
718714
}
719715
}
720716

721717
fn uri(&self) -> HyperSigResult<&http::Uri> {
722718
match self {
723719
RequestOrResponse::Request(req) => Ok(req.uri()),
724-
_ => Err(HyperSigError::InvalidComponentName("`uri` is only for request".to_string())),
720+
_ => Err(HyperSigError::InvalidComponentName("`uri` is only for request".into())),
725721
}
726722
}
727723

@@ -735,9 +731,7 @@ impl<B> RequestOrResponse<'_, B> {
735731
fn status(&self) -> HyperSigResult<http::StatusCode> {
736732
match self {
737733
RequestOrResponse::Response(res) => Ok(res.status()),
738-
_ => Err(HyperSigError::InvalidComponentName(
739-
"`status` is only for response".to_string(),
740-
)),
734+
_ => Err(HyperSigError::InvalidComponentName("`status` is only for response".into())),
741735
}
742736
}
743737
}
@@ -747,7 +741,7 @@ fn extract_signature_headers_with_name<B>(req_or_res: &RequestOrResponse<B>) ->
747741
let headers = req_or_res.headers();
748742
if !(headers.contains_key("signature-input") && headers.contains_key("signature")) {
749743
return Err(HyperSigError::NoSignatureHeaders(
750-
"The request does not have signature and signature-input headers".to_string(),
744+
"The request does not have signature and signature-input headers",
751745
));
752746
};
753747

@@ -800,14 +794,14 @@ fn build_signature_base<B1, B2>(
800794
})
801795
.collect::<Result<Vec<_>, _>>()?;
802796

803-
HttpSignatureBase::try_new(&component_lines, signature_params).map_err(|e| e.into())
797+
HttpSignatureBase::try_new(component_lines, signature_params).map_err(|e| e.into())
804798
}
805799

806800
/// Extract http field from hyper http request/response
807801
fn extract_http_field<B>(req_or_res: &RequestOrResponse<B>, id: &HttpMessageComponentId) -> HyperSigResult<HttpMessageComponent> {
808802
let HttpMessageComponentName::HttpField(header_name) = &id.name else {
809803
return Err(HyperSigError::InvalidComponentName(
810-
"invalid http message component name as http field".to_string(),
804+
"invalid http message component name as http field".into(),
811805
));
812806
};
813807
let headers = match req_or_res {
@@ -821,7 +815,7 @@ fn extract_http_field<B>(req_or_res: &RequestOrResponse<B>, id: &HttpMessageComp
821815
.map(|v| v.to_str().map(|s| s.to_owned()))
822816
.collect::<Result<Vec<_>, _>>()?;
823817

824-
HttpMessageComponent::try_from((id, field_values.as_slice())).map_err(|e| e.into())
818+
HttpMessageComponent::try_from((id, field_values)).map_err(|e| e.into())
825819
}
826820

827821
/// Extract derived component from hyper http request/response
@@ -831,7 +825,7 @@ fn extract_derived_component<B>(
831825
) -> HyperSigResult<HttpMessageComponent> {
832826
let HttpMessageComponentName::Derived(derived_id) = &id.name else {
833827
return Err(HyperSigError::InvalidComponentName(
834-
"invalid http message component name as derived component".to_string(),
828+
"invalid http message component name as derived component".into(),
835829
));
836830
};
837831
// Validate parameters allowed on derived components (RFC 9421).
@@ -860,9 +854,7 @@ fn extract_derived_component<B>(
860854
match req_or_res {
861855
RequestOrResponse::Request(_) => {
862856
if matches!(derived_id, DerivedComponentName::Status) {
863-
return Err(HyperSigError::InvalidComponentName(
864-
"`status` is only for response".to_string(),
865-
));
857+
return Err(HyperSigError::InvalidComponentName("`status` is only for response".into()));
866858
}
867859
}
868860
RequestOrResponse::Response(_) => {
@@ -874,7 +866,7 @@ fn extract_derived_component<B>(
874866
&& !has_req
875867
{
876868
return Err(HyperSigError::InvalidComponentName(
877-
"derived components other than `@status` and `@signature-params` require `req` parameter for response".to_string(),
869+
"derived components other than `@status` and `@signature-params` require `req` parameter for response".into(),
878870
));
879871
}
880872
// `@status` must not have `req` parameter
@@ -924,7 +916,7 @@ fn extract_derived_component<B>(
924916
.collect::<Vec<_>>(),
925917
};
926918

927-
HttpMessageComponent::try_from((id, field_values.as_slice())).map_err(|e| e.into())
919+
HttpMessageComponent::try_from((id, field_values)).map_err(|e| e.into())
928920
}
929921

930922
/* --------------------------------------- */

httpsig-hyper/src/hyper_http_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ async fn test_extract_signature_params_from_request() {
116116
let component = extract_http_message_component(&req_or_res, &component_id).unwrap();
117117
assert_eq!(component.to_string(), "\"@signature-params\": (\"@method\" \"@authority\")");
118118
assert_eq!(component.value.to_string(), r##"("@method" "@authority")"##);
119-
assert_eq!(component.value.as_field_value(), r##"sig1=("@method" "@authority")"##);
119+
assert_eq!(component.value.to_field_value(), r##"sig1=("@method" "@authority")"##);
120120
assert_eq!(component.value.as_component_value(), r##"("@method" "@authority")"##);
121121
assert_eq!(component.value.key(), Some("sig1"));
122122
}

httpsig/src/error.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::borrow::Cow;
2+
13
use thiserror::Error;
24

35
/// Result type for http signature
@@ -38,16 +40,16 @@ pub enum HttpSigError {
3840
InvalidComponentId(String),
3941
/// Invalid http message component
4042
#[error("Invalid http message component: {0}")]
41-
InvalidComponent(String),
43+
InvalidComponent(Cow<'static, str>),
4244

4345
/* ----- Signature params errors ----- */
4446
/// Invalid signature params
4547
#[error("Invalid signature params: {0}")]
46-
InvalidSignatureParams(String),
48+
InvalidSignatureParams(&'static str),
4749

4850
/// Error in building signature header
4951
#[error("Failed to build signature header: {0}")]
50-
BuildSignatureHeaderError(String),
52+
BuildSignatureHeaderError(&'static str),
5153

5254
/// Error in building signature base
5355
#[error("Failed to build signature base: {0}")]

httpsig/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ Signature: sig-b26=:wqcAqbmYJ2ji2glfAMaRy4gruYYnx2nEFN2HN6jrnDnQCK1u02Gb04v9EDgw
122122
.map(|&line| message_component::HttpMessageComponent::try_from(line).unwrap())
123123
.collect::<Vec<_>>();
124124

125-
let signature_base = HttpSignatureBase::try_new(&component_lines, &signature_params).unwrap();
125+
let signature_base = HttpSignatureBase::try_new(component_lines, &signature_params).unwrap();
126126
let sk = SecretKey::from_pem(&AlgorithmName::Ed25519, EDDSA_SECRET_KEY).unwrap();
127127
let pk = PublicKey::from_pem(&AlgorithmName::Ed25519, EDDSA_PUBLIC_KEY).unwrap();
128128

@@ -140,7 +140,7 @@ Signature: sig-b26=:wqcAqbmYJ2ji2glfAMaRy4gruYYnx2nEFN2HN6jrnDnQCK1u02Gb04v9EDgw
140140

141141
// sender
142142
let signature_params = HttpSignatureParams::try_from(SIGNATURE_PARAMS).unwrap();
143-
let signature_base = HttpSignatureBase::try_new(&component_lines, &signature_params).unwrap();
143+
let signature_base = HttpSignatureBase::try_new(component_lines.clone(), &signature_params).unwrap();
144144
let sk = SecretKey::from_pem(&AlgorithmName::Ed25519, EDDSA_SECRET_KEY).unwrap();
145145
let signature_headers = signature_base.build_signature_headers(&sk, Some("sig-b26")).unwrap();
146146
let signature_params_header_string = signature_headers.signature_input_header_value();
@@ -153,7 +153,7 @@ Signature: sig-b26=:wqcAqbmYJ2ji2glfAMaRy4gruYYnx2nEFN2HN6jrnDnQCK1u02Gb04v9EDgw
153153
let header_map = HttpSignatureHeaders::try_parse(&signature_header_string, &signature_params_header_string).unwrap();
154154
let received_signature_headers = header_map.get("sig-b26").unwrap();
155155
let received_signature_base =
156-
HttpSignatureBase::try_new(&component_lines, received_signature_headers.signature_params()).unwrap();
156+
HttpSignatureBase::try_new(component_lines, received_signature_headers.signature_params()).unwrap();
157157
let pk = PublicKey::from_pem(&AlgorithmName::Ed25519, EDDSA_PUBLIC_KEY).unwrap();
158158
let verification_result = received_signature_base.verify_signature_headers(&pk, received_signature_headers);
159159
assert!(verification_result.is_ok());

0 commit comments

Comments
 (0)