Made it a git repo

This commit is contained in:
Slatian 2023-02-11 21:46:55 +01:00
commit afdec2b8a2
5 changed files with 1541 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

1418
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

13
Cargo.toml Normal file
View File

@ -0,0 +1,13 @@
[package]
name = "rust-web-thingy"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
axum = "0.6"
rand = "0.8"
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["full"] }
tera = "1"

99
src/main.rs Normal file
View File

@ -0,0 +1,99 @@
use axum::{
extract::Query,
extract::State,
http::StatusCode,
response::Html,
Router,
routing::get,
};
use tera::Tera;
use std::net::{IpAddr, Ipv4Addr};
use std::sync::Arc;
#[derive(serde::Deserialize, serde::Serialize)]
enum ResponseFormat {
#[serde(rename="text/plain", alias="text")]
TextPlain,
#[serde(rename="text/html", alias="html")]
TextHtml,
#[serde(rename="application/json", alias="json")]
ApplicationJson,
}
impl ToString for ResponseFormat {
fn to_string(&self) -> String {
match self {
ResponseFormat::TextPlain => "text/plain".to_string(),
ResponseFormat::TextHtml => "text/html".to_string(),
ResponseFormat::ApplicationJson => "application/json".to_string(),
}
}
}
#[derive(serde::Deserialize, serde::Serialize)]
struct IpQuery {
ip: Option<IpAddr>,
format: Option<ResponseFormat>,
}
struct ServiceSharedState {
tera: Tera,
}
#[tokio::main]
async fn main() {
// Initalize Tera templates
// TODO: don't hardcode template directory
let tera = match Tera::new("templates/*.html") {
Ok(t) => t,
Err(e) => {
println!("Template parsing error(s): {}", e);
::std::process::exit(1);
}
};
// Initialize shared state
let shared_state = Arc::new(ServiceSharedState{
tera: tera,
});
// Initalize axum server
let app = Router::new()
.route("/", get(handle_default_route))
.route("/hi", get(hello_world_handler))
.with_state(shared_state)
;
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
}
async fn hello_world_handler() -> &'static str {
"Hello, there, you, awesome creature!"
}
async fn handle_default_route(
Query(ip_query): Query<IpQuery>,
State(arc_state): State<Arc<ServiceSharedState>>,
) -> Result<Html<String>,StatusCode> {
let address = ip_query.ip.unwrap_or(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)));
let format = ip_query.format.unwrap_or(ResponseFormat::TextHtml);
let format_string = format.to_string();
let state = Arc::clone(&arc_state);
let mut context = tera::Context::new();
context.insert("ip", &address);
context.insert("format", &format_string);
match state.tera.render("index.html", &context) {
Ok(html) => Ok(Html(html)),
Err(e) => {
println!("There was an error while rendering index.html: {e}");
Err(StatusCode::INTERNAL_SERVER_ERROR)
}
}
}

10
templates/index.html Normal file
View File

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html>
<head>
<title>Your IP: {{ ip }}</title>
</head>
<body>
<h1>Your IP-Address is: {{ ip }}</h1>
<p>Your requested format was: <b>{{format}}</b></p>
</body>
</html>