feat: building
This commit is contained in:
@@ -6,13 +6,13 @@ pub struct CommandImpl;
|
||||
|
||||
impl Command for CommandImpl {
|
||||
fn name(&self) -> &str { "cli" }
|
||||
|
||||
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name()).about("Local mini KMS cli")
|
||||
.arg(Arg::with_name("connect").long("connect").takes_value(true).default_value("127.0.0.1:6567").help("Connect server"))
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
fn run(&self, _arg_matches: &ArgMatches, _sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
simple_error!("Not implemented")
|
||||
}
|
||||
}
|
||||
27
src/db.rs
Normal file
27
src/db.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
use rusqlite::{Connection, params};
|
||||
use rust_util::{debugging, information, opt_result, success, XResult};
|
||||
|
||||
pub fn open_db(db: &str) -> XResult<Connection> {
|
||||
let con = opt_result!(Connection::open(db), "Open sqlite db: {}, failed: {}", db);
|
||||
debugging!("Db auto commit: {}", con.is_autocommit());
|
||||
Ok(con)
|
||||
}
|
||||
|
||||
pub fn init_db(conn: &Connection) -> XResult<bool> {
|
||||
let mut stmt = conn.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='keys'")?;
|
||||
let mut rows = stmt.query(())?;
|
||||
if rows.next()?.is_some() {
|
||||
information!("Table keys exists, skip init");
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
let _ = conn.execute(r##"
|
||||
CREATE TABLE keys (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
value TEXT
|
||||
)
|
||||
"##, ())?;
|
||||
success!("Table keys created");
|
||||
Ok(true)
|
||||
}
|
||||
@@ -2,6 +2,7 @@ use clap::{App, AppSettings, ArgMatches};
|
||||
use rust_util::{failure_and_exit, information};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
|
||||
mod db;
|
||||
mod cli;
|
||||
mod serve;
|
||||
|
||||
|
||||
78
src/serve.rs
78
src/serve.rs
@@ -1,6 +1,16 @@
|
||||
use std::sync::RwLock;
|
||||
use clap::{App, Arg, ArgMatches, SubCommand};
|
||||
use rust_util::simple_error;
|
||||
use hyper::{Body, Client, Method, Request, Response, Server, StatusCode};
|
||||
use hyper::client::HttpConnector;
|
||||
use hyper::service::{make_service_fn, service_fn};
|
||||
use rust_util::{failure_and_exit, iff, information, success};
|
||||
use rust_util::util_clap::{Command, CommandError};
|
||||
use crate::db;
|
||||
|
||||
type GenericError = Box<dyn std::error::Error + Send + Sync>;
|
||||
type Result<T> = std::result::Result<T, GenericError>;
|
||||
|
||||
static NOTFOUND: &[u8] = b"Not Found\n";
|
||||
|
||||
pub struct CommandImpl;
|
||||
|
||||
@@ -9,10 +19,70 @@ impl Command for CommandImpl {
|
||||
|
||||
fn subcommand<'a>(&self) -> App<'a, 'a> {
|
||||
SubCommand::with_name(self.name()).about("Local mini KMS serve")
|
||||
.arg(Arg::with_name("listen").long("listen").takes_value(true).default_value("127.0.0.1:6567").help("Listen"))
|
||||
.arg(Arg::with_name("listen").long("listen").takes_value(true).default_value("127.0.0.1:5567").help("Listen"))
|
||||
}
|
||||
|
||||
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
|
||||
simple_error!("Not implemented")
|
||||
let listen = sub_arg_matches.value_of("listen").expect("Get argument listen error");
|
||||
let rt = tokio::runtime::Runtime::new().expect("Create tokio runtime error");
|
||||
rt.block_on(async {
|
||||
let addr = listen.parse().expect(&format!("Parse listen error: {}", listen));
|
||||
let client = Client::new();
|
||||
let new_service = make_service_fn(move |_| {
|
||||
let client = client.clone();
|
||||
async {
|
||||
Ok::<_, GenericError>(service_fn(move |req| {
|
||||
response_requests(req, client.to_owned())
|
||||
}))
|
||||
}
|
||||
});
|
||||
let server = Server::bind(&addr).serve(new_service);
|
||||
information!("Listening on http://{}", addr);
|
||||
match server.await {
|
||||
Err(e) => failure_and_exit!("Server error: {}", e),
|
||||
Ok(_) => success!("Server ended"),
|
||||
}
|
||||
});
|
||||
Ok(Some(0))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ref: https://github.com/hyperium/hyper/blob/master/examples/web_api.rs
|
||||
async fn response_requests(
|
||||
req: Request<Body>,
|
||||
_client: Client<HttpConnector>,
|
||||
) -> Result<Response<Body>> {
|
||||
match (req.method(), req.uri().path()) {
|
||||
// (&Method::GET, "/") | (&Method::GET, "/index.html") => Ok(Response::new(INDEX.into())),
|
||||
// (&Method::GET, "/test.html") => client_request_response(&client).await,
|
||||
(&Method::GET, "/status") => status().await,
|
||||
(&Method::GET, "/version") => get_version().await,
|
||||
_ => {
|
||||
Ok(Response::builder()
|
||||
.status(StatusCode::NOT_FOUND).body(NOTFOUND.into())
|
||||
.expect("Response not found error"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------------------------------
|
||||
|
||||
struct MemoryKey {
|
||||
master_key: Vec<u8>,
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref STATUS_RW_LOCK: RwLock<bool> = RwLock::new(false);
|
||||
}
|
||||
|
||||
async fn status() -> Result<Response<Body>> {
|
||||
let status_rw_lock = STATUS_RW_LOCK.read().expect("Lock read status rw lock error");
|
||||
let status_rw_lock_value = *status_rw_lock;
|
||||
Ok(Response::builder().body(format!("{}\n", iff!(status_rw_lock_value, "init", "uninit")).into()).expect("x"))
|
||||
}
|
||||
|
||||
async fn get_version() -> Result<Response<Body>> {
|
||||
Ok(Response::builder().body(format!(
|
||||
"{} - {}\n", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")
|
||||
).into()).expect("Response get_version error"))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user