feat: init

main
Moritz Böhme 2024-01-20 12:02:46 +01:00
commit 7e1cecc167
Signed by: moritz
GPG Key ID: 970C6E89EB0547A9
9 changed files with 1854 additions and 0 deletions

1
.envrc Normal file
View File

@ -0,0 +1 @@
use flake

28
.gitignore vendored Normal file
View File

@ -0,0 +1,28 @@
# Created by https://www.toptal.com/developers/gitignore/api/direnv
# Edit at https://www.toptal.com/developers/gitignore?templates=direnv
### direnv ###
.direnv
.envrc
# End of https://www.toptal.com/developers/gitignore/api/direnv
# Created by https://www.toptal.com/developers/gitignore/api/rust
# Edit at https://www.toptal.com/developers/gitignore?templates=rust
### Rust ###
# Generated by Cargo
# will have compiled files and executables
debug/
target/
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
# These are backup files generated by rustfmt
**/*.rs.bk
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
# End of https://www.toptal.com/developers/gitignore/api/rust

1594
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 = "counter-rust"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
actix-web = { version = "4.4.1" }
askama = { version = "0.12.1", features = ["with-actix-web"] }
askama_actix = "0.14.0"
env_logger = "0.11.0"
rustls = "0.22.2"

93
flake.lock Normal file
View File

@ -0,0 +1,93 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1705309234,
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"naersk": {
"inputs": {
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1698420672,
"narHash": "sha256-/TdeHMPRjjdJub7p7+w55vyABrsJlt5QkznPYy55vKA=",
"owner": "nix-community",
"repo": "naersk",
"rev": "aeb58d5e8faead8980a807c840232697982d47b9",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "naersk",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1704161960,
"narHash": "sha256-QGua89Pmq+FBAro8NriTuoO/wNaUtugt29/qqA8zeeM=",
"path": "/nix/store/7b7m3p9gc9da6cd7wgyabs3wg1832j0v-source",
"rev": "63143ac2c9186be6d9da6035fa22620018c85932",
"type": "path"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1705666311,
"narHash": "sha256-VYdSQm7zq3AStyHhRr3SBCTA8fVzrl6WtIlXTs2Wlts=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "a455c5fb3ee513e2f443838a0e84d52b035adb67",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"naersk": "naersk",
"nixpkgs": "nixpkgs_2"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

30
flake.nix Normal file
View File

@ -0,0 +1,30 @@
{
inputs = {
flake-utils.url = "github:numtide/flake-utils";
naersk.url = "github:nix-community/naersk";
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
};
outputs = { self, flake-utils, naersk, nixpkgs }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = (import nixpkgs) {
inherit system;
};
naersk' = pkgs.callPackage naersk { };
in
rec {
# For `nix build` & `nix run`:
defaultPackage = naersk'.buildPackage {
src = ./.;
};
# For `nix develop`:
devShell = pkgs.mkShell {
nativeBuildInputs = with pkgs; [ rustc cargo rust-analyzer clippy entr ];
};
}
);
}

63
src/main.rs Normal file
View File

@ -0,0 +1,63 @@
use std::sync::Mutex;
use actix_web::{App, HttpServer};
use actix_web::web;
use askama::Template;
#[derive(Debug)]
struct AppState {
counter: Mutex<i32>
}
#[derive(Template)]
#[template(path = "counter.html")]
struct CounterTemplate {
counter: i32,
}
#[derive(Template)]
#[template(path = "index.html", escape = "txt")]
struct IndexTemplate {
counter: CounterTemplate,
}
#[actix_web::get("/")]
async fn index(data: web::Data<AppState>) -> impl actix_web::Responder {
let counter = data.counter.lock().unwrap();
let counter_template = CounterTemplate { counter: *counter };
IndexTemplate { counter: counter_template }
}
#[actix_web::post("/api/increment")]
async fn increment(data: web::Data<AppState>) -> impl actix_web::Responder {
let mut counter = data.counter.lock().unwrap();
*counter += 1;
CounterTemplate { counter: *counter }
}
#[actix_web::post("/api/decrement")]
async fn decrement(data: web::Data<AppState>) -> impl actix_web::Responder {
let mut counter = data.counter.lock().unwrap();
*counter -= 1;
CounterTemplate { counter: *counter }
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
std::env::set_var("RUST_LOG", "debug");
env_logger::init();
println!("Starting webserver on port 8080");
let app_state = web::Data::new( AppState {
counter: Mutex::new(0)
});
HttpServer::new(move|| {
App::new()
.app_data(app_state.clone())
.service(index)
.service(increment)
.service(decrement)
})
.bind(("127.0.0.1", 8080))?
.run()
.await
}

3
templates/counter.html Normal file
View File

@ -0,0 +1,3 @@
<h1 id="counter" class="text-6xl font-bold text-gray-800 dark:text-gray-200">
{{ counter }}
</h1>

29
templates/index.html Normal file
View File

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title></title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/htmx.org@1.9.10" integrity="sha384-D1Kt99CQMDuVetoL1lrYwg5t+9QdHe7NLX/SoJYkXDFfX37iInKRy5xLSi8nO7UC" crossorigin="anonymous"></script>
</head>
<body>
<div class="flex flex-col items-center justify-center h-screen bg-gray-100 dark:bg-gray-900">
<div class="text-center">
{{ counter }}
<p class="text-xl text-gray-600 dark:text-gray-400">
Click the buttons to increase or decrease the counter
</p>
</div>
<div class="mt-8 flex gap-4">
<button hx-post="/api/increment" hx-target="#counter" class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50">
Increment
</button>
<button hx-post="/api/decrement" hx-target="#counter" class="px-4 py-2 bg-red-500 text-white rounded hover:bg-red-600 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-opacity-50">
Decrement
</button>
</div>
</div>
</body>
</html>