Compare commits

...

2 commits

Author SHA1 Message Date
Timo Ley 92799df15e feat: initial base implementation 2023-06-21 10:09:28 +02:00
Timo Ley b3e1badef2 chore: remove Cargo.lock 2023-06-21 10:08:12 +02:00
9 changed files with 216 additions and 331 deletions

3
.gitignore vendored
View file

@ -1 +1,4 @@
/target
config.toml
test.sql
Cargo.lock

326
Cargo.lock generated
View file

@ -1,326 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "MS3"
version = "0.1.0"
dependencies = [
"sibyl",
"tokio",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bytes"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "hermit-abi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]]
name = "libc"
version = "0.2.146"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
[[package]]
name = "lock_api"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "mio"
version = "0.8.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
dependencies = [
"libc",
"wasi",
"windows-sys",
]
[[package]]
name = "num_cpus"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "once_cell"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "parking_lot"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets",
]
[[package]]
name = "pin-project-lite"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
[[package]]
name = "proc-macro2"
version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
dependencies = [
"bitflags",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "sibyl"
version = "0.6.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7052c5a26b0268924449767392a7b0e267dc7936f871744e76fafe92ae2490a0"
dependencies = [
"libc",
"once_cell",
"parking_lot",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
dependencies = [
"libc",
]
[[package]]
name = "smallvec"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
name = "socket2"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "syn"
version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "tokio"
version = "1.28.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2"
dependencies = [
"autocfg",
"bytes",
"libc",
"mio",
"num_cpus",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys",
]
[[package]]
name = "tokio-macros"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
[[package]]
name = "windows_i686_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
[[package]]
name = "windows_i686_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"

View file

@ -1,5 +1,5 @@
[package]
name = "MS3"
name = "ms3"
version = "0.1.0"
edition = "2021"
@ -7,4 +7,13 @@ edition = "2021"
[dependencies]
tokio = { version = "1.0", features = ["full"] }
sibyl = "0.6.16"
sibyl = { version = "0.6", features = ["nonblocking", "tokio"] }
axum = { version = "0.2.8", features = ["headers", "multipart"] }
hyper = "0.14.16"
tower = { version = "0.4", features = ["util", "timeout"] }
tower-http = { version = "0.1", features = ["add-extension", "trace", "fs", "set-header"] }
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.51"
structopt = "0.3.22"
toml = "0.5.8"
thiserror = "1.0.30"

11
src/config.rs Normal file
View file

@ -0,0 +1,11 @@
use std::net::SocketAddr;
use serde::Deserialize;
#[derive(Deserialize)]
pub struct Config {
pub addr: SocketAddr,
pub db_name: String,
pub db_username: String,
pub db_password: String,
}

65
src/error.rs Normal file
View file

@ -0,0 +1,65 @@
use std::convert::Infallible;
use axum::{response::IntoResponse, body::{Full, Bytes}, Json};
use hyper::StatusCode;
use serde::{Serializer, Serialize};
use thiserror::Error;
#[derive(Error, Debug)]
pub enum ApplicationError {
#[error("File read error: {0}")]
Read(#[from] std::io::Error),
#[error("Deserialize error: {0}")]
Deserialize(#[from] toml::de::Error),
#[error("Database connection error: {0}")]
Database(#[from] sibyl::Error),
#[error("Axum error: {0}")]
Axum(#[from] hyper::Error),
}
#[derive(Error, Debug)]
pub enum ServiceError {
#[error("SQL error: {0}")]
Database(#[from] sibyl::Error),
#[error("Response code: {0}")]
ErrorResponse(StatusCode, Option<String>),
}
fn serialize_status<S>(x: &StatusCode, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
s.serialize_u16(x.as_u16())
}
#[derive(Serialize)]
pub struct ErrorResponse {
#[serde(serialize_with = "serialize_status")]
pub status: StatusCode,
pub error: String,
}
impl IntoResponse for ServiceError {
type Body = Full<Bytes>;
type BodyError = Infallible;
fn into_response(self) -> axum::http::Response<Self::Body> {
let res = match self {
ServiceError::Database(err) => ErrorResponse::new(StatusCode::INTERNAL_SERVER_ERROR, Some(err.to_string())),
ServiceError::ErrorResponse(code, reason) => ErrorResponse::new(code, reason),
};
let status = res.status;
(status, Json(res)).into_response()
}
}
impl ErrorResponse {
fn new(status: StatusCode, message: Option<String>) -> Self {
let reason = status.canonical_reason().unwrap_or_default();
Self {
status,
error: message.unwrap_or_else(|| reason.to_string()),
}
}
}

View file

@ -1,5 +1,61 @@
#[tokio::main]
use std::{path::PathBuf, sync::Arc};
async fn main() {
println!("Hello, world!");
use axum::{Router, AddExtensionLayer, http::{HeaderValue, header}};
use error::ApplicationError;
use hyper::{Request, Body};
use sibyl::{Environment, SessionPool};
use structopt::{StructOpt, lazy_static::lazy_static};
use config::Config;
use tower_http::set_header::SetResponseHeaderLayer;
mod config;
mod error;
mod routes;
mod sql;
mod model;
#[derive(StructOpt)]
struct Opt {
#[structopt(
short,
long,
help = "config file to use",
default_value = "./config.toml"
)]
config: PathBuf,
}
pub struct ServiceInner {
pool: SessionPool<'static>
}
pub type Service = Arc<ServiceInner>;
lazy_static!{
pub static ref ORACLE: Environment = sibyl::env().expect("Sibyl error");
}
#[tokio::main]
async fn main() -> Result<(), ApplicationError> {
let opt = Opt::from_args();
let config = std::fs::read(&opt.config)?;
let config = toml::from_slice::<Config>(&config)?;
let pool = ORACLE.create_session_pool(&config.db_name, &config.db_username, &config.db_password, 0, 1, 10).await?;
let service: Service = Arc::new(ServiceInner{ pool });
let app = Router::new()
.nest("/api", routes::routes())
.layer(AddExtensionLayer::new(service))
.layer(SetResponseHeaderLayer::<_, Request<Body>>::if_not_present(
header::ACCESS_CONTROL_ALLOW_ORIGIN,
HeaderValue::from_static("*"),
));
axum::Server::bind(&config.addr)
.serve(app.into_make_service())
.await?;
Ok(())
}

11
src/model.rs Normal file
View file

@ -0,0 +1,11 @@
use serde::Serialize;
#[derive(Serialize)]
pub struct Room {
pub room_number: i32,
pub floor: i32,
pub size: i32,
pub room_type: String,
pub beds: i32,
pub accessibility: bool,
}

17
src/routes.rs Normal file
View file

@ -0,0 +1,17 @@
use axum::{Router, routing::BoxRoute, extract::Extension, response::IntoResponse, Json, handler::get};
use crate::{Service, error::ServiceError};
async fn rooms(
Extension(service): Extension<Service>,
) -> Result<impl IntoResponse, ServiceError> {
let rooms = service.get_rooms().await?;
Ok(Json(rooms))
}
pub fn routes() -> Router<BoxRoute> {
Router::new()
.route("/rooms", get(rooms))
.boxed()
}

39
src/sql.rs Normal file
View file

@ -0,0 +1,39 @@
use crate::{ServiceInner, model::Room, error::ServiceError};
impl ServiceInner {
pub async fn get_rooms(&self) -> Result<Vec<Room>, ServiceError> {
let session = self.pool.get_session().await?;
let stmt = session.prepare("
SELECT
roomNumber,
floor,
roomTyp,
\"size\",
accessibility,
beds
FROM room
").await?;
let rows = stmt.query("").await?;
let mut rooms: Vec<Room> = vec![];
while let Some(row) = rows.next().await? {
let acc: i32 = row.get(5)?;
let room = Room {
room_number: row.get(0)?,
floor: row.get(1)?,
size: row.get(3)?,
room_type: row.get(2)?,
beds: row.get(4)?,
accessibility: acc != 0,
};
rooms.push(room);
}
Ok(rooms)
}
}