Skip to content

Commit fbb9011

Browse files
committed
feat: serve https
1 parent 3e5a0a1 commit fbb9011

File tree

15 files changed

+160
-25
lines changed

15 files changed

+160
-25
lines changed
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
-----BEGIN CERTIFICATE-----
2+
MIIBlTCCATugAwIBAgIUA86Riy2FThTljOBvpMNN5CmnVgIwCgYIKoZIzj0EAwIw
3+
IDEeMBwGA1UEAwwVc3luZGljYXRpb25kLnltZ3l0LmlvMB4XDTI0MDIxMTEwMDE1
4+
NFoXDTM0MDIwODEwMDE1NFowIDEeMBwGA1UEAwwVc3luZGljYXRpb25kLnltZ3l0
5+
LmlvMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEhztnvCAv0+oFHVue7EYfitKl
6+
HXw83579zSlB4DyhF/5LN8ljr0TljOTsSXlSAtPkladiASIDXPVm1xzzVgiHhaNT
7+
MFEwHQYDVR0OBBYEFBvVS3MisB/EBclw0i+v/iSXTNI0MB8GA1UdIwQYMBaAFBvV
8+
S3MisB/EBclw0i+v/iSXTNI0MA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwID
9+
SAAwRQIhALBtRGKYgN65Evvw4u7a7hmNw441BNUo0kXOL5kb+Rv4AiAjHfuhruKb
10+
qzmvo4OdZIVIWhrsBqakXynXmS5rZIiHng==
11+
-----END CERTIFICATE-----
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-----BEGIN PRIVATE KEY-----
2+
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgKmgzy8Zj73IXrit3
3+
EWT5DLFTagNNiwguS9j2I37ZIHShRANCAASHO2e8IC/T6gUdW57sRh+K0qUdfDzf
4+
nv3NKUHgPKEX/ks3yWOvROWM5OxJeVIC0+SVp2IBIgNc9WbXHPNWCIeF
5+
-----END PRIVATE KEY-----

Cargo.lock

+48-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ repository = "https://github.com/ymgyt/syndicationd"
1616
anyhow = { version = "1" }
1717
async-trait = { version = "0.1.77" }
1818
axum = { version = "0.7.4" }
19+
axum-server = { version = "0.6.0", features = ["tls-rustls"] }
1920
chrono = { version = "0.4.31" }
2021
clap = { version = "4.4" }
2122
feed-rs = { version = "1.4" }
@@ -24,6 +25,7 @@ graphql_client = { version = "0.13.0", default-features = false }
2425
headers = { version = "0.4.0" }
2526
http = { version = "0.2" } # request use 0.2
2627
kvsd = { version = "0.1.2", default-features = false }
28+
thiserror = { version = "1.0.56" }
2729
# kvsd = { path = "../kvsd" }
2830
moka = { version = "0.12.4", features = ["future"] }
2931
opentelemetry = { version = "0.21.0" }

crates/synd_api/Cargo.toml

+3-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ async-graphql = { version = "7.0", features = ["tracing"] }
1919
async-graphql-axum = { version = "7.0" }
2020
async-trait = { workspace = true }
2121
axum = { workspace = true }
22+
axum-server = { workspace = true }
2223
chrono = { workspace = true }
23-
clap = { workspace = true, features = ["derive"] }
24+
clap = { workspace = true, features = ["derive", "env"] }
2425
feed-rs = { workspace = true }
2526
futures-util = { workspace = true }
2627
graphql_client = { workspace = true }
@@ -33,7 +34,7 @@ serde = { workspace = true }
3334
serde_json = "1.0.111"
3435
supports-color = { version = "2.1.0" }
3536
synd_feed = { path = "../synd_feed", version = "0.1.0" }
36-
thiserror = "1.0.56"
37+
thiserror = { workspace = true }
3738
tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
3839
tower = { version = "0.4.13", default_features = false, features = ["limit", "timeout"] }
3940
tower-http = { version = "0.5.1", default_features = false, features = ["trace", "sensitive-headers", "cors", "limit"] }

crates/synd_api/src/args.rs

+20-5
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,40 @@
1+
use std::path::PathBuf;
2+
13
use clap::Parser;
24

35
#[derive(Parser, Debug)]
46
#[command(version, propagate_version = true, disable_help_subcommand = true)]
57
pub struct Args {
68
#[command(flatten)]
79
pub kvsd: KvsdOptions,
10+
#[command(flatten)]
11+
pub tls: TlsOptions,
812
}
913

1014
#[derive(clap::Args, Debug)]
11-
#[command(next_help_heading = "kvsd")]
15+
#[command(next_help_heading = "Kvsd options")]
1216
pub struct KvsdOptions {
13-
#[arg(long = "kvsd-host")]
17+
#[arg(long = "kvsd-host", env = "SYND_KVSD_HOST")]
1418
pub host: String,
15-
#[arg(long = "kvsd-port")]
19+
#[arg(long = "kvsd-port", env = "SYND_KVSD_PORT")]
1620
pub port: u16,
17-
#[arg(long = "kvsd-username")]
21+
#[arg(long = "kvsd-username", alias = "kvsd-user", env = "SYND_KVSD_USER")]
1822
pub username: String,
19-
#[arg(long = "kvsd-password")]
23+
#[arg(long = "kvsd-password", alias = "kvsd-pass", env = "SYND_KVSD_PASS")]
2024
pub password: String,
2125
}
2226

27+
#[derive(clap::Args, Debug)]
28+
#[command(next_help_heading = "Tls options")]
29+
pub struct TlsOptions {
30+
/// Tls certificate file path
31+
#[arg(long = "tls-cert", env = "SYND_TLS_CERT", value_name = "CERT_PATH")]
32+
pub certificate: PathBuf,
33+
/// Tls private key file path
34+
#[arg(long = "tls-key", env = "SYND_TLS_KEY", value_name = "KEY_PATH")]
35+
pub private_key: PathBuf,
36+
}
37+
2338
#[must_use]
2439
pub fn parse() -> Args {
2540
Args::parse()

crates/synd_api/src/dependency.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
use std::{sync::Arc, time::Duration};
22

3+
use anyhow::Context;
4+
use axum_server::tls_rustls::RustlsConfig;
35
use synd_feed::feed::{
46
cache::{CacheConfig, CacheLayer},
57
parser::FeedService,
68
};
79

810
use crate::{
9-
args::KvsdOptions,
11+
args::{KvsdOptions, TlsOptions},
1012
config,
1113
repository::kvsd::KvsdClient,
1214
serve::auth::Authenticator,
@@ -16,10 +18,11 @@ use crate::{
1618
pub struct Dependency {
1719
pub authenticator: Authenticator,
1820
pub runtime: Runtime,
21+
pub tls_config: RustlsConfig,
1922
}
2023

2124
impl Dependency {
22-
pub async fn new(kvsd: KvsdOptions) -> anyhow::Result<Self> {
25+
pub async fn new(kvsd: KvsdOptions, tls: TlsOptions) -> anyhow::Result<Self> {
2326
let KvsdOptions {
2427
host,
2528
port,
@@ -48,9 +51,14 @@ impl Dependency {
4851

4952
let runtime = Runtime::new(make_usecase, authorizer);
5053

54+
let tls_config = RustlsConfig::from_pem_file(&tls.certificate, &tls.private_key)
55+
.await
56+
.with_context(|| format!("tls options: {tls:?}"))?;
57+
5158
Ok(Dependency {
5259
authenticator,
5360
runtime,
61+
tls_config,
5462
})
5563
}
5664
}

crates/synd_api/src/main.rs

+22-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
use synd_o11y::{opentelemetry::OpenTelemetryGuard, tracing_subscriber::otel_metrics};
22
use tracing::{error, info};
33

4-
use synd_api::{args, config, dependency::Dependency, serve::listen_and_serve, shutdown::Shutdown};
4+
use synd_api::{
5+
args::{self, Args},
6+
config,
7+
dependency::Dependency,
8+
repository::kvsd::ConnectKvsdFailed,
9+
serve::listen_and_serve,
10+
shutdown::Shutdown,
11+
};
512

613
fn init_tracing() -> Option<OpenTelemetryGuard> {
714
use synd_o11y::{
@@ -65,17 +72,26 @@ fn init_tracing() -> Option<OpenTelemetryGuard> {
6572
guard
6673
}
6774

75+
async fn run(Args { kvsd, tls }: Args, shutdown: Shutdown) -> anyhow::Result<()> {
76+
let dep = Dependency::new(kvsd, tls).await?;
77+
78+
info!(version = config::VERSION, "Runinng...");
79+
80+
listen_and_serve(dep, shutdown.notify()).await
81+
}
82+
6883
#[tokio::main]
6984
async fn main() {
7085
let args = args::parse();
7186
let _guard = init_tracing();
72-
let dep = Dependency::new(args.kvsd).await.unwrap();
7387
let shutdown = Shutdown::watch_signal();
7488

75-
info!(version = config::VERSION, "Runinng...");
76-
77-
if let Err(err) = listen_and_serve(dep, shutdown.notify()).await {
78-
error!("{err:?}");
89+
if let Err(err) = run(args, shutdown).await {
90+
if let Some(err) = err.downcast_ref::<ConnectKvsdFailed>() {
91+
error!("{err}: make sure kvsd is running");
92+
} else {
93+
error!("{err:?}");
94+
}
7995
std::process::exit(1);
8096
}
8197
}

crates/synd_api/src/repository/kvsd.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
use std::{io::ErrorKind, time::Duration};
22

3+
use anyhow::Context;
34
use async_trait::async_trait;
45
use futures_util::TryFutureExt;
56
use kvsd::{
67
client::{tcp::Client, Api},
78
Key, Value,
89
};
910
use serde::{Deserialize, Serialize};
11+
use thiserror::Error;
1012
use tokio::sync::Mutex;
1113
use tokio::{net::TcpStream, sync::MutexGuard};
1214

1315
use crate::repository::{
1416
self, subscription::RepositoryResult, RepositoryError, SubscriptionRepository,
1517
};
1618

19+
#[derive(Error, Debug)]
20+
#[error("connect kvsd failed")]
21+
pub struct ConnectKvsdFailed;
22+
1723
pub struct KvsdClient {
1824
#[allow(dead_code)]
1925
client: Mutex<Client<TcpStream>>,
@@ -48,14 +54,16 @@ impl KvsdClient {
4854
err => break err,
4955
}
5056
retry += 1;
51-
tokio::time::sleep(Duration::from_millis(500)).await;
57+
tokio::time::sleep(Duration::from_millis(1000)).await;
5258
}
5359
};
5460

5561
tokio::time::timeout(timeout, handshake)
56-
.await?
62+
.await
63+
.map_err(anyhow::Error::from)
64+
.context(ConnectKvsdFailed)?
65+
.map_err(anyhow::Error::from)
5766
.inspect(|_| tracing::info!("Kvsd handshake successfully completed"))
58-
.map_err(Into::into)
5967
}
6068

6169
async fn get<'a, T>(

crates/synd_api/src/serve/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ where
4848
let Dependency {
4949
authenticator,
5050
runtime,
51+
tls_config,
5152
} = dep;
5253

5354
let schema = gql::schema_builder().data(runtime).finish();
@@ -71,8 +72,8 @@ where
7172
)
7273
.route("/healthcheck", get(probe::healthcheck));
7374

74-
axum::serve(listener, service)
75-
.with_graceful_shutdown(shutdown)
75+
axum_server::from_tcp_rustls(listener.into_std()?, tls_config)
76+
.serve(service.into_make_service())
7677
.await?;
7778

7879
tracing::info!("Shutdown complete");

crates/synd_term/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ integration = []
5252
synd_api = { path = "../synd_api" }
5353
synd_test = { path = "../synd_test" }
5454

55+
axum-server = { workspace = true }
5556
kvsd = { workspace = true }
5657
serial_test = { version = "3.0.0", default_features = false, features = ["async", "file_locks"] }
5758
tempdir = "0.3.7"

crates/synd_term/src/client/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ impl Client {
3131
.user_agent(config::USER_AGENT)
3232
.timeout(Duration::from_secs(10))
3333
.connect_timeout(Duration::from_secs(10))
34+
// this client specifically targets the syndicationd api, so accepts self signed certificates
35+
.danger_accept_invalid_certs(true)
3436
.build()?;
3537

3638
Ok(Self {

crates/synd_term/src/config.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::{
66
use directories::ProjectDirs;
77

88
pub mod api {
9-
pub const ENDPOINT: &str = "http://localhost:5959/graphql";
9+
pub const ENDPOINT: &str = "https://localhost:5959/graphql";
1010
}
1111

1212
pub mod github {

0 commit comments

Comments
 (0)