mirror of
https://github.com/kristoferssolo/zero2prod.git
synced 2025-10-21 20:10:40 +00:00
feat(config): add config file
This commit is contained in:
parent
5ce9b4a766
commit
938bb7d071
1285
Cargo.lock
generated
1285
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -15,7 +15,9 @@ name = "zero2prod"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
axum = "0.7"
|
axum = "0.7"
|
||||||
|
config = "0.14"
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
sqlx = { version = "0.7", features = ["runtime-tokio", "tls-rustls", "macros", "postgres", "uuid", "chrono", "migrate"] }
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|||||||
38
src/configuation.rs
Normal file
38
src/configuation.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct Settings {
|
||||||
|
pub database: DatabaseSettings,
|
||||||
|
pub application_port: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct DatabaseSettings {
|
||||||
|
pub username: String,
|
||||||
|
pub password: String,
|
||||||
|
pub port: u16,
|
||||||
|
pub host: String,
|
||||||
|
pub database_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for DatabaseSettings {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"postgres://{}:{}@{}:{}/{}",
|
||||||
|
self.username, self.password, self.host, self.port, self.database_name
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_configuration() -> Result<Settings, config::ConfigError> {
|
||||||
|
let settings = config::Config::builder()
|
||||||
|
.add_source(config::File::new(
|
||||||
|
"configuration.toml",
|
||||||
|
config::FileFormat::Toml,
|
||||||
|
))
|
||||||
|
.build()?;
|
||||||
|
settings.try_deserialize::<Settings>()
|
||||||
|
}
|
||||||
40
src/lib.rs
40
src/lib.rs
@ -1,37 +1,3 @@
|
|||||||
use axum::{
|
pub mod configuation;
|
||||||
extract::Path,
|
pub mod routes;
|
||||||
http::StatusCode,
|
pub mod startup;
|
||||||
response::IntoResponse,
|
|
||||||
routing::{get, post},
|
|
||||||
Form, Router,
|
|
||||||
};
|
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
pub fn app() -> Router {
|
|
||||||
Router::new()
|
|
||||||
.route("/", get(root))
|
|
||||||
.route("/:name", get(greet))
|
|
||||||
.route("/health_check", get(health_check))
|
|
||||||
.route("/subscribtions", post(subscribe))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn root() -> impl IntoResponse {
|
|
||||||
"Hello, world!"
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn greet(Path(name): Path<String>) -> impl IntoResponse {
|
|
||||||
format!("Hello, {name}!")
|
|
||||||
}
|
|
||||||
async fn health_check() -> impl IntoResponse {
|
|
||||||
StatusCode::OK
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct FormData {
|
|
||||||
name: String,
|
|
||||||
email: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn subscribe(Form(form): Form<FormData>) -> impl IntoResponse {
|
|
||||||
StatusCode::OK
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,12 +1,14 @@
|
|||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
|
use zero2prod::{configuation::get_configuration, routes::route};
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() -> Result<(), std::io::Error> {
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 8000));
|
let configuation = get_configuration().expect("Failed to read configuation.");
|
||||||
|
let addr = SocketAddr::from(([127, 0, 0, 1], configuation.application_port));
|
||||||
let listener = TcpListener::bind(addr)
|
let listener = TcpListener::bind(addr)
|
||||||
.await
|
.await
|
||||||
.expect("Failed to bind random port");
|
.expect("Failed to bind random port");
|
||||||
axum::serve(listener, zero2prod::app()).await.unwrap();
|
axum::serve(listener, route()).await
|
||||||
}
|
}
|
||||||
|
|||||||
5
src/routes/health_check.rs
Normal file
5
src/routes/health_check.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
use axum::{http::StatusCode, response::IntoResponse};
|
||||||
|
|
||||||
|
pub async fn health_check() -> impl IntoResponse {
|
||||||
|
StatusCode::OK
|
||||||
|
}
|
||||||
15
src/routes/mod.rs
Normal file
15
src/routes/mod.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
mod health_check;
|
||||||
|
mod subscibtions;
|
||||||
|
use axum::{
|
||||||
|
routing::{get, post},
|
||||||
|
Router,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub use health_check::*;
|
||||||
|
pub use subscibtions::*;
|
||||||
|
|
||||||
|
pub fn route() -> Router {
|
||||||
|
Router::new()
|
||||||
|
.route("/health_check", get(health_check))
|
||||||
|
.route("/subscribtions", post(subscribe))
|
||||||
|
}
|
||||||
11
src/routes/subscibtions.rs
Normal file
11
src/routes/subscibtions.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
use axum::{http::StatusCode, response::IntoResponse, Form};
|
||||||
|
use serde::Deserialize;
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct FormData {
|
||||||
|
name: String,
|
||||||
|
email: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn subscribe(Form(form): Form<FormData>) -> impl IntoResponse {
|
||||||
|
StatusCode::OK
|
||||||
|
}
|
||||||
2
src/startup.rs
Normal file
2
src/startup.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
|
||||||
@ -1,5 +1,7 @@
|
|||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
|
use sqlx::{Connection, PgConnection};
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
|
use zero2prod::{configuation::get_configuration, routes::route};
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn health_check() {
|
async fn health_check() {
|
||||||
@ -19,6 +21,11 @@ async fn health_check() {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn subscribe_returns_200_for_valid_form_data() {
|
async fn subscribe_returns_200_for_valid_form_data() {
|
||||||
let address = spawn_app().await;
|
let address = spawn_app().await;
|
||||||
|
let configuration = get_configuration().expect("Failed to read configuration.");
|
||||||
|
let db_url = configuration.database.to_string();
|
||||||
|
let connection = PgConnection::connect(&db_url)
|
||||||
|
.await
|
||||||
|
.expect("Failed to connect to Postgres.");
|
||||||
let client = Client::new();
|
let client = Client::new();
|
||||||
|
|
||||||
let body = "name=kristofers%20solo&email=dev%40kristofers.solo";
|
let body = "name=kristofers%20solo&email=dev%40kristofers.solo";
|
||||||
@ -67,6 +74,6 @@ async fn spawn_app() -> String {
|
|||||||
.await
|
.await
|
||||||
.expect("Failed to bind random port");
|
.expect("Failed to bind random port");
|
||||||
let port = listener.local_addr().unwrap().port();
|
let port = listener.local_addr().unwrap().port();
|
||||||
let _ = tokio::spawn(async move { axum::serve(listener, zero2prod::app()).await.unwrap() });
|
let _ = tokio::spawn(async move { axum::serve(listener, route()).await.unwrap() });
|
||||||
format!("http://127.0.0.1:{}", port)
|
format!("http://127.0.0.1:{}", port)
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user