1
0
mirror of https://github.com/actix/examples synced 2025-02-02 17:39:05 +01:00

160 lines
4.1 KiB
Rust
Raw Normal View History

2020-04-03 16:14:30 +09:00
// Allow this lint since it's fine to use type directly in the short example.
#![allow(clippy::type_complexity)]
use std::{
error,
future::Future,
pin::Pin,
sync::{Arc, RwLock},
time::Duration,
};
2019-04-15 10:05:22 +08:00
use actix_web::{middleware, web, App, Error, HttpResponse, HttpServer};
2019-12-07 23:59:24 +06:00
use bytes::Bytes;
use futures_util::FutureExt as _;
2019-04-15 10:05:22 +08:00
use serde_json::Value;
#[allow(dead_code)]
mod convention;
/// The main handler for JSONRPC server.
2022-02-18 02:44:02 +00:00
async fn rpc_handler(body: Bytes, app_state: web::Data<AppState>) -> Result<HttpResponse, Error> {
2019-12-07 23:59:24 +06:00
let reqjson: convention::Request = match serde_json::from_slice(body.as_ref()) {
Ok(ok) => ok,
Err(_) => {
let r = convention::Response {
jsonrpc: String::from(convention::JSONRPC_VERSION),
result: Value::Null,
error: Some(convention::ErrorData::std(-32700)),
id: Value::Null,
};
return Ok(HttpResponse::Ok()
.content_type("application/json")
.body(r.dump()));
2019-04-15 10:05:22 +08:00
}
2019-12-07 23:59:24 +06:00
};
2021-10-07 03:04:59 +01:00
let mut result = convention::Response {
id: reqjson.id.clone(),
..convention::Response::default()
};
2019-12-07 23:59:24 +06:00
match rpc_select(&app_state, reqjson.method.as_str(), reqjson.params).await {
Ok(ok) => result.result = ok,
Err(e) => result.error = Some(e),
}
2019-04-15 10:05:22 +08:00
2019-12-07 23:59:24 +06:00
Ok(HttpResponse::Ok()
.content_type("application/json")
.body(result.dump()))
2019-04-15 10:05:22 +08:00
}
2019-12-07 23:59:24 +06:00
async fn rpc_select(
2019-04-15 10:27:25 +08:00
app_state: &AppState,
method: &str,
params: Vec<Value>,
) -> Result<Value, convention::ErrorData> {
2019-04-15 10:05:22 +08:00
match method {
"ping" => {
let r = app_state.network.read().unwrap().ping();
Ok(Value::from(r))
}
2019-04-15 10:27:25 +08:00
"wait" => {
if params.len() != 1 || !params[0].is_u64() {
return Err(convention::ErrorData::std(-32602));
}
2022-07-09 21:05:06 +01:00
let fut = app_state
2019-04-15 10:27:25 +08:00
.network
.read()
.unwrap()
2022-07-09 21:05:06 +01:00
.wait(params[0].as_u64().unwrap());
match fut.await {
2019-04-15 10:27:25 +08:00
Ok(ok) => Ok(Value::from(ok)),
Err(e) => Err(convention::ErrorData::new(500, &format!("{e:?}")[..])),
2019-04-15 10:27:25 +08:00
}
}
2019-04-15 10:05:22 +08:00
"get" => {
let r = app_state.network.read().unwrap().get();
Ok(Value::from(r))
}
"inc" => {
app_state.network.write().unwrap().inc();
Ok(Value::Null)
}
_ => Err(convention::ErrorData::std(-32601)),
}
}
pub trait ImplNetwork {
fn ping(&self) -> String;
2022-02-18 02:44:02 +00:00
fn wait(&self, d: u64) -> Pin<Box<dyn Future<Output = Result<String, Box<dyn error::Error>>>>>;
2019-04-15 10:05:22 +08:00
fn get(&self) -> u32;
fn inc(&mut self);
}
pub struct ObjNetwork {
c: u32,
}
impl ObjNetwork {
fn new() -> Self {
Self { c: 0 }
}
}
impl ImplNetwork for ObjNetwork {
fn ping(&self) -> String {
String::from("pong")
}
2022-02-18 02:44:02 +00:00
fn wait(&self, d: u64) -> Pin<Box<dyn Future<Output = Result<String, Box<dyn error::Error>>>>> {
2019-12-07 23:59:24 +06:00
async move {
2022-02-02 15:16:19 +00:00
actix_web::rt::time::sleep(Duration::from_secs(d)).await;
2019-12-07 23:59:24 +06:00
Ok(String::from("pong"))
}
2019-12-25 20:48:33 +04:00
.boxed_local()
2019-04-15 10:05:22 +08:00
}
fn get(&self) -> u32 {
self.c
}
fn inc(&mut self) {
self.c += 1;
}
}
#[derive(Clone)]
pub struct AppState {
2019-09-05 00:04:57 +09:00
network: Arc<RwLock<dyn ImplNetwork>>,
2019-04-15 10:05:22 +08:00
}
impl AppState {
2019-09-05 00:04:57 +09:00
pub fn new(network: Arc<RwLock<dyn ImplNetwork>>) -> Self {
2019-04-15 10:05:22 +08:00
Self { network }
}
}
2020-09-12 16:49:45 +01:00
#[actix_web::main]
2019-12-07 23:59:24 +06:00
async fn main() -> std::io::Result<()> {
2023-03-14 03:11:49 +00:00
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
2019-04-15 10:05:22 +08:00
let network = Arc::new(RwLock::new(ObjNetwork::new()));
2023-03-14 03:11:49 +00:00
log::info!("starting HTTP server at http://localhost:8080");
2019-04-15 10:05:22 +08:00
HttpServer::new(move || {
let app_state = AppState::new(network.clone());
App::new()
2022-02-02 15:16:19 +00:00
.app_data(web::Data::new(app_state))
2019-04-15 10:05:22 +08:00
.wrap(middleware::Logger::default())
2019-12-07 23:59:24 +06:00
.service(web::resource("/").route(web::post().to(rpc_handler)))
2019-04-15 10:05:22 +08:00
})
2022-02-17 20:22:36 +00:00
.bind(("127.0.0.1", 8080))
2019-04-15 10:05:22 +08:00
.unwrap()
2019-12-25 20:48:33 +04:00
.run()
2019-12-07 23:59:24 +06:00
.await
2019-04-15 10:05:22 +08:00
}