commit - 1cb08214cf3a82ad3acb8fec023e7fb2a404f6bd
commit + c806356b760c9478ac6b47e22e71917ba436bcd8
blob - 556952c4198c548f93bd7667434b18fda7be9c84
blob + 9b0bebcc211a37fb3c319e992a6b8b8919de1f93
--- web/README.md
+++ web/README.md
* [x] Graceful Shutdown
* [x] Minijinja
* [x] Prometheus
-* [ ] Middleware Ip
+* [x] Middleware Ip
* [x] Request Id Header
* [x] Static files
* [x] Config
blob - 207eafbd53830c5193ccc5ea5502abca1654ccd8
blob + d266dac95ef710f4e07d61d0565c34bc52ca0566
--- web/template/Cargo.toml
+++ web/template/Cargo.toml
[dependencies]
anyhow = "=1.0.100"
axum = { version = "=0.8.6", features = ["macros"] }
+axum-client-ip = "=1.1.3"
axum-messages = "=0.8.0"
axum_csrf = { version = "=0.11.0", features = ["layer"] }
config = { version = "=0.15.19", default-features = false, features = ["toml"] }
blob - f9c63402ebb48560a26b3ab2a1b4286a335395f8
blob + d1f56d93282c97bddded2b3c6399390911d2364c
--- web/template/src/main.rs
+++ web/template/src/main.rs
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
+use std::net::SocketAddr;
use std::sync::Arc;
use minijinja::Environment;
mod helpers;
mod metric;
mod router;
-mod state;
mod settings;
+mod state;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// TODO(msi): from config
let listener = TcpListener::bind("0.0.0.0:3000").await?;
info!("listening on http://{}", listener.local_addr().unwrap());
- axum::serve(listener, app)
- .with_graceful_shutdown(helpers::shutdown_signal())
- .await?;
+ axum::serve(
+ listener,
+ app.into_make_service_with_connect_info::<SocketAddr>(),
+ )
+ .with_graceful_shutdown(helpers::shutdown_signal())
+ .await?;
Ok(())
}
blob - 170890ae66c2802d5e4c9638ba179ea083e46c7b
blob + ca2f2a800fa47ac104c61617c1a9d127a84700b4
--- web/template/src/router.rs
+++ web/template/src/router.rs
response::{Html, IntoResponse, Redirect},
routing::get,
};
+use axum_client_ip::{ClientIp, ClientIpSource};
use axum_csrf::{CsrfConfig, CsrfLayer, CsrfToken, Key};
use axum_messages::{Messages, MessagesManagerLayer};
use minijinja::context;
.with_key(Some(cookie_key))
.with_cookie_domain(Some("127.0.0.1"));
+ // TODO(msi): from config, if debug mode
+ let ip_source = ClientIpSource::ConnectInfo;
+
Router::new()
.route("/", get(handler_home))
.route("/content", get(handler_content))
.route("/message", get(set_messages_handler))
.route("/read-messages", get(read_messages_handler))
.route("/csrf", get(csrf_root).post(csrf_check_key))
+ .route("/ip", get(ip_handler))
.layer(MessagesManagerLayer)
// TODO(msi): from config folder asssets
.nest_service("/assets", ServeDir::new("assets"))
.with_expiry(Expiry::OnInactivity(Duration::seconds(10))),
MessagesManagerLayer,
CsrfLayer::new(config),
+ ip_source.into_extension(),
// TODO(msi): from config
TimeoutLayer::new(std::time::Duration::from_secs(10)),
PropagateRequestIdLayer::new(x_request_id),
.with_state(app_state)
}
+async fn ip_handler(ClientIp(ip): ClientIp) -> String {
+ ip.to_string()
+}
+
async fn csrf_root(
token: CsrfToken,
State(state): State<Arc<AppState>>,
blob - 897cbf4288d8cc11fc05ceb140d88314764f74bd
blob + 981476489b4c549916d998d1ff06ed29398442de
--- web/template/src/settings.rs
+++ web/template/src/settings.rs
impl Settings {
pub(crate) fn new() -> Result<Self, ConfigError> {
info!("loading settings");
- let run_mode = env::var("RUN_MODE").unwrap_or_else(|_| "development".into());
+ let run_mode =
+ env::var("RUN_MODE").unwrap_or_else(|_| "development".into());
let s = Config::builder()
// Start off by merging in the "default" configuration file
// Default to 'development' env
// Note that this file is _optional_
.add_source(
- File::with_name(&format!("config/{run_mode}"))
- .required(false),
+ File::with_name(&format!("config/{run_mode}")).required(false),
)
// Add in a local configuration file
// This file shouldn't be checked in to git
blob - f162c30c552c43988a707bd39c1cbd88cc1ed4a4
blob + 6abc2fda11620fbecb3d72b3b37cc2b3dac02d2d
--- web/template/templates/layout.jinja
+++ web/template/templates/layout.jinja
<li><a href="/message">Set Message</a></li>
<li><a href="/read-messages">Read Messages</a></li>
<li><a href="/csrf">Csrf</a></li>
+ <li><a href="/ip">Ip</a></li>
</ul>
</nav>
<h1><h1>Hello, World web =]</h1>