Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce header provider trait #31

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

wvanlint
Copy link
Contributor

Introduces a HeaderProvider trait that will provide headers for each VSS call.

This change is split off from #26, which will introduce a JWT header provider based on LNURL Auth.

pub trait VssHeaderProvider {
/// Returns the HTTP headers to be used for a VSS request.
/// This method is called on each request, and should likely perform some form of caching.
async fn get_headers(&self, request: &[u8]) -> Result<HashMap<String, String>, VssError>;
Copy link
Collaborator

Choose a reason for hiding this comment

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

++
request: A reference to serialized request body. It can be used to perform operations such as request signing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.


#[async_trait]
impl VssHeaderProvider for FixedHeaders {
async fn get_headers(&self, _request: &[u8]) -> Result<HashMap<String, String>, VssError> {
Copy link
Collaborator

@G8XSU G8XSU May 15, 2024

Choose a reason for hiding this comment

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

returning some of the errors in VssError can have unintended consequences such as NoSuchKey/Conflict, or in some cases misleading.

the alternative is, we use io::Result<HashMap<String,String>> here and blanket convert all errors to VssError::AuthError in VssClient. (i think this would be much easier to debug and easy to understand from api perspective)

or we could document that only

InvalidRequestError,  (invalid request by user or invalid input)
AuthError,  (in case of auth failure) (or blanket convert all errors to authError)
InternalServerError, (auth server unavailable)
InternalError (unexpected code failure) (if the failure could be because of user provided input, it should still be invalid request, for example an error due to user provided headers or seed)

should be used here and explain how they will be used for auth_provider.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah I agree, this was the main reason I initially created a separate error type. Moved to io::Result which will be embedded in VssError::AuthError.

Copy link
Collaborator

Choose a reason for hiding this comment

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

sounds good,
I was also good with the way we have done error handling in lnurlauthprovider, it would just need some explaining in trait docs.

Copy link
Contributor

@tnull tnull May 22, 2024

Choose a reason for hiding this comment

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

I'm afraid if we want to expose/use this interface in LDK Node bindings, we need to revert the recent changes as discussed in #26. We need to keep the simpler error types as io::Error is probably not feasible to expose in bindings.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah right, I forgot whether this will turn out internal in ldk-node or exposed as bindings. We did discuss the option of having this exposed as bindings, so I changed this into Result<_, String> to not have different semantics around VssError for different cases.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Sounds good to me !
As we don't have any way of handling more granular error types.

Copy link
Contributor

@tnull tnull May 23, 2024

Choose a reason for hiding this comment

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

Ah right, I forgot whether this will turn out internal in ldk-node or exposed as bindings. We did discuss the option of having this exposed as bindings, so I changed this into Result<_, String> to not have different semantics around VssError for different cases.

Unfortunately the error type must be an enum and implement std::error::Error (see https://mozilla.github.io/uniffi-rs/udl/errors.html), so I think we really have to revert to what we had discussed before.

Copy link
Collaborator

@G8XSU G8XSU May 23, 2024

Choose a reason for hiding this comment

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

ok, in that case lets just revert to using VssError, we are using it correctly in lnurl PR.
and have some docs in this trait as discussed in first comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, thanks for mentioning that! I should have double-checked UniFFI. Reverted back to VssError and added documentation in the trait. Enforced all VssHeaderProvider errors to be a single variant i.e. VssError::AuthError to not conflate semantics.

Copy link
Contributor

Choose a reason for hiding this comment

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

ok, in that case lets just revert to using VssError, we are using it correctly in lnurl PR. and have some docs in this trait as discussed in first comment.

No, I really meant it, we should revert to the simple error type: UniFFI doesn't support tuple structs/enums. If we want to use VssError, it can't have any such variants, i.e., VssError::AuthError(String) would need to become AuthError(error: String) etc. It also shouldn't rely on any constructors/methods, as otherwise needs to be exposed differently.

Reverting back to what we previously discussed seems much simpler.

Cargo.lock Outdated Show resolved Hide resolved
src/client.rs Outdated
.get_headers(&request_body)
.await
.map_err(|e| VssError::InternalError(e.to_string()))?;
let headermap = get_headermap(&headers).map_err(VssError::InternalError)?;
Copy link
Collaborator

Choose a reason for hiding this comment

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

if we can't get string value header map from headers, then there is probably some user provided invalid input.
i think this can be InvalidRequestError.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Similar to the discussion above, using io::Error that will be embedded in VssError::AuthError. These might also be invalid headers by the provider.

@wvanlint wvanlint force-pushed the header_provider branch 2 times, most recently from c2d1d00 to 9e151a4 Compare May 16, 2024 23:13
@wvanlint wvanlint requested a review from G8XSU May 16, 2024 23:17
@wvanlint
Copy link
Contributor Author

FYI I am aiming to get this merged first before rebasing #26 if that sounds good.

Comment on lines +16 to +17
/// Any returned errors should be of the `VssError::AuthError` variant,
/// or will be mapped to it.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
/// Any returned errors should be of the `VssError::AuthError` variant,
/// or will be mapped to it.
/// Any returned errors must be of the `VssError::AuthError` variant.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, lets link to it, i.e.

Suggested change
/// Any returned errors should be of the `VssError::AuthError` variant,
/// or will be mapped to it.
/// Any returned errors should be of the [`VssError::AuthError`] variant,
/// or will be mapped to it.

Comment on lines +136 to +139
.map_err(|e| match e {
e @ VssError::AuthError(_) => e,
e => VssError::AuthError(e.to_string()),
})?;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
.map_err(|e| match e {
e @ VssError::AuthError(_) => e,
e => VssError::AuthError(e.to_string()),
})?;
.map_err(|e| match e {
VssError::AuthError(_) => e,
_ => VssError::AuthError(e.to_string()),
})?;

nit: @ Binding seems unnecessary here.

.get_headers(&request_body)
.await
.and_then(get_headermap)
.map_err(|e| match e {
Copy link
Collaborator

Choose a reason for hiding this comment

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

should we add a simple testcase for this ?

@@ -34,7 +39,19 @@ impl<R: RetryPolicy<E = VssError>> VssClient<R> {

/// Constructs a [`VssClient`] from a given [`reqwest::Client`], using `base_url` as the VSS server endpoint.
pub fn from_client(base_url: &str, client: Client, retry_policy: R) -> Self {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: If we end up owning the value anyways, we could consider just taking a String here and below.

Comment on lines +16 to +17
/// Any returned errors should be of the `VssError::AuthError` variant,
/// or will be mapped to it.
Copy link
Contributor

Choose a reason for hiding this comment

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

Also, lets link to it, i.e.

Suggested change
/// Any returned errors should be of the `VssError::AuthError` variant,
/// or will be mapped to it.
/// Any returned errors should be of the [`VssError::AuthError`] variant,
/// or will be mapped to it.


#[async_trait]
impl VssHeaderProvider for FixedHeaders {
async fn get_headers(&self, _request: &[u8]) -> Result<HashMap<String, String>, VssError> {
Copy link
Contributor

Choose a reason for hiding this comment

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

ok, in that case lets just revert to using VssError, we are using it correctly in lnurl PR. and have some docs in this trait as discussed in first comment.

No, I really meant it, we should revert to the simple error type: UniFFI doesn't support tuple structs/enums. If we want to use VssError, it can't have any such variants, i.e., VssError::AuthError(String) would need to become AuthError(error: String) etc. It also shouldn't rely on any constructors/methods, as otherwise needs to be exposed differently.

Reverting back to what we previously discussed seems much simpler.

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.

None yet

3 participants