feat(server): allow specifying id address and port to bind to

Closes kemitix/git-next#44
This commit is contained in:
Paul Campbell 2024-05-10 22:01:47 +01:00
parent daa40e7621
commit 1cd56d953e
6 changed files with 57 additions and 8 deletions

View file

@ -1,5 +1,9 @@
[http]
addr = "0.0.0.0"
port = 8080
[webhook]
url = "https://localhost:8080/webhook"
url = "https://localhost:8080"
[storage]
path = "./data"

View file

@ -3,7 +3,7 @@ use std::path::PathBuf;
use actix::prelude::*;
use kxio::{fs::FileSystem, network::Network};
use tracing::{error, info};
use tracing::{error, info, warn};
use crate::server::{
actors::{
@ -62,6 +62,10 @@ impl Handler<ServerConfig> for Server {
#[allow(clippy::cognitive_complexity)] // TODO: (#75) reduce complexity
fn handle(&mut self, msg: ServerConfig, _ctx: &mut Self::Context) -> Self::Result {
let Ok(socket_addr) = msg.http() else {
warn!("Unable to parse http.addr");
return;
};
if let Some(webhook) = self.webhook.take() {
webhook.do_send(ShutdownWebhook);
}
@ -103,7 +107,7 @@ impl Handler<ServerConfig> for Server {
.for_each(|msg| webhook_router.do_send(msg));
}
let webhook = WebhookActor::new(webhook_router.recipient()).start();
let webhook = WebhookActor::new(socket_addr, webhook_router.recipient()).start();
self.webhook.replace(webhook);
}
}

View file

@ -4,6 +4,8 @@ mod message;
mod router;
mod server;
use std::net::SocketAddr;
use actix::prelude::*;
pub use message::WebhookMessage;
@ -13,14 +15,16 @@ use tracing::Instrument;
#[derive(Debug)]
pub struct WebhookActor {
socket_addr: SocketAddr,
span: tracing::Span,
spawn_handle: Option<actix::SpawnHandle>,
message_receiver: Recipient<WebhookMessage>,
}
impl WebhookActor {
pub fn new(message_receiver: Recipient<WebhookMessage>) -> Self {
pub fn new(socket_addr: SocketAddr, message_receiver: Recipient<WebhookMessage>) -> Self {
let span = tracing::info_span!("WebhookActor");
Self {
socket_addr,
span,
message_receiver,
spawn_handle: None,
@ -32,7 +36,7 @@ impl Actor for WebhookActor {
fn started(&mut self, ctx: &mut Self::Context) {
let _gaurd = self.span.enter();
let address: Recipient<WebhookMessage> = self.message_receiver.clone();
let server = server::start(address);
let server = server::start(self.socket_addr, address);
let spawn_handle = ctx.spawn(server.in_current_span().into_actor(self));
self.spawn_handle.replace(spawn_handle);
}

View file

@ -1,10 +1,15 @@
use std::net::SocketAddr;
use actix::prelude::*;
use tracing::{debug, info};
use crate::server::actors::webhook::message::WebhookMessage;
pub async fn start(address: actix::prelude::Recipient<super::message::WebhookMessage>) {
pub async fn start(
socket_addr: SocketAddr,
address: actix::prelude::Recipient<super::message::WebhookMessage>,
) {
// start webhook server
use warp::Filter;
// Define the Warp route to handle incoming HTTP requests
@ -49,6 +54,6 @@ pub async fn start(address: actix::prelude::Recipient<super::message::WebhookMes
);
// Start the server
info!("Starting webhook server: http://0.0.0.0:8080/");
warp::serve(route).run(([0, 0, 0, 0], 8080)).await;
info!("Starting webhook server: {}", socket_addr);
warp::serve(route).run(socket_addr).await;
}

View file

@ -5,8 +5,10 @@ pub mod load;
use std::{
collections::HashMap,
fmt::{Display, Formatter},
net::SocketAddr,
ops::Deref,
path::{Path, PathBuf},
str::FromStr,
};
use serde::Deserialize;
@ -21,6 +23,7 @@ pub enum Error {
Io(std::io::Error),
KxIoFs(kxio::fs::Error),
TomlDe(toml::de::Error),
AddressParse(std::net::AddrParseError),
}
impl std::error::Error for Error {}
@ -30,6 +33,7 @@ type Result<T> = core::result::Result<T, Error>;
#[derive(Debug, PartialEq, Eq, Deserialize, Message)]
#[rtype(result = "()")]
pub struct ServerConfig {
http: Http,
webhook: Webhook,
storage: ServerStorage,
forge: HashMap<String, ForgeConfig>,
@ -56,9 +60,29 @@ impl ServerConfig {
pub const fn webhook(&self) -> &Webhook {
&self.webhook
}
pub fn http(&self) -> Result<SocketAddr> {
self.http.socket_addr()
}
}
/// Defines the port the server will listen to for incoming webhooks messages
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
pub struct Http {
addr: String,
port: u16,
}
impl Http {
fn socket_addr(&self) -> Result<SocketAddr> {
Ok(SocketAddr::from_str(&format!(
"{}:{}",
self.addr, self.port
))?)
}
}
/// Defines the Webhook Forges should send updates to
/// Must be an address that is accessible from the remote forge
#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
pub struct Webhook {
url: String,

View file

@ -16,6 +16,10 @@ fn load_should_parse_server_config() -> Result<()> {
fs.file_write(
&fs.base().join("git-next-server.toml"),
r#"
[http]
addr = "0.0.0.0"
port = 8080
[webhook]
url = "http://localhost:9909/webhook"
@ -43,6 +47,10 @@ fn load_should_parse_server_config() -> Result<()> {
?;
let_assert!(Ok(config) = ServerConfig::load(&fs));
let expected = ServerConfig {
http: Http {
addr: "0.0.0.0".to_string(),
port: 8080,
},
webhook: Webhook {
url: "http://localhost:9909/webhook".to_string(),
},