mirror of
https://github.com/zzzzDev4/ias-tea-axum.git
synced 2025-04-21 07:41:21 +02:00
Initial commit: Axum, Postgres DB setup
This commit is contained in:
commit
79c245f5c8
8 changed files with 3279 additions and 0 deletions
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
/target
|
||||||
|
.shuttle-storage
|
||||||
|
Secrets*.toml
|
||||||
|
.vscode
|
3128
Cargo.lock
generated
Normal file
3128
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
16
Cargo.toml
Normal file
16
Cargo.toml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
[package]
|
||||||
|
name = "ias-tea-axum"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
|
||||||
|
axum = "0.7.3"
|
||||||
|
serde = { version = "1.0.188", features = ["derive"] }
|
||||||
|
shuttle-axum = "0.44.0"
|
||||||
|
shuttle-runtime = "0.44.0"
|
||||||
|
shuttle-shared-db = { version = "0.44.0", features = ["postgres", "sqlx"] }
|
||||||
|
sqlx = "0.7.1"
|
||||||
|
tokio = "1.28.2"
|
||||||
|
|
||||||
|
tower-http = { version = "0.5.0", features = ["fs"] }
|
33
assets/index.html
Normal file
33
assets/index.html
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Tea Homepage</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Tea is great.</p>
|
||||||
|
<input type="text" id="myInput">
|
||||||
|
<button id="myButton">Click me if you want tea!</button>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
document.getElementById('myButton').addEventListener('click', function() {
|
||||||
|
var myHeaders = new Headers();
|
||||||
|
myHeaders.append('Content-Type', 'application/json');
|
||||||
|
|
||||||
|
var inputValue = document.getElementById('myInput').value;
|
||||||
|
var raw = JSON.stringify({ "teaname": inputValue });
|
||||||
|
|
||||||
|
var requestOptions = {
|
||||||
|
method: 'POST',
|
||||||
|
headers: myHeaders,
|
||||||
|
body: raw,
|
||||||
|
redirect: 'follow'
|
||||||
|
};
|
||||||
|
|
||||||
|
fetch('https://ias-tea-axum.shuttleapp.rs/tea', requestOptions)
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(result => console.log(result))
|
||||||
|
.catch(error => console.log('error', error));
|
||||||
|
});
|
||||||
|
</script>
|
3
build.rs
Normal file
3
build.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
fn main() {
|
||||||
|
println!("cargo:rerun-if-changed=migrations");
|
||||||
|
}
|
4
migrations/0001_init.sql
Normal file
4
migrations/0001_init.sql
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
CREATE TABLE IF NOT EXISTS teas (
|
||||||
|
id serial PRIMARY KEY,
|
||||||
|
teaname TEXT NOT NULL
|
||||||
|
);
|
1
shuttle.toml
Normal file
1
shuttle.toml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
assets = ["assets/*"]
|
90
src/main.rs
Normal file
90
src/main.rs
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
// Invoke-WebRequest -Uri https://ias-tea-axum.shuttleapp.rs/todos -Method POST -Body '{"note":"Earl Grey Premium"}' -ContentType 'application/json'
|
||||||
|
// cargo shuttle resource delete <type>
|
||||||
|
// cargo shuttle resource list
|
||||||
|
use axum::{
|
||||||
|
extract::{Path, State},
|
||||||
|
http::StatusCode,
|
||||||
|
response::IntoResponse,
|
||||||
|
routing::{get, post},
|
||||||
|
Json, Router,
|
||||||
|
};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use sqlx::{FromRow, PgPool};
|
||||||
|
use tower_http::services::ServeFile;
|
||||||
|
|
||||||
|
async fn retrieve(
|
||||||
|
Path(id): Path<i32>,
|
||||||
|
State(state): State<MyState>,
|
||||||
|
) -> Result<impl IntoResponse, impl IntoResponse> {
|
||||||
|
println!("retrieve");
|
||||||
|
match sqlx::query_as::<_, Tea>("SELECT * FROM teas WHERE id = $1")
|
||||||
|
.bind(id)
|
||||||
|
.fetch_one(&state.pool)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(tea) => Ok((StatusCode::OK, Json(tea))),
|
||||||
|
Err(e) => Err((StatusCode::BAD_REQUEST, e.to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn retrieve_all(
|
||||||
|
State(state): State<MyState>,
|
||||||
|
) -> Result<impl IntoResponse, impl IntoResponse> {
|
||||||
|
println!("retrieve all");
|
||||||
|
match sqlx::query_as::<_, Tea>("SELECT * FROM teas LIMIT 100")
|
||||||
|
.fetch_all(&state.pool)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(all_tea) => Ok((StatusCode::OK, Json(all_tea))),
|
||||||
|
Err(e) => Err((StatusCode::BAD_REQUEST, e.to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn add(
|
||||||
|
State(state): State<MyState>,
|
||||||
|
Json(data): Json<TeaNew>,
|
||||||
|
) -> Result<impl IntoResponse, impl IntoResponse> {
|
||||||
|
println!("add");
|
||||||
|
match sqlx::query_as::<_, Tea>("INSERT INTO teas (teaname) VALUES ($1) RETURNING id, teaname")
|
||||||
|
.bind(&data.teaname)
|
||||||
|
.fetch_one(&state.pool)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(tea) => Ok((StatusCode::CREATED, Json(tea))),
|
||||||
|
Err(e) => Err((StatusCode::BAD_REQUEST, e.to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct MyState {
|
||||||
|
pool: PgPool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[shuttle_runtime::main]
|
||||||
|
async fn main(#[shuttle_shared_db::Postgres] pool: PgPool) -> shuttle_axum::ShuttleAxum {
|
||||||
|
sqlx::migrate!()
|
||||||
|
.run(&pool)
|
||||||
|
.await
|
||||||
|
.expect("Failed to run migrations");
|
||||||
|
|
||||||
|
let state = MyState { pool };
|
||||||
|
let router = Router::new()
|
||||||
|
.nest_service("/", ServeFile::new("assets/index.html"))
|
||||||
|
.route("/tea", post(add))
|
||||||
|
.route("/tea/:id", get(retrieve))
|
||||||
|
.route("/alltea", get(retrieve_all))
|
||||||
|
.with_state(state);
|
||||||
|
|
||||||
|
Ok(router.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct TeaNew {
|
||||||
|
pub teaname: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, FromRow)]
|
||||||
|
struct Tea {
|
||||||
|
pub id: i32,
|
||||||
|
pub teaname: String,
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue