Skip to content

Commit

Permalink
Revert Revert Remove reqwest dependency (#366)
Browse files Browse the repository at this point in the history
  • Loading branch information
Diane Huxley authored Sep 23, 2024
1 parent 83f2954 commit bf0209b
Show file tree
Hide file tree
Showing 15 changed files with 280 additions and 128 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ FROM --platform=linux/amd64 alpine:latest
RUN apk add --no-cache \
build-base \
musl-dev \
openssl-dev \
linux-headers \
rustup \
libgcc \
Expand All @@ -13,21 +12,12 @@ RUN apk add --no-cache \
git \
perl \
make \
bash \
openssl-libs-static
bash

# Install rust
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | bash -s -- -y --no-modify-path --default-toolchain 1.74.0
ENV PATH="/root/.cargo/bin:${PATH}"

# Set environment variables to ensure vendored OpenSSL is used
ENV OPENSSL_STATIC=1
ENV OPENSSL_LIB_DIR=/usr/lib
ENV OPENSSL_INCLUDE_DIR=/usr/include
ENV PKG_CONFIG_ALLOW_CROSS=1
ENV PKG_CONFIG_PATH=/usr/lib/pkgconfig
ENV LIBRARY_PATH="/usr/lib:/usr/local/lib"

# Copy the source code to the container
WORKDIR /usr/src/myapp
COPY Cargo.toml ./
Expand All @@ -44,7 +34,7 @@ RUN cargo build --release --package web5_uniffi
# Compile as a dynamic lib (.so) from our static lib (.a) while keeping dependencies self-contained
RUN gcc -shared -o target/release/libweb5_uniffi.so -Wl,--whole-archive \
target/release/libweb5_uniffi.a -Wl,--no-whole-archive -static-libgcc \
-L/usr/lib -lssl -lcrypto -Wl,-Bdynamic -fPIC
-Wl,-Bdynamic -fPIC

# Set the entrypoint, so that we can `docker cp` the build output
CMD tail -f /dev/null
3 changes: 2 additions & 1 deletion crates/web5/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ k256 = { version = "0.13.3", features = ["ecdsa", "jwk"] }
tokio = "1.38.0"
rand = { workspace = true }
regex = "1.10.4"
reqwest = { version = "0.12.4", features = ["json", "blocking"] }
serde = { workspace = true }
serde_json = { workspace = true }
sha2 = "0.10.8"
Expand All @@ -30,6 +29,8 @@ x25519-dalek = { version = "2.0.1", features = ["getrandom", "static_secrets"] }
zbase32 = "0.1.2"
lazy_static = "1.5.0"
flate2 = "1.0.33"
rustls = { version = "0.23.13", default-features = false, features = ["std", "tls12"] }
rustls-native-certs = "0.8.0"

[dev-dependencies]
mockito = "1.5.0"
Expand Down
16 changes: 10 additions & 6 deletions crates/web5/src/credentials/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ mod tests {

#[test]
fn test_schema_resolve_network_issue() {
let url = "invalid url".to_string(); // here
let url = "http://local".to_string(); // here

let result = create_vc(
issuer(),
Expand All @@ -571,7 +571,11 @@ mod tests {

match result {
Err(Web5Error::Network(err_msg)) => {
assert!(err_msg.contains("unable to resolve json schema"))
assert!(
err_msg.contains("failed to connect to host"),
"Error message is: {}",
err_msg
)
}
_ => panic!(
"expected Web5Error::Network with specific message but got {:?}",
Expand Down Expand Up @@ -600,8 +604,8 @@ mod tests {
);

match result {
Err(Web5Error::JsonSchema(err_msg)) => {
assert!(err_msg.contains("non-200 response when resolving json schema"))
Err(Web5Error::Http(err_msg)) => {
assert_eq!("non-successful response code 500", err_msg)
}
_ => panic!(
"expected Web5Error::JsonSchema with specific message but got {:?}",
Expand Down Expand Up @@ -632,8 +636,8 @@ mod tests {
);

match result {
Err(Web5Error::JsonSchema(err_msg)) => {
assert!(err_msg.contains("unable to parse json schema from response body"))
Err(Web5Error::Http(err_msg)) => {
assert!(err_msg.contains("unable to parse json response body"))
}
_ => panic!(
"expected Web5Error::JsonSchema with specific message but got {:?}",
Expand Down
25 changes: 6 additions & 19 deletions crates/web5/src/credentials/credential_schema.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use super::verifiable_credential_1_1::VerifiableCredential;
use crate::errors::{Result, Web5Error};
use crate::{
errors::{Result, Web5Error},
http::get_json,
};
use jsonschema::{Draft, JSONSchema};
use reqwest::blocking::get;
use serde::{Deserialize, Serialize};

pub const CREDENTIAL_SCHEMA_TYPE: &str = "JsonSchema";
Expand All @@ -28,23 +30,8 @@ pub(crate) fn validate_credential_schema(
}

let url = &credential_schema.id;
let response = get(url).map_err(|err| {
Web5Error::Network(format!("unable to resolve json schema {} {}", url, err))
})?;
if !response.status().is_success() {
return Err(Web5Error::JsonSchema(format!(
"non-200 response when resolving json schema {} {}",
url,
response.status()
)));
}
let schema_json = response.json::<serde_json::Value>().map_err(|err| {
Web5Error::JsonSchema(format!(
"unable to parse json schema from response body {} {}",
url, err
))
})?;
let compiled_schema = JSONSchema::options().compile(&schema_json).map_err(|err| {
let json_schema = get_json::<serde_json::Value>(url)?;
let compiled_schema = JSONSchema::options().compile(&json_schema).map_err(|err| {
Web5Error::JsonSchema(format!("unable to compile json schema {} {}", url, err))
})?;

Expand Down
16 changes: 10 additions & 6 deletions crates/web5/src/credentials/verifiable_credential_1_1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -791,13 +791,17 @@ mod tests {

#[test]
fn test_schema_resolve_network_issue() {
let vc_jwt_with_invalid_url = r#"eyJ0eXAiOiJKV1QiLCJhbGciOiJFZERTQSIsImtpZCI6ImRpZDpqd2s6ZXlKaGJHY2lPaUpGWkRJMU5URTVJaXdpYTNSNUlqb2lUMHRRSWl3aVkzSjJJam9pUldReU5UVXhPU0lzSW5naU9pSmZYelYxVEU1bWNVWTRRbTB6ZVhnMmJVRndMVlJJV25sSk5WcDJWQzFmYVVKbExWZDJiMHRuTTFwakluMCMwIn0.eyJ2YyI6eyJAY29udGV4dCI6WyJodHRwczovL3d3dy53My5vcmcvMjAxOC9jcmVkZW50aWFscy92MSJdLCJpZCI6InVybjp1dWlkOmRlNDY2N2YxLTMzM2ItNDg4OC1hMDc5LTdkMGU1N2JiZmFlZiIsInR5cGUiOlsiVmVyaWZpYWJsZUNyZWRlbnRpYWwiXSwiaXNzdWVyIjoiZGlkOmp3azpleUpoYkdjaU9pSkZaREkxTlRFNUlpd2lhM1I1SWpvaVQwdFFJaXdpWTNKMklqb2lSV1F5TlRVeE9TSXNJbmdpT2lKZlh6VjFURTVtY1VZNFFtMHplWGcyYlVGd0xWUklXbmxKTlZwMlZDMWZhVUpsTFZkMmIwdG5NMXBqSW4wIiwiaXNzdWFuY2VEYXRlIjoiMjAyNC0wOC0zMFQxNTowNToyMC43NjQ0MDgrMDA6MDAiLCJleHBpcmF0aW9uRGF0ZSI6bnVsbCwiY3JlZGVudGlhbFN1YmplY3QiOnsiaWQiOiJkaWQ6ZGh0OnFnbW1weWp3NWh3bnFmZ3puN3dtcm0zM2FkeThnYjh6OWlkZWliNm05Z2o0eXM2d255OHkifSwiY3JlZGVudGlhbFNjaGVtYSI6eyJpZCI6ImludmFsaWQgdXJsIiwidHlwZSI6Ikpzb25TY2hlbWEifX0sImlzcyI6ImRpZDpqd2s6ZXlKaGJHY2lPaUpGWkRJMU5URTVJaXdpYTNSNUlqb2lUMHRRSWl3aVkzSjJJam9pUldReU5UVXhPU0lzSW5naU9pSmZYelYxVEU1bWNVWTRRbTB6ZVhnMmJVRndMVlJJV25sSk5WcDJWQzFmYVVKbExWZDJiMHRuTTFwakluMCIsImp0aSI6InVybjp1dWlkOmRlNDY2N2YxLTMzM2ItNDg4OC1hMDc5LTdkMGU1N2JiZmFlZiIsInN1YiI6ImRpZDpkaHQ6cWdtbXB5anc1aHducWZnem43d21ybTMzYWR5OGdiOHo5aWRlaWI2bTlnajR5czZ3bnk4eSIsIm5iZiI6MTcyNTAzMDMyMCwiaWF0IjoxNzI1MDMwMzIwfQ.3sH7qzI7QrQMdkWIvqf7k8Mr2dMGjWBLrv4QB8gEz0t83RSFMtG-fWT-YVkUlo1qMvC4gNjT2Jc0eObCAA7VDQ"#;
let vc_jwt_with_invalid_url = r#"eyJ0eXAiOiJKV1QiLCJhbGciOiJFZDI1NTE5Iiwia2lkIjoiZGlkOmp3azpleUpoYkdjaU9pSkZaREkxTlRFNUlpd2lhM1I1SWpvaVQwdFFJaXdpWTNKMklqb2lSV1F5TlRVeE9TSXNJbmdpT2lKTmEycDVaRlo1ZFhaU1psaExRMDVWYm0wNVVWRnJVbkUwY0doWVdYRTBObUpFVjJGemFHOW5kbXhWSW4wIzAifQ.eyJpc3MiOiJkaWQ6andrOmV5SmhiR2NpT2lKRlpESTFOVEU1SWl3aWEzUjVJam9pVDB0UUlpd2lZM0oySWpvaVJXUXlOVFV4T1NJc0luZ2lPaUpOYTJwNVpGWjVkWFpTWmxoTFEwNVZibTA1VVZGclVuRTBjR2hZV1hFME5tSkVWMkZ6YUc5bmRteFZJbjAiLCJqdGkiOiJ1cm46dXVpZDo2YzM2YzU0Zi02M2VhLTRiY2MtOTgxOS0zYmNmMGIyYmUxMDgiLCJzdWIiOiJkaWQ6ZGh0OnFnbW1weWp3NWh3bnFmZ3puN3dtcm0zM2FkeThnYjh6OWlkZWliNm05Z2o0eXM2d255OHkiLCJuYmYiOjE3MjYwODk0NDIsImlhdCI6MTcyNjA4OTQ0MiwidmMiOnsiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiXSwiY3JlZGVudGlhbFNjaGVtYSI6eyJpZCI6Imh0dHA6Ly9sb2NhbC9zY2hlbWFzL2VtYWlsLmpzb24iLCJ0eXBlIjoiSnNvblNjaGVtYSJ9LCJpZCI6InVybjp1dWlkOjZjMzZjNTRmLTYzZWEtNGJjYy05ODE5LTNiY2YwYjJiZTEwOCIsImlzc3VlciI6ImRpZDpqd2s6ZXlKaGJHY2lPaUpGWkRJMU5URTVJaXdpYTNSNUlqb2lUMHRRSWl3aVkzSjJJam9pUldReU5UVXhPU0lzSW5naU9pSk5hMnA1WkZaNWRYWlNabGhMUTA1VmJtMDVVVkZyVW5FMGNHaFlXWEUwTm1KRVYyRnphRzluZG14VkluMCIsImlzc3VhbmNlRGF0ZSI6IjIwMjQtMDktMTFUMjE6MTc6MjJaIiwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJpZCI6ImRpZDpkaHQ6cWdtbXB5anc1aHducWZnem43d21ybTMzYWR5OGdiOHo5aWRlaWI2bTlnajR5czZ3bnk4eSJ9fX0.eZfQZdkDB2D2QMs6BPaxjU-FCJLIGMlCz0sF5FjhHkaizItfv3zGXqWVEjc8f-SRiLSmujlEKgwfw22cCvnDAQ"#;

let result = VerifiableCredential::from_vc_jwt(vc_jwt_with_invalid_url, true);

match result {
Err(Web5Error::Network(err_msg)) => {
assert!(err_msg.contains("unable to resolve json schema"))
assert!(
err_msg.contains("failed to connect to host"),
"Error message is: {}",
err_msg
)
}
_ => panic!(
"expected Web5Error::Network with specific message but got {:?}",
Expand All @@ -822,8 +826,8 @@ mod tests {

let result = VerifiableCredential::from_vc_jwt(vc_jwt_at_port, true);
match result {
Err(Web5Error::JsonSchema(err_msg)) => {
assert!(err_msg.contains("non-200 response when resolving json schema"))
Err(Web5Error::Http(err_msg)) => {
assert_eq!("non-successful response code 500", err_msg)
}
_ => panic!(
"expected Web5Error::JsonSchema with specific message but got {:?}",
Expand All @@ -850,8 +854,8 @@ mod tests {

let result = VerifiableCredential::from_vc_jwt(vc_jwt_at_port, true);
match result {
Err(Web5Error::JsonSchema(err_msg)) => {
assert!(err_msg.contains("unable to parse json schema from response body"))
Err(Web5Error::Http(err_msg)) => {
assert!(err_msg.contains("unable to parse json response body"))
}
_ => panic!(
"expected Web5Error::JsonSchema with specific message but got {:?}",
Expand Down
6 changes: 3 additions & 3 deletions crates/web5/src/dids/bearer_did.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ mod tests {
key_manager: Some(key_manager.clone()),
..Default::default()
}))
.unwrap();
.unwrap();

let portable_did = PortableDid {
did_uri: did_jwk_bearer_did.did.uri,
Expand Down Expand Up @@ -208,12 +208,12 @@ mod tests {
key_manager: Some(key_manager.clone()),
..Default::default()
}))
.unwrap();
.unwrap();

let result = bearer_did.to_portable_did(key_manager);
assert!(result.is_ok());
let portable_did = result.unwrap();
assert_eq!(bearer_did.did.uri, portable_did.did_uri);
}
}
}
}
1 change: 0 additions & 1 deletion crates/web5/src/dids/did.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ lazy_static! {
}

impl Did {

/// Parses a given DID URI into a `Did` struct.
///
/// This function extracts and parses components from a DID URI, including the method,
Expand Down
44 changes: 9 additions & 35 deletions crates/web5/src/dids/methods/did_dht/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use bep44::Bep44Message;
use reqwest::blocking::Client;
use simple_dns::Packet;

use crate::{
Expand All @@ -19,6 +18,7 @@ use crate::{
},
},
errors::{Result, Web5Error},
http::{get, put},
};
use std::sync::Arc;

Expand Down Expand Up @@ -191,15 +191,8 @@ impl DidDht {
bearer_did.did.id.trim_start_matches('/')
);

let client = Client::new();
let response = client
.put(url)
.header("Content-Type", "application/octet-stream")
.body(body)
.send()
.map_err(|_| Web5Error::Network("failed to publish DID to mainline".to_string()))?;

if response.status() != 200 {
let response = put(&url, &body)?;
if response.status_code != 200 {
return Err(Web5Error::Network(
"failed to PUT DID to mainline".to_string(),
));
Expand Down Expand Up @@ -255,35 +248,16 @@ impl DidDht {
did.id.trim_start_matches('/')
);

let client = Client::new();

// Make the GET request
let response = client
.get(url)
.send()
.map_err(|_| ResolutionMetadataError::InternalError)?;

// Check if the status is not 200
let status = response.status();
if status == 404 {
return Err(ResolutionMetadataError::NotFound)?;
} else if status != 200 {
return Err(ResolutionMetadataError::InternalError)?;
}

// check http response status is 200 and body is nonempty
let body = response
.bytes()
.map_err(|_| ResolutionMetadataError::NotFound)?;
let response = get(&url).map_err(|_| ResolutionMetadataError::InternalError)?;

// Check if the body is empty
if body.is_empty() {
return Err(ResolutionMetadataError::NotFound)?;
if response.status_code == 404 {
return Err(ResolutionMetadataError::NotFound);
} else if response.status_code != 200 {
return Err(ResolutionMetadataError::InternalError);
}

// bep44 decode and verify response body bytes
let body: Vec<u8> = body.into();
let bep44_message = Bep44Message::decode(&body)
let bep44_message = Bep44Message::decode(&response.body)
.map_err(|_| ResolutionMetadataError::InvalidDidDocument)?;
bep44_message
.verify(&Ed25519Verifier::new(identity_key))
Expand Down
1 change: 0 additions & 1 deletion crates/web5/src/dids/methods/did_jwk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ pub struct DidJwk;
/// by third parties without relying on a separate blockchain or ledger. This is particularly useful for scenarios
/// involving verifiable credentials or capabilities.
impl DidJwk {

/// Creates a new "did:jwk" DID, derived from a public key.
///
/// This method generates a "did:jwk" DID by creating a key pair, using the provided key manager, and
Expand Down
46 changes: 14 additions & 32 deletions crates/web5/src/dids/methods/did_web/resolver.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use crate::dids::{
data_model::document::Document,
did::Did,
resolution::{
resolution_metadata::ResolutionMetadataError, resolution_result::ResolutionResult,
use crate::{
dids::{
data_model::document::Document,
did::Did,
resolution::{
resolution_metadata::ResolutionMetadataError, resolution_result::ResolutionResult,
},
},
http::get_json,
};
use reqwest::header::HeaderMap;
use std::{
future::{Future, IntoFuture},
pin::Pin,
Expand Down Expand Up @@ -48,32 +50,12 @@ impl Resolver {
}

async fn resolve(url: String) -> Result<ResolutionResult, ResolutionMetadataError> {
let headers = HeaderMap::new();

let client = reqwest::Client::builder()
.default_headers(headers)
.build()
.map_err(|_| ResolutionMetadataError::InternalError)?;

let response = client
.get(&url)
.send()
.await
.map_err(|_| ResolutionMetadataError::InternalError)?;

if response.status().is_success() {
let did_document = response
.json::<Document>()
.await
.map_err(|_| ResolutionMetadataError::RepresentationNotSupported)?;

Ok(ResolutionResult {
document: Some(did_document),
..Default::default()
})
} else {
Err(ResolutionMetadataError::NotFound)
}
let document =
get_json::<Document>(&url).map_err(|_| ResolutionMetadataError::InternalError)?;
Ok(ResolutionResult {
document: Some(document),
..Default::default()
})
}
}

Expand Down
1 change: 0 additions & 1 deletion crates/web5/src/dids/portable_did.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use crate::{
};
use serde::{Deserialize, Serialize};


/// Represents a Portable DID (Decentralized Identifier) that includes the DID Document and
/// its associated private keys. This structure is useful for exporting/importing DIDs
/// across different contexts or process boundaries.
Expand Down
2 changes: 2 additions & 0 deletions crates/web5/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ pub enum Web5Error {
Network(String),
#[error("datetime error {0}")]
DateTime(String),
#[error("http error {0}")]
Http(String),

#[error(transparent)]
Resolution(#[from] ResolutionMetadataError),
Expand Down
Loading

0 comments on commit bf0209b

Please sign in to comment.