Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 121 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 39 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,45 @@
};

packages = {
run-stack = pkgs.writeShellApplication {
name = "run-stack";
runtimeInputs = [
pkgs.tinyproxy
pkgs.simple-http-server
];
text =
let
proxyConfig = pkgs.writeTextFile {
name = "proxy.conf";
text = ''
ReversePath "/" "http://0.0.0.0:8001/"
ReversePath "/api/" "http://0.0.0.0:8002/api/"
ReverseOnly Yes
Port 8000
ReverseBaseURL "http://0.0.0.0:8000/"
'';
};
in
''
simple-http-server --index --port 8001 frontend &
PID_FRONTEND=$!
cargo run -- --listen-address 0.0.0.0:8002 &
PID_BACKEND=$!
tinyproxy -d -c ${proxyConfig} &
PID_PROXY=$!

cleanup() {
kill $PID_FRONTEND $PID_BACKEND $PID_PROXY
wait $PID_FRONTEND $PID_BACKEND $PID_PROXY
exit 0
}

trap cleanup SIGINT

wait $PID_FRONTEND $PID_BACKEND $PID_PROXY
'';
};

server-deps = craneLib.buildDepsOnly commonAttrs;

server-docs = craneLib.cargoDoc (
Expand Down
21 changes: 21 additions & 0 deletions frontend/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/style.css">
<script src="https://unpkg.com/[email protected]" integrity="sha384-Y7hw+L/jvKeWIRRkqWYfPcvVxHzVzn5REgzbawhxAuQGwX1XWe70vji+VSeHOThJ" crossorigin="anonymous"></script>
<title>Demo</title>
</head>
<body>
<div id="app" hx-get="/api/v1/items" hx-trigger="load">
</div>
<noscript>
<p lang="en">
This website requires JavaScript. Here are the
<a href="https://www.enable-javascript.com/en/">instructions how to enable JavaScript in your web browser</a>.
Or perhaps you need to make an exception in your script blocker.
</p>
</noscript>
</body>
</html>
2 changes: 2 additions & 0 deletions frontend/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@import "https://unpkg.com/open-props";
@import "https://unpkg.com/open-props/normalize.min.css";
3 changes: 3 additions & 0 deletions server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ version = "0.1.0"
edition = "2021"

[dependencies]
askama = "0.12"
axum = { version = "0.8", features = ["tracing"] }
axum-extra = { version = "0.10", features = ["typed-routing"] }
clap = { version = "4", features = ["derive"] }
lazy_static = "1.5.0"
tokio = { version = "1", features = [ "full", "tracing"] }
tracing = "0.1"
tracing-subscriber = "0.3"
uuid = { version = "1", features = ["v4"] }

[dev-dependencies]
ureq = "2"
Expand Down
15 changes: 15 additions & 0 deletions server/src/item.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
use askama::Template;
use uuid::Uuid;

#[derive(Debug, Clone)]
pub struct Item {
pub id: Uuid,
pub name: String,
pub price: u128,
}

#[derive(Template)]
#[template(path = "items.html")]
pub struct ItemsTemplate<'a> {
pub items: &'a Vec<Item>,
}
1 change: 1 addition & 0 deletions server/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod cli;
pub mod item;
pub mod routes;

use crate::cli::CliArgs;
Expand Down
21 changes: 18 additions & 3 deletions server/src/routes.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
use axum::http::StatusCode;
use askama::Template;
use axum::response::Html;
use axum_extra::routing::TypedPath;
use lazy_static::lazy_static;
use std::sync::Mutex;
use tracing::instrument;

use crate::item::{Item, ItemsTemplate};

lazy_static! {
static ref ITEMS: Mutex<Vec<Item>> = Mutex::new(vec![Item {
id: uuid::Uuid::new_v4(),
name: "test".to_string(),
price: 12345
}]);
}

#[derive(TypedPath, Debug, Clone, Copy)]
#[typed_path("/api/v1/items")]
pub struct GetItemsPath;

#[instrument(level = "trace", ret)]
pub async fn get_items_handler(_: GetItemsPath) -> (StatusCode, &'static str) {
(StatusCode::OK, "Hello World!")
pub async fn get_items_handler(_: GetItemsPath) -> Html<String> {
let items = ITEMS.lock().unwrap();
let template = ItemsTemplate { items: &items };
Html(template.render().unwrap())
}
12 changes: 12 additions & 0 deletions server/templates/items.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<table>
<tr>
<th>Id</th>
<th>Name</th>
</tr>
{% for item in items %}
<tr>
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
</tr>
{% endfor %}
</table>
3 changes: 2 additions & 1 deletion server/tests/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ pub async fn test_server_listens() {
.unwrap()
.into_string()
.unwrap();
assert_eq!(response, "Hello World!")
assert!(response.contains("<table>"));
assert!(response.contains("test"))
})
.await
.unwrap();
Expand Down
Loading