implement request making

This commit is contained in:
Aleksandr 2025-10-06 01:36:36 +03:00
parent 840c0b95df
commit 5743585a77
6 changed files with 77 additions and 11 deletions

View file

@ -7,7 +7,7 @@ use eva::{
use http::Method;
use viendesu_core::{
errors,
errors::{self, Aux},
requests::Response,
service::{
CallStep, Session, SessionMaker,
@ -97,7 +97,56 @@ impl HttpClient {
where
R: Request,
{
todo!()
let mut endpoint = self.options.endpoint.clone();
if endpoint.ends_with('/') {
endpoint.push_str(path.strip_prefix('/').unwrap_or(path));
} else {
endpoint.push_str(path);
}
let mut req = self.client.request(method.clone(), endpoint);
if method == Method::GET {
req = req.query(&request);
} else {
let mut dst = Vec::with_capacity(128);
self.options
.format
.dump(Default::default(), &request, &mut dst);
req = req
.body(dst)
.header("content-type", self.options.format.mime_type());
}
if let Some(sess) = self.session {
req = req.header("authorization", format!("Bearer {}", sess.to_str()));
}
let response = self
.client
.execute(req.build().expect("shit happens"))
.await
.map_err(|e| Aux::InternalError(format_compact!("failed to make request: {e:#}")))?;
let bytes = response
.bytes()
.await
.map_err(|e| Aux::InternalError(format_compact!("failed to read bytes: {e:#}")))?;
#[derive(serde::Deserialize)]
#[serde(untagged)]
enum GenericResponse<O, E> {
Success { ok: O },
Error { error: errors::Generic<E> },
}
let resp: GenericResponse<R::Response, R::Error> =
self.options.format.load(&bytes).map_err(|e| {
Aux::Deserialization(format!("failed to deserialize response: {e:#}"))
})?;
match resp {
GenericResponse::Error { error } => Err(error),
GenericResponse::Success { ok } => Ok(ok),
}
}
}

View file

@ -1,12 +1,14 @@
pub mod status_code;
pub trait Request: Send + Sync + 'static + for<'de> serde::Deserialize<'de> {
pub trait Request:
Send + Sync + 'static + for<'de> serde::Deserialize<'de> + serde::Serialize
{
type Response: IsResponse;
type Error: IsResponse;
}
eva::trait_set! {
pub trait IsResponse = status_code::HasStatusCode + serde::Serialize + Send + Sync + 'static;
pub trait IsResponse = status_code::HasStatusCode + for<'de> serde::Deserialize<'de> + serde::Serialize + Send + Sync + 'static;
}
macro_rules! impl_req {

View file

@ -43,8 +43,6 @@ pub async fn load_args<R: ServerRequest>(req: AxumRequest) -> Result<Context<R>,
let response_format =
extract::response_format(&parts).map_err(|e| response::err(Format::default(), e))?;
let request_format =
extract::request_format(&parts).map_err(|e| response::err(Format::default(), e))?;
let request: R = if parts.method == Method::GET {
let query = parts.uri.query().unwrap_or("");
@ -52,6 +50,8 @@ pub async fn load_args<R: ServerRequest>(req: AxumRequest) -> Result<Context<R>,
.map_err(|e| Aux::Deserialization(format!("failed to decode query: {e}")))
.map_err(|e| response::err(response_format, e))?
} else {
let request_format =
extract::request_format(&parts).map_err(|e| response::err(response_format, e))?;
let content_length =
extract::content_length(&parts).map_err(|e| response::err(response_format, e))?;
let mut data_stream = body.into_data_stream();

View file

@ -9,7 +9,10 @@ use axum::{
routing::{MethodFilter, method_routing},
};
use viendesu_core::{errors as core_errors, service::SessionOf};
use viendesu_core::{
errors as core_errors,
service::{Session, SessionOf, authz::AuthenticationMut},
};
use crate::{
format::Format,
@ -118,11 +121,21 @@ impl<R: ServerRequest, M, T: Types, Cx: MakeContext<R>> FinishedHandler<R, M, T,
let (parts, body) = req.into_parts();
let context = make_context(AxumRequest::from_parts(parts, body)).await?;
let resp_format = context.response_format;
let session = state
let mut session = state
.make_session()
.await
.map_err(|e| response::err(resp_format, e))?;
if let Some(token) = extract::session_token(&context.parts)
.map_err(|e| response::err(resp_format, e))?
{
session
.authentication_mut()
.authenticate(token)
.await
.map_err(|e| response::err(resp_format, e))?;
}
match make_request(session, context).await {
Ok(r) => Ok(response::ok(resp_format, r)),
Err(e) => Err(response::err(resp_format, e)),

View file

@ -48,6 +48,8 @@ pub fn session_token(parts: &Parts) -> AuxResult<Option<session::Token>> {
)));
};
dbg!((scheme, rest));
match scheme {
"Bearer" => rest
.parse()

View file

@ -2,7 +2,7 @@ use axum::{
http::StatusCode,
response::{IntoResponse, Response as AxumResponse},
};
use serde::Serialize;
use serde::{Serialize, Deserialize};
use crate::format::{DumpParams, Format};
use crate::requests::{IsResponse, status_code::HasStatusCode};
@ -18,7 +18,7 @@ macro_rules! header {
#[track_caller]
pub fn err<E: IsResponse>(format: Format, error: E) -> AxumResponse {
#[derive(Serialize)]
#[derive(Serialize, Deserialize)]
struct Failure<E> {
pub error: E,
}
@ -34,7 +34,7 @@ pub fn err<E: IsResponse>(format: Format, error: E) -> AxumResponse {
#[track_caller]
pub fn ok<O: IsResponse>(format: Format, ok: O) -> AxumResponse {
#[derive(Serialize)]
#[derive(Serialize, Deserialize)]
struct Success<T> {
ok: T,
}