diff --git a/crates/client/Cargo.toml b/crates/client/Cargo.toml index f6d97ebec..50920feb1 100644 --- a/crates/client/Cargo.toml +++ b/crates/client/Cargo.toml @@ -16,7 +16,7 @@ eventsource-stream = { version = "0.2.3", features = [] } futures-lite = "2.6.1" jsonwebtoken = { version = "10.2.0", default-features = false, features = ["rust_crypto"] } parking_lot = { workspace = true } -reqwest = { version = "0.12.8", features = ["stream"] } +reqwest = { version = "0.12.8", default-features = false, features = ["stream", "rustls-tls"] } serde = { workspace = true } serde_json = { workspace = true } thiserror = "2.0.12" @@ -26,6 +26,6 @@ url = "2.5.4" [dev-dependencies] base64 = { version = "0.22.1", default-features = false, features = ["alloc"] } lazy_static = "1.4.0" -reqwest = { version = "0.12.8", features = ["stream", "multipart", "json"] } +reqwest = { version = "0.12.8", features = ["stream", "multipart", "json", "rustls-tls"] } temp-dir = "0.1.13" tokio = { version = "1.43.0", features = ["macros", "rt-multi-thread"] } diff --git a/crates/client/src/lib.rs b/crates/client/src/lib.rs index cb713fefe..52c7bf82c 100644 --- a/crates/client/src/lib.rs +++ b/crates/client/src/lib.rs @@ -10,11 +10,12 @@ use eventsource_stream::Eventsource; use futures_lite::StreamExt; use parking_lot::RwLock; -use reqwest::header::{self, HeaderMap, HeaderValue}; +use reqwest::header::{self, CONTENT_TYPE, HeaderMap, HeaderValue}; use reqwest::{Method, StatusCode}; use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use std::borrow::Cow; +use std::collections::HashMap; use std::sync::Arc; use thiserror::Error; use tracing::*; @@ -763,6 +764,50 @@ impl Client { return Ok(tokens); } + + pub async fn register(&self, email: &str, password: &str, password_repeat: &str) -> Result { + #[derive(Serialize)] + struct Credentials<'a> { + email: &'a str, + password: &'a str, + password_repeat: &'a str, + } + + let client = reqwest::Client::new(); + + // Only include headers you actually need (like Auth or User-Agent). + // Do NOT manually set Content-Type or Content-Encoding for forms. + let mut headers = build_headers(None); + headers.remove(CONTENT_TYPE); + headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/x-www-form-urlencoded")); + + let mut params = HashMap::new(); + params.insert("email", email); + params.insert("password", password); + params.insert("password_repeat", password_repeat); + + // let url = url::Url::parse(&self.site()).map_err(Error::InvalidUrl)?; + + let url = format!("{}/{}/register", self.site().trim_end_matches('/'), AUTH_API); + println!("Register URL: {}", url); + + let response = client + .post(url) + .headers(headers) // Ensure build_headers doesn't conflict + .form(¶ms) // <--- This automatically sets Content-Type to application/x-www-form-urlencoded + .send() + .await + .map_err(Error::OtherReqwest)?; + + let status = response.status(); + let body = response.text().await.map_err(Error::OtherReqwest)?; + + println!("Status: {}", status); + println!("Response Body: {}", body); // Check if TrailBase is returning a 'success' message that actually contains an error detail + + return Ok(body); + } + pub async fn logout(&self) -> Result<(), Error> { #[derive(Serialize)] struct LogoutRequest { @@ -818,11 +863,16 @@ impl Client { fn build_headers(tokens: Option<&Tokens>) -> HeaderMap { let mut base = HeaderMap::with_capacity(5); + + let mut value = HeaderValue::from_static("application/json"); + value.set_sensitive(false); base.insert( header::CONTENT_TYPE, - HeaderValue::from_static("application/json"), + value, ); + // base.insert(header::ACCEPT, HeaderValue::from_static("application/json")); + if let Some(tokens) = tokens { if let Ok(value) = HeaderValue::from_str(&format!("Bearer {}", tokens.auth_token)) { base.insert(header::AUTHORIZATION, value);