1
0
mirror of synced 2025-01-11 16:24:16 +00:00

WIP: http server

This commit is contained in:
al8n 2023-01-06 20:18:03 +13:00 committed by Gusto Bacvinka
parent a66641deb3
commit e11ce63c96
3 changed files with 186 additions and 0 deletions

View File

@ -6,11 +6,15 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
axum = "0.6"
async-trait = "0.1"
clap = { version = "4", features = ["derive", "env"], optional = true }
overwatch-rs = { git = "https://github.com/logos-co/Overwatch", branch = "main" }
overwatch-derive = { git = "https://github.com/logos-co/Overwatch", branch = "main" }
serde = { version = "1.0", features = ["derive"] }
tracing = "0.1"
tracing-appender = "0.2"
tracing-subscriber = { version = "0.3", features = ["json"] }
tracing-gelf = "0.7"
tower-http = { version = "0.3", features = ["cors", "trace"] }
futures = "0.3"

View File

@ -0,0 +1,73 @@
use std::{
collections::HashMap,
sync::{Arc, Mutex},
};
use clap::Parser;
use nomos_http::*;
use overwatch_rs::{
overwatch::OverwatchRunner,
services::{
handle::{ServiceHandle, ServiceStateHandle},
relay::{NoMessage, Relay},
state::{NoOperator, NoState},
ServiceCore, ServiceData, ServiceId,
}, DynError,
};
pub struct Foo;
impl ServiceData for Foo {
const SERVICE_ID: ServiceId = "Foo";
type Settings = ();
type State = NoState<()>;
type StateOperator = NoOperator<Self::State>;
type Message = NoMessage;
}
#[async_trait::async_trait]
impl ServiceCore for Foo {
/// Initialize the service with the given state
fn init(service_state: ServiceStateHandle<Self>) -> Result<Self, DynError> {
Ok(Self)
}
/// Service main loop
async fn run(mut self) -> Result<(), DynError> {
Ok(())
}
}
#[derive(overwatch_derive::Services)]
struct Services {
http: ServiceHandle<HttpServer<Foo>>,
}
#[derive(clap::Parser)]
pub struct Args {
#[clap(flatten)]
http: ServerSettings,
}
fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let settings = Args::parse();
let graphql = OverwatchRunner::<Services>::run(
ServicesServiceSettings {
http: settings.http,
},
None,
)?;
// tracing_subscriber::fmt::fmt()
// // .with_env_filter(std::env::var("RUST_LOG").unwrap_or_else(|_| "info".to_owned()))
// .with_file(false)
// .init();
graphql.wait_finished();
Ok(())
}

View File

@ -0,0 +1,109 @@
// std
// crates
use axum::{
http::{
header::{CONTENT_TYPE, USER_AGENT},
HeaderValue,
},
routing::{post, get},
Router, Server, response::Html,
};
use tower_http::{
cors::{Any, CorsLayer},
trace::TraceLayer,
};
// internal
use overwatch_rs::services::relay::Relay;
use overwatch_rs::services::{
handle::ServiceStateHandle,
relay::NoMessage,
state::{NoOperator, NoState},
ServiceCore, ServiceData, ServiceId,
};
/// Configuration for the Http Server
#[derive(Debug, Clone, clap::Args, serde::Deserialize, serde::Serialize)]
pub struct ServerSettings {
/// Socket where the server will be listening on for incoming requests.
#[arg(short, long = "addr", default_value_t = std::net::SocketAddr::new(std::net::IpAddr::V4(std::net::Ipv4Addr::new(127, 0, 0, 1)), 8080), env = "HTTP_ADDRESS")]
pub address: std::net::SocketAddr,
/// Allowed origins for this server deployment requests.
#[arg(long = "cors-origin")]
pub cors_origins: Vec<String>,
}
pub trait Data {
}
pub trait Abstration {
}
#[derive(Clone)]
pub struct HttpServer<HTTPAbstration: ServiceCore> {
settings: ServerSettings,
http_abstraction_channel: Relay<HTTPAbstration>,
}
impl<Backend: ServiceCore + Send + Sync + 'static> ServiceData for HttpServer<Backend> {
const SERVICE_ID: ServiceId = "HttpServer";
type Settings = ServerSettings;
type State = NoState<ServerSettings>;
type StateOperator = NoOperator<Self::State>;
type Message = NoMessage;
}
async fn handler() -> Html<&'static str> {
Html("<h1>Hello, World!</h1>")
}
#[async_trait::async_trait]
impl<HTTPAbstration: ServiceCore + Send + Sync + 'static> ServiceCore for HttpServer<HTTPAbstration>
{
fn init(service_state: ServiceStateHandle<Self>) -> Result<Self, overwatch_rs::DynError> {
let settings = service_state.settings_reader.get_updated_settings();
let http_abstraction_channel: Relay<HTTPAbstration> =
service_state.overwatch_handle.relay();
Ok(Self {
settings,
http_abstraction_channel,
})
}
async fn run(mut self) -> Result<(), overwatch_rs::DynError> {
let mut builder = CorsLayer::new();
if self.settings.cors_origins.is_empty() {
builder = builder.allow_origin(Any);
}
for origin in &self.settings.cors_origins {
builder = builder.allow_origin(
origin
.as_str()
.parse::<HeaderValue>()
.expect("fail to parse origin"),
);
}
let cors = builder
.allow_headers([CONTENT_TYPE, USER_AGENT])
.allow_methods(Any);
let addr = self.settings.address;
let router = Router::new()
.route("/", get(handler))
.layer(cors)
.layer(TraceLayer::new_for_http());
tracing::info!("HTTP server listening: {}", addr);
let mut srv = Server::bind(&addr).serve(router.into_make_service());
let conn = self.http_abstraction_channel.connect().await?;
Ok(())
}
}