Skip to content

Move shared response processing code to ohttp.rs#660

Merged
spacebear21 merged 2 commits intopayjoin:masterfrom
spacebear21:ohttp-reqs-refactor
Jun 6, 2025
Merged

Move shared response processing code to ohttp.rs#660
spacebear21 merged 2 commits intopayjoin:masterfrom
spacebear21:ohttp-reqs-refactor

Conversation

@spacebear21
Copy link
Collaborator

The process_res methods across send and receive have a lot of shared code that can be extracted into reusable functions. process_get_res and process_post_res essentially do the same thing, and could conceivably be combined into one function. They were kept separate because "202 Accepted" is not a valid response for POST requests.

@spacebear21
Copy link
Collaborator Author

Leaving in draft for now because some follow-up items need to be addressed:

  • process_response methods return inconsistent error types when POSTing vs. GETting, specifically: EncapsulationError vs. ResponseError for send and SessionError vs. Error for receive.
  • There are four duplicated variants between InternalEncapsulationError and InternalSessionError.
    • Also, EncapsulationError is a misnomer since it afaict it's exclusively raised when decapsulating responses.
    • The Hpke variant has nothing to do with en/decapsulation.

@coveralls
Copy link
Collaborator

coveralls commented Apr 18, 2025

Pull Request Test Coverage Report for Build 15500115610

Details

  • 51 of 75 (68.0%) changed or added relevant lines in 5 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-0.01%) to 85.043%

Changes Missing Coverage Covered Lines Changed/Added Lines %
payjoin/src/receive/v2/error.rs 0 2 0.0%
payjoin/src/send/v2/error.rs 0 3 0.0%
payjoin/src/ohttp.rs 28 47 59.57%
Totals Coverage Status
Change from base Build 15449709719: -0.01%
Covered Lines: 6772
Relevant Lines: 7963

💛 - Coveralls

@spacebear21 spacebear21 force-pushed the ohttp-reqs-refactor branch from d72153b to 141b559 Compare June 5, 2025 21:49
@DanGould
Copy link
Contributor

DanGould commented Jun 6, 2025

are there other from conversions that can be deleted?

@spacebear21
Copy link
Collaborator Author

The error audit I mentioned in my other comment can be addressed later in a follow-up, I'll make a new issue.

are there other from conversions that can be deleted?

I had a second commit locally that I hadn't pushed which simplifies the From mappings. The PR is still a net addition but I think the simplification is significant.

Copy link
Contributor

@DanGould DanGould left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 request and 1 concern

  1. I think there's a more concise and semantically correct way to write process_get_res which might solve a mutant. See below.
  2. I think some of the From impls for DirectoryResponseError may be even more verbose than changes to make map_err work while expanding our public API and should be reconsidered

Fighting a head cold so warning these comments might be less sane than usual.

Comment on lines 66 to 71
let body = match response.status() {
http::StatusCode::OK => response.body().to_vec(),
http::StatusCode::ACCEPTED => return Ok(None),
_ => return Err(DirectoryResponseError::UnexpectedStatusCode(response.status())),
};
Ok(Some(body))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this was carried over, but I think it's more appropriately written as the following, which might address @benalleng's mutant concern as well

Suggested change
let body = match response.status() {
http::StatusCode::OK => response.body().to_vec(),
http::StatusCode::ACCEPTED => return Ok(None),
_ => return Err(DirectoryResponseError::UnexpectedStatusCode(response.status())),
};
Ok(Some(body))
match response.status() {
http::StatusCode::OK => Ok(Some(response.body().to_vec())),
http::StatusCode::ACCEPTED => Ok(None),
code => Err(DirectoryResponseError::UnexpectedStatusCode(code)),
}

this addresses 2 separate issues: 1. replying with Some(body) outside of the match and using the single response.status() call as the context for the UnexpectedStatusCode error.

Comment on lines 27 to 32
DirectoryResponseError::InvalidSize(e) =>
InternalSessionError::UnexpectedResponseSize(e),
DirectoryResponseError::OhttpDecapsulation(e) =>
InternalSessionError::OhttpEncapsulation(e),
DirectoryResponseError::UnexpectedStatusCode(e) =>
InternalSessionError::UnexpectedStatusCode(e),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should InternalSessionError not have a BadResponse variant that encapsulates DirectoryResponseError?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is addressed in the second commit.

Comment on lines 38 to 40
impl From<DirectoryResponseError> for Error {
fn from(value: DirectoryResponseError) -> Self { V2(value.into()) }
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't seem to me like this should necessarily be coerced into a V2 error. It could be a multiparty or later error, and so should be explicitly mapped at the call site.

Comment on lines 125 to 113

impl From<DirectoryResponseError> for EncapsulationError {
fn from(value: DirectoryResponseError) -> Self {
match value {
DirectoryResponseError::InvalidSize(e) => InternalEncapsulationError::InvalidSize(e),
DirectoryResponseError::OhttpDecapsulation(e) => InternalEncapsulationError::Ohttp(e),
DirectoryResponseError::UnexpectedStatusCode(e) =>
InternalEncapsulationError::UnexpectedStatusCode(e),
}
.into()
}
}

impl From<DirectoryResponseError> for ResponseError {
fn from(value: DirectoryResponseError) -> Self {
ResponseError::Validation(
super::InternalValidationError::V2Encapsulation(value.into()).into(),
)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, it seems like this conversion is only done once (which could be done with map_err or an Err(e) match arm) making the From unnecessarily verbose, and the EncapsulationError seems like it could just have a DirectoryResponseError unless these InvalidSize, OhttpDecapsulation, UnexpectedStatusCode variants crop up outside of the context of a directory response.

Comment on lines 44 to 51
impl From<DirectoryResponseError> for Error {
fn from(e: DirectoryResponseError) -> Self { InternalSessionError::DirectoryResponse(e).into() }
}

impl From<DirectoryResponseError> for SessionError {
fn from(e: DirectoryResponseError) -> Self { InternalSessionError::DirectoryResponse(e).into() }
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see this commit obviates my earlier comments. However, it still seems like it depends on context which one of these it gets converted to, which suggests to me you still want a map instead of the conversion (which happens on only few occasions)

@spacebear21 spacebear21 force-pushed the ohttp-reqs-refactor branch from daef0ac to 3b2dc34 Compare June 6, 2025 19:58
@spacebear21
Copy link
Collaborator Author

The latest push fixes process_get_res and replaces the From implementations with map_err.

Copy link
Contributor

@DanGould DanGould left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming checking if the get body is empty was a bug ACK 3b2dc34

The `process_res` methods across send and receive have a lot of shared
code that can be extracted into reusable functions. `process_get_res`
and `process_post_res` essentially do the same thing, and could
conceivably be combined into one function. They were kept separate
because "202 Accepted" is not a valid response for POST requests.
Instead of mapping DirectoryResponseError to the corresponding variants
on InternalSessionError and InternalCreateRequestError, nest those
variants by replacing them with DirectoryResponseError.
@spacebear21 spacebear21 force-pushed the ohttp-reqs-refactor branch from 3b2dc34 to ec4b67e Compare June 6, 2025 21:28
@spacebear21
Copy link
Collaborator Author

ec4b67e only applies your suggestions re: response.status().

@spacebear21 spacebear21 merged commit d8c37c0 into payjoin:master Jun 6, 2025
7 checks passed
benalleng added a commit to benalleng/rust-payjoin that referenced this pull request Jun 12, 2025
In payjoin#660 we added a process_get_res and process_post_res methods in
ohttps to pull away some of the logic from our send module but
multiparty remained the same.

This PR attempts pull sync the multiparty sender error handling with
this new approach. As well this change gets rid of the remaining mutant
on this status code match block.
benalleng added a commit to benalleng/rust-payjoin that referenced this pull request Jun 12, 2025
In payjoin#660 we added a process_get_res and process_post_res methods in
ohttps to pull away some of the logic from our send module but
multiparty remained the same.

This PR attempts pull sync the multiparty sender error handling with
this new approach. As well this change gets rid of the remaining mutant
on this status code match block.
benalleng added a commit to benalleng/rust-payjoin that referenced this pull request Jun 12, 2025
In payjoin#660 we added a process_get_res and process_post_res methods in
ohttps to pull away some of the logic from our send module but
multiparty remained the same.

This PR attempts pull sync the multiparty sender error handling with
this new approach. As well this change gets rid of the remaining mutant
on this status code match block.
benalleng added a commit to benalleng/rust-payjoin that referenced this pull request Jun 12, 2025
In payjoin#660 we added a process_get_res and process_post_res methods in
ohttps to pull away some of the logic from our send module but
multiparty remained the same.

This PR attempts pull sync the multiparty sender error handling with
this new approach. As well this change gets rid of the remaining mutant
on this status code match block.
benalleng added a commit to benalleng/rust-payjoin that referenced this pull request Jun 12, 2025
In payjoin#660 we added a process_get_res and process_post_res methods in
ohttps to pull away some of the logic from our send module but
multiparty remained the same.

This PR attempts pull sync the multiparty sender error handling with
this new approach. As well this change gets rid of the remaining mutant
on this status code match block.
shinghim pushed a commit to shinghim/rust-payjoin that referenced this pull request Jul 2, 2025
In payjoin#660 we added a process_get_res and process_post_res methods in
ohttps to pull away some of the logic from our send module but
multiparty remained the same.

This PR attempts pull sync the multiparty sender error handling with
this new approach. As well this change gets rid of the remaining mutant
on this status code match block.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants