Skip to content
This repository was archived by the owner on Jan 2, 2026. It is now read-only.

Commit 94f18da

Browse files
committed
fix: compilation error on example http_api
1 parent 172ebd5 commit 94f18da

File tree

1 file changed

+189
-169
lines changed

1 file changed

+189
-169
lines changed

examples/http_api.rs

Lines changed: 189 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -4,202 +4,222 @@
44

55
#![allow(clippy::unwrap_used, clippy::arithmetic_side_effects)]
66

7-
use std::str::FromStr;
8-
9-
use der::asn1::BitString;
10-
use ed25519_dalek::ed25519::signature::Signer;
11-
use ed25519_dalek::{Signature as Ed25519DalekSignature, SigningKey, VerifyingKey};
12-
use httptest::matchers::request;
13-
use httptest::responders::json_encoded;
14-
use httptest::{Expectation, Server};
15-
use polyproto::api::HttpClient;
16-
use polyproto::api::core::current_unix_time;
17-
use polyproto::certs::PublicKeyInfo;
18-
use polyproto::errors::CertificateConversionError;
19-
use polyproto::key::{PrivateKey, PublicKey};
20-
use polyproto::signature::Signature;
21-
use polyproto::types::routes::core::v1::GET_CHALLENGE_STRING;
22-
use serde_json::json;
23-
use spki::{AlgorithmIdentifierOwned, ObjectIdentifier, SignatureBitStringEncoding};
24-
use url::Url;
25-
26-
async fn setup_example() -> Server {
27-
let server = Server::run();
28-
server.expect(
29-
Expectation::matching(request::method_path(
30-
GET_CHALLENGE_STRING.method.as_str(),
31-
GET_CHALLENGE_STRING.path,
32-
))
33-
.respond_with(json_encoded(json!({
34-
"challenge": "abcd".repeat(8),
35-
"expires": current_unix_time() + 100
36-
}))),
37-
);
38-
server
39-
}
40-
41-
#[cfg(not(test))]
42-
#[tokio::main]
43-
async fn main() {
44-
let server = setup_example().await;
45-
let url = format!("http://{}", server.addr());
46-
47-
// The actual example starts here.
48-
// Create a new HTTP client
49-
let client = HttpClient::new().unwrap();
50-
// Create an authorized session, if you need it
51-
let _session: polyproto::api::Session<Ed25519Signature, Ed25519PrivateKey> =
52-
polyproto::api::Session::new(&client, "12345", Url::parse(&url).unwrap(), None);
53-
// You can now use the client and session to make requests to the polyproto home server!
54-
// The client is responsible for all unauthenticated requests, while sessions handle all
55-
// the routes needing authentication of some sort.
56-
// Routes are documented under <https://docs.polyphony.chat/APIs/core/>, and each route has a
57-
// corresponding method in the `HttpClient` struct. For example, if we wanted to get the certificate
58-
// of the home server, we'd call:
59-
let cert = client
60-
.get_server_id_cert(None, &Url::parse("https://example.com/").unwrap())
61-
.await
62-
.unwrap();
63-
dbg!(cert);
64-
}
65-
66-
#[cfg(test)]
67-
fn main() {
68-
main()
69-
}
7+
#[cfg(feature = "reqwest")]
8+
mod reqwest_example {
9+
use std::str::FromStr;
10+
11+
use der::asn1::BitString;
12+
use ed25519_dalek::ed25519::signature::Signer;
13+
use ed25519_dalek::{Signature as Ed25519DalekSignature, SigningKey, VerifyingKey};
14+
use httptest::matchers::request;
15+
use httptest::responders::json_encoded;
16+
use httptest::{Expectation, Server};
17+
use polyproto::api::HttpClient;
18+
use polyproto::api::core::current_unix_time;
19+
use polyproto::certs::PublicKeyInfo;
20+
use polyproto::errors::CertificateConversionError;
21+
use polyproto::key::{PrivateKey, PublicKey};
22+
use polyproto::signature::Signature;
23+
use polyproto::types::routes::core::v1::GET_CHALLENGE_STRING;
24+
use serde_json::json;
25+
use spki::{AlgorithmIdentifierOwned, ObjectIdentifier, SignatureBitStringEncoding};
26+
use url::Url;
27+
28+
pub async fn setup_example() -> Server {
29+
let server = Server::run();
30+
server.expect(
31+
Expectation::matching(request::method_path(
32+
GET_CHALLENGE_STRING.method.as_str(),
33+
GET_CHALLENGE_STRING.path,
34+
))
35+
.respond_with(json_encoded(json!({
36+
"challenge": "abcd".repeat(8),
37+
"expires": current_unix_time() + 100
38+
}))),
39+
);
40+
server
41+
}
7042

71-
#[derive(Debug, PartialEq, Eq, Clone)]
72-
pub(crate) struct Ed25519Signature {
73-
pub(crate) signature: Ed25519DalekSignature,
74-
pub(crate) algorithm: AlgorithmIdentifierOwned,
75-
}
43+
#[cfg(not(test))]
44+
pub async fn run_example() {
45+
let server = setup_example().await;
46+
let url = format!("http://{}", server.addr());
47+
48+
// The actual example starts here.
49+
// Create a new HTTP client
50+
let client = HttpClient::new().unwrap();
51+
// Create an authorized session, if you need it
52+
let _session: polyproto::api::Session<Ed25519Signature, Ed25519PrivateKey> =
53+
polyproto::api::Session::new(&client, "12345", Url::parse(&url).unwrap(), None);
54+
// You can now use the client and session to make requests to the polyproto home server!
55+
// The client is responsible for all unauthenticated requests, while sessions handle all
56+
// the routes needing authentication of some sort.
57+
// Routes are documented under <https://docs.polyphony.chat/APIs/core/>, and each route has a
58+
// corresponding method in the `HttpClient` struct. For example, if we wanted to get the certificate
59+
// of the home server, we'd call:
60+
let cert = client
61+
.get_server_id_cert(None, &Url::parse("https://example.com/").unwrap())
62+
.await
63+
.unwrap();
64+
dbg!(cert);
65+
}
7666

77-
impl std::fmt::Display for Ed25519Signature {
78-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79-
write!(f, "{:?}", self.signature)
67+
#[cfg(test)]
68+
pub fn test_main() {
69+
tokio::runtime::Runtime::new()
70+
.unwrap()
71+
.block_on(run_example())
8072
}
81-
}
8273

83-
// We implement the Signature trait for our signature type.
84-
impl Signature for Ed25519Signature {
85-
// We define the signature type from the ed25519-dalek crate as the associated type.
86-
type Signature = Ed25519DalekSignature;
74+
#[tokio::main]
75+
pub async fn main() {
76+
run_example().await
77+
}
8778

88-
// This is straightforward: we return a reference to the signature.
89-
fn as_signature(&self) -> &Self::Signature {
90-
&self.signature
79+
#[derive(Debug, PartialEq, Eq, Clone)]
80+
pub(crate) struct Ed25519Signature {
81+
pub(crate) signature: Ed25519DalekSignature,
82+
pub(crate) algorithm: AlgorithmIdentifierOwned,
9183
}
9284

93-
// The algorithm identifier for a given signature implementation is constant. We just need
94-
// to define it here.
95-
fn algorithm_identifier() -> AlgorithmIdentifierOwned {
96-
AlgorithmIdentifierOwned {
97-
// This is the OID for Ed25519. It is defined in the IANA registry.
98-
oid: ObjectIdentifier::from_str("1.3.101.112").unwrap(),
99-
// For this example, we don't need or want any parameters.
100-
parameters: None,
85+
impl std::fmt::Display for Ed25519Signature {
86+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
87+
write!(f, "{:?}", self.signature)
10188
}
10289
}
10390

104-
fn from_bytes(signature: &[u8]) -> Self {
105-
let mut signature_vec = signature.to_vec();
106-
signature_vec.resize(64, 0);
107-
let signature_array: [u8; 64] = {
108-
let mut array = [0; 64];
109-
array.copy_from_slice(&signature_vec[..]);
110-
array
111-
};
112-
Self {
113-
signature: Ed25519DalekSignature::from_bytes(&signature_array),
114-
algorithm: Self::algorithm_identifier(),
91+
// We implement the Signature trait for our signature type.
92+
impl Signature for Ed25519Signature {
93+
// We define the signature type from the ed25519-dalek crate as the associated type.
94+
type Signature = Ed25519DalekSignature;
95+
96+
// This is straightforward: we return a reference to the signature.
97+
fn as_signature(&self) -> &Self::Signature {
98+
&self.signature
99+
}
100+
101+
// The algorithm identifier for a given signature implementation is constant. We just need
102+
// to define it here.
103+
fn algorithm_identifier() -> AlgorithmIdentifierOwned {
104+
AlgorithmIdentifierOwned {
105+
// This is the OID for Ed25519. It is defined in the IANA registry.
106+
oid: ObjectIdentifier::from_str("1.3.101.112").unwrap(),
107+
// For this example, we don't need or want any parameters.
108+
parameters: None,
109+
}
110+
}
111+
112+
fn from_bytes(signature: &[u8]) -> Self {
113+
let mut signature_vec = signature.to_vec();
114+
signature_vec.resize(64, 0);
115+
let signature_array: [u8; 64] = {
116+
let mut array = [0; 64];
117+
array.copy_from_slice(&signature_vec[..]);
118+
array
119+
};
120+
Self {
121+
signature: Ed25519DalekSignature::from_bytes(&signature_array),
122+
algorithm: Self::algorithm_identifier(),
123+
}
124+
}
125+
126+
fn as_bytes(&self) -> Vec<u8> {
127+
self.as_signature().to_vec()
115128
}
116129
}
117130

118-
fn as_bytes(&self) -> Vec<u8> {
119-
self.as_signature().to_vec()
131+
// The `SignatureBitStringEncoding` trait is used to convert a signature to a bit string. We implement
132+
// it for our signature type.
133+
impl SignatureBitStringEncoding for Ed25519Signature {
134+
fn to_bitstring(&self) -> der::Result<der::asn1::BitString> {
135+
BitString::from_bytes(&self.as_signature().to_bytes())
136+
}
120137
}
121-
}
122138

123-
// The `SignatureBitStringEncoding` trait is used to convert a signature to a bit string. We implement
124-
// it for our signature type.
125-
impl SignatureBitStringEncoding for Ed25519Signature {
126-
fn to_bitstring(&self) -> der::Result<der::asn1::BitString> {
127-
BitString::from_bytes(&self.as_signature().to_bytes())
139+
// Next, we implement the key traits. We start by defining the private key type.
140+
#[derive(Debug, Clone, PartialEq, Eq)]
141+
pub(crate) struct Ed25519PrivateKey {
142+
// Defined below
143+
pub(crate) public_key: Ed25519PublicKey,
144+
// The private key from the ed25519-dalek crate
145+
pub(crate) key: SigningKey,
128146
}
129-
}
130147

131-
// Next, we implement the key traits. We start by defining the private key type.
132-
#[derive(Debug, Clone, PartialEq, Eq)]
133-
pub(crate) struct Ed25519PrivateKey {
134-
// Defined below
135-
pub(crate) public_key: Ed25519PublicKey,
136-
// The private key from the ed25519-dalek crate
137-
pub(crate) key: SigningKey,
138-
}
148+
impl PrivateKey<Ed25519Signature> for Ed25519PrivateKey {
149+
type PublicKey = Ed25519PublicKey;
139150

140-
impl PrivateKey<Ed25519Signature> for Ed25519PrivateKey {
141-
type PublicKey = Ed25519PublicKey;
151+
// Return a reference to the public key
152+
fn pubkey(&self) -> &Self::PublicKey {
153+
&self.public_key
154+
}
142155

143-
// Return a reference to the public key
144-
fn pubkey(&self) -> &Self::PublicKey {
145-
&self.public_key
156+
// Signs a message. The beauty of having to wrap the ed25519-dalek crate is that we can
157+
// harness all of its functionality, such as the `sign` method.
158+
fn sign(&self, data: &[u8]) -> Ed25519Signature {
159+
let signature = self.key.sign(data);
160+
Ed25519Signature {
161+
signature,
162+
algorithm: self.algorithm_identifier(),
163+
}
164+
}
146165
}
147166

148-
// Signs a message. The beauty of having to wrap the ed25519-dalek crate is that we can
149-
// harness all of its functionality, such as the `sign` method.
150-
fn sign(&self, data: &[u8]) -> Ed25519Signature {
151-
let signature = self.key.sign(data);
152-
Ed25519Signature {
153-
signature,
154-
algorithm: self.algorithm_identifier(),
155-
}
167+
// Same thing as above for the public key type.
168+
#[derive(Debug, Clone, PartialEq, Eq)]
169+
pub(crate) struct Ed25519PublicKey {
170+
// The public key type from the ed25519-dalek crate
171+
pub(crate) key: VerifyingKey,
156172
}
157-
}
158173

159-
// Same thing as above for the public key type.
160-
#[derive(Debug, Clone, PartialEq, Eq)]
161-
pub(crate) struct Ed25519PublicKey {
162-
// The public key type from the ed25519-dalek crate
163-
pub(crate) key: VerifyingKey,
164-
}
174+
impl PublicKey<Ed25519Signature> for Ed25519PublicKey {
175+
// Verifies a signature. We use the `verify_strict` method from the ed25519-dalek crate.
176+
// This method is used to mitigate weak key forgery.
177+
fn verify_signature(
178+
&self,
179+
signature: &Ed25519Signature,
180+
data: &[u8],
181+
) -> Result<(), polyproto::errors::composite::PublicKeyError> {
182+
match self.key.verify_strict(data, signature.as_signature()) {
183+
Ok(_) => Ok(()),
184+
Err(_) => Err(polyproto::errors::composite::PublicKeyError::BadSignature),
185+
}
186+
}
165187

166-
impl PublicKey<Ed25519Signature> for Ed25519PublicKey {
167-
// Verifies a signature. We use the `verify_strict` method from the ed25519-dalek crate.
168-
// This method is used to mitigate weak key forgery.
169-
fn verify_signature(
170-
&self,
171-
signature: &Ed25519Signature,
172-
data: &[u8],
173-
) -> Result<(), polyproto::errors::composite::PublicKeyError> {
174-
match self.key.verify_strict(data, signature.as_signature()) {
175-
Ok(_) => Ok(()),
176-
Err(_) => Err(polyproto::errors::composite::PublicKeyError::BadSignature),
188+
// Returns the public key info. Public key info is used to encode the public key in a
189+
// certificate or a CSR. It is named after the `SubjectPublicKeyInfo` type from the X.509
190+
// standard, and thus includes the information needed to encode the public key in a certificate
191+
// or a CSR.
192+
fn public_key_info(&self) -> PublicKeyInfo {
193+
PublicKeyInfo {
194+
algorithm: Ed25519Signature::algorithm_identifier(),
195+
public_key_bitstring: BitString::from_bytes(&self.key.to_bytes()).unwrap(),
196+
}
177197
}
178-
}
179198

180-
// Returns the public key info. Public key info is used to encode the public key in a
181-
// certificate or a CSR. It is named after the `SubjectPublicKeyInfo` type from the X.509
182-
// standard, and thus includes the information needed to encode the public key in a certificate
183-
// or a CSR.
184-
fn public_key_info(&self) -> PublicKeyInfo {
185-
PublicKeyInfo {
186-
algorithm: Ed25519Signature::algorithm_identifier(),
187-
public_key_bitstring: BitString::from_bytes(&self.key.to_bytes()).unwrap(),
199+
fn try_from_public_key_info(
200+
public_key_info: PublicKeyInfo,
201+
) -> Result<Self, CertificateConversionError> {
202+
let mut key_vec = public_key_info.public_key_bitstring.raw_bytes().to_vec();
203+
key_vec.resize(32, 0);
204+
let signature_array: [u8; 32] = {
205+
let mut array = [0; 32];
206+
array.copy_from_slice(&key_vec[..]);
207+
array
208+
};
209+
Ok(Self {
210+
key: VerifyingKey::from_bytes(&signature_array).unwrap(),
211+
})
188212
}
189213
}
214+
}
190215

191-
fn try_from_public_key_info(
192-
public_key_info: PublicKeyInfo,
193-
) -> Result<Self, CertificateConversionError> {
194-
let mut key_vec = public_key_info.public_key_bitstring.raw_bytes().to_vec();
195-
key_vec.resize(32, 0);
196-
let signature_array: [u8; 32] = {
197-
let mut array = [0; 32];
198-
array.copy_from_slice(&key_vec[..]);
199-
array
200-
};
201-
Ok(Self {
202-
key: VerifyingKey::from_bytes(&signature_array).unwrap(),
203-
})
204-
}
216+
#[cfg(feature = "reqwest")]
217+
#[tokio::main]
218+
async fn main() {
219+
reqwest_example::run_example().await
220+
}
221+
222+
#[cfg(not(feature = "reqwest"))]
223+
fn main() {
224+
eprintln!("This example requires you to compile with the 'reqwest' feature enabled.")
205225
}

0 commit comments

Comments
 (0)