1.1--- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2+++ b/rust/app/cli/alik/lib.rs Mon Jan 08 23:18:11 2024 -0500
1.3@@ -0,0 +1,94 @@
1.4+//! app/cli/alik/lib.rs --- Alik Lib
1.5+
1.6+//// Code:
1.7+// use net::axum::Router;
1.8+use net::axum::http::{HeaderMap, StatusCode};
1.9+use tokio::net::TcpListener;
1.10+use net::axum::{
1.11+ Router,
1.12+ extract::State,
1.13+ http::{HeaderName, HeaderValue},
1.14+ response::{IntoResponse,Response, self},
1.15+ routing::get,
1.16+ body::{Body, Bytes},
1.17+};
1.18+use net::http::graphql::{http::GraphiQLSource, EmptyMutation, EmptySubscription, Schema};
1.19+use net::http::graphql_axum::GraphQL;
1.20+use net::http::tower::trace::TraceLayer;
1.21+use logger::tracing::{self, Span};
1.22+use net::reqwest::Client;
1.23+use net::stream::StreamExt;
1.24+use std::{convert::Infallible, time::Duration};
1.25+use logger::log;
1.26+
1.27+pub async fn graphiql() -> impl IntoResponse {
1.28+ response::Html(GraphiQLSource::build().endpoint("/").finish())
1.29+}
1.30+
1.31+//// Server
1.32+pub async fn proxy_via_reqwest(State(client): State<Client>) -> Response {
1.33+ let reqwest_response = match client.get("http://127.0.0.1:3000/stream").send().await {
1.34+ Ok(res) => res,
1.35+ Err(err) => {
1.36+ log::error!("{} {}", &err, "request failed");
1.37+ return (StatusCode::BAD_REQUEST, Body::empty()).into_response();
1.38+ }
1.39+ };
1.40+
1.41+ let response_builder = Response::builder().status(reqwest_response.status().as_u16());
1.42+
1.43+ // Here the mapping of headers is required due to reqwest and axum differ on the http crate versions
1.44+ let mut headers = HeaderMap::with_capacity(reqwest_response.headers().len());
1.45+ headers.extend(reqwest_response.headers().into_iter().map(|(name, value)| {
1.46+ let name = HeaderName::from_bytes(name.as_ref()).unwrap();
1.47+ let value = HeaderValue::from_bytes(value.as_ref()).unwrap();
1.48+ (name, value)
1.49+ }));
1.50+
1.51+ response_builder
1.52+ .body(Body::from_stream(reqwest_response.bytes_stream()))
1.53+ // This unwrap is fine because the body is empty here
1.54+ .unwrap()
1.55+}
1.56+
1.57+pub async fn stream_some_data() -> Body {
1.58+ let stream = net::stream::iter(0..5)
1.59+ .throttle(Duration::from_secs(1))
1.60+ .map(|n| n.to_string())
1.61+ .map(Ok::<_, Infallible>);
1.62+ Body::from_stream(stream)
1.63+}
1.64+
1.65+pub async fn start_service() {
1.66+ let client = Client::new();
1.67+
1.68+ let app = Router::new()
1.69+ .route("/", get(proxy_via_reqwest))
1.70+ .route("/stream", get(stream_some_data))
1.71+ // Add some logging so we can see the streams going through
1.72+ .layer(TraceLayer::new_for_http().on_body_chunk(
1.73+ |chunk: &Bytes, _latency: Duration, _span: &Span| {
1.74+ tracing::debug!("streaming {} bytes", chunk.len());
1.75+ },
1.76+ ))
1.77+ .with_state(client);
1.78+
1.79+ let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")
1.80+ .await
1.81+ .unwrap();
1.82+ log::debug!("listening on {}", listener.local_addr().unwrap());
1.83+ net::axum::serve(listener, app).await.unwrap();
1.84+}
1.85+pub async fn start_graph_service() {
1.86+ // let schema = Schema::build(QueryRoot, EmptyMutation, EmptySubscription)
1.87+ // .data(Vec::new())
1.88+ // .finish();
1.89+
1.90+ let app = Router::new().route("/", get(graphiql));
1.91+ // .post_service(GraphQL::new(schema)));
1.92+
1.93+ println!("GraphiQL IDE: http://localhost:3000");
1.94+ net::axum::serve(TcpListener::bind("127.0.0.1:3000").await.unwrap(), app)
1.95+ .await
1.96+ .unwrap();
1.97+}