Skip to content

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
Contributor

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
Contributor

@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
Contributor

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
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
Contributor

@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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reverted back to the original UniFFI compatible error type previous to #26 (comment).

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
Contributor

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 wvanlint requested review from G8XSU and tnull May 22, 2024 23:06
@wvanlint
Copy link
Contributor Author

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

@wvanlint wvanlint requested a review from G8XSU May 23, 2024 22:23
src/client.rs Outdated
.get_headers(&request_body)
.await
.and_then(get_headermap)
.map_err(|e| match e {
Copy link
Contributor

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 ?

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.

src/client.rs Outdated
}

/// 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.

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
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.

@wvanlint wvanlint requested review from G8XSU and tnull July 9, 2024 22:47
Copy link
Contributor

@tnull tnull left a comment

Choose a reason for hiding this comment

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

LGTM

Just two tiny nits, but happy to have this land as is.

src/client.rs Outdated
use std::sync::Arc;

use crate::error::VssError;
use crate::headers::get_headermap;
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Could group these imports.

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.

}

/// Constructs a [`VssClient`] using `base_url` as the VSS server endpoint.
/// HTTP headers will be provided by the given `header_provider`.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Add newline after initial paragraph to improve doc rendering.

Suggested change
/// HTTP headers will be provided by the given `header_provider`.
///
/// HTTP headers will be provided by the given `header_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.

Done.

Copy link
Contributor

@G8XSU G8XSU left a comment

Choose a reason for hiding this comment

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

Lgtm! Feel free to squash.

@wvanlint
Copy link
Contributor Author

Thanks! Squashed.

@G8XSU G8XSU merged commit 59769c9 into lightningdevkit:main Jul 17, 2024
@wvanlint wvanlint deleted the header_provider branch July 17, 2024 21:45
@G8XSU G8XSU mentioned this pull request Aug 23, 2024
G8XSU added a commit to G8XSU/vss-rust-client that referenced this pull request Aug 23, 2024
Major Changes include:
* Signature change in vss-client constructor. (in lightningdevkit#31 )
* Vss-client can now also return AuthError if AuthException is returned from server. (lightningdevkit#30)
* Adds VssHeaderProvider, can be used for auth and request signing.(lightningdevkit#31)
* Adds LnurlAuthToJwtProvider, provides LnUrl based JWT auth. (lightningdevkit#26)
* Adds KeyObfuscator, to provide client-side key obfuscation. (lightningdevkit#32)
* Package now has enforced MSRV of 1.63.0. (lightningdevkit#19)

This is a minor version bump because there are non-backward compatible changes in vss-client usage.
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