working json rpc module

This commit is contained in:
narodnik
2020-12-27 18:01:07 +01:00
parent 6df824ffb6
commit 5ddcdbc69e
3 changed files with 113 additions and 0 deletions

View File

@@ -46,6 +46,11 @@ async-dup = "1.1.0"
async-std = "1.6.2"
easy-parallel = "3.1.0"
jsonrpc-core = "16.0.0"
http-types = "2.9.0"
async-h1 = "2.3.0"
async-native-tls = "0.3.3"
[[bin]]
name = "zkvm"
path = "src/bin/zkvm.rs"

23
scripts/client.py Normal file
View File

@@ -0,0 +1,23 @@
import requests
import json
def main():
url = "http://localhost:8000/"
# Example echo method
payload = {
"method": "say_hello",
"params": ["echome!"],
"jsonrpc": "2.0",
"id": 0,
}
response = requests.post(url, json=payload).json()
print(response)
assert response["result"] == "Hello World!"
assert response["jsonrpc"]
if __name__ == "__main__":
main()

View File

@@ -11,7 +11,91 @@ use std::sync::Arc;
use sapvi::{ClientProtocol, Result, SeedProtocol, ServerProtocol};
use std::net::TcpListener;
use async_native_tls::{Identity, TlsAcceptor};
use http_types::{Request, Response, StatusCode, Body, Method};
use smol::{future, Async};
/// Serves a request and returns a response.
async fn serve(mut req: Request) -> http_types::Result<Response> {
println!("Serving {}", req.url());
let request = req.body_string().await?;
let mut io = jsonrpc_core::IoHandler::new();
io.add_sync_method("say_hello", |_| {
Ok(jsonrpc_core::Value::String("Hello World!".into()))
});
//let request = r#"{"jsonrpc": "2.0", "method": "say_hello", "params": [42, 23], "id": 1}"#;
//let response = r#"{"jsonrpc":"2.0","result":"Hello World!","id":1}"#;
//assert_eq!(io.handle_request_sync(request), Some(response.to_string()));
let response = io.handle_request_sync(&request).ok_or(sapvi::Error::BadOperationType)?;
let mut res = Response::new(StatusCode::Ok);
res.insert_header("Content-Type", "text/plain");
res.set_body(response);
Ok(res)
}
/// Listens for incoming connections and serves them.
async fn listen(executor: Arc<Executor<'_>>, listener: Async<TcpListener>, tls: Option<TlsAcceptor>) -> Result<()> {
// Format the full host address.
let host = match &tls {
None => format!("http://{}", listener.get_ref().local_addr()?),
Some(_) => format!("https://{}", listener.get_ref().local_addr()?),
};
println!("Listening on {}", host);
loop {
// Accept the next connection.
let (stream, _) = listener.accept().await?;
// Spawn a background task serving this connection.
let task = match &tls {
None => {
let stream = async_dup::Arc::new(stream);
executor.spawn(async move {
if let Err(err) = async_h1::accept(stream, serve).await {
println!("Connection error: {:#?}", err);
}
})
}
Some(tls) => {
// In case of HTTPS, establish a secure TLS connection first.
match tls.accept(stream).await {
Ok(stream) => {
let stream = async_dup::Arc::new(async_dup::Mutex::new(stream));
executor.spawn(async move {
if let Err(err) = async_h1::accept(stream, serve).await {
println!("Connection error: {:#?}", err);
}
})
}
Err(err) => {
println!("Failed to establish secure TLS connection: {:#?}", err);
continue;
}
}
}
};
// Detach the task to let it run in the background.
task.detach();
}
}
async fn start(executor: Arc<Executor<'_>>, options: ProgramOptions) -> Result<()> {
let http = listen(executor.clone(), Async::<TcpListener>::bind(([127, 0, 0, 1], 8000))?, None);
http.await;
return Ok(());
/*
let connections = Arc::new(Mutex::new(HashMap::new()));
let stored_addrs = Arc::new(Mutex::new(Vec::new()));
@@ -83,6 +167,7 @@ async fn start(executor: Arc<Executor<'_>>, options: ProgramOptions) -> Result<(
//server_task.cancel().await;
//Ok(())
*/
}
struct ProgramOptions {