Web API, Web UI #86
File diff suppressed because it is too large
Load Diff
|
@ -4,15 +4,19 @@ version = "0.1.0"
|
|||
authors = ["projectmoon <projectmoon@agnos.is>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
tonic = { git = "https://github.com/hyperium/tonic", branch = "master" }
|
||||
tonic-web = { git = "https://github.com/hyperium/tonic", branch = "master" }
|
||||
log = "0.4"
|
||||
tracing-subscriber = "0.2"
|
||||
tonic = { version = "0.4" }
|
||||
prost = "0.7"
|
||||
once_cell = "1.7"
|
||||
tenebrous-rpc = { path = "../rpc" }
|
||||
tokio-stream = { version = "0.1", features = ["net"] }
|
||||
juniper = { git = "https://github.com/graphql-rust/juniper", branch = "master" }
|
||||
juniper_rocket_async = { git = "https://github.com/graphql-rust/juniper", branch = "master" }
|
||||
rocket = { git = "https://github.com/SergioBenitez/Rocket", branch = "master" }
|
||||
warp = "0.2"
|
||||
#tokio-stream = { version = "0.1", features = ["net"] } # needed for grpc-web?
|
||||
|
||||
[dependencies.tokio]
|
||||
version = "1"
|
||||
features = [ "full" ]
|
||||
# [dependencies.tokio]
|
||||
# version = "1"
|
||||
# features = [ "full" ]
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
// use std::net::SocketAddr;
|
||||
// use tenebrous_rpc::protos::web_api::{
|
||||
// web_api_server::{WebApi, WebApiServer},
|
||||
// RoomsListReply, UserIdRequest,
|
||||
// };
|
||||
// use tokio::net::TcpListener;
|
||||
// use tokio_stream::wrappers::TcpListenerStream;
|
||||
// use tonic::{transport::Server, Request, Response, Status};
|
||||
|
||||
//grpc-web stuff
|
||||
// struct WebApiService;
|
||||
|
||||
// #[tonic::async_trait]
|
||||
// impl WebApi for WebApiService {
|
||||
// async fn list_room(
|
||||
// &self,
|
||||
// request: Request<UserIdRequest>,
|
||||
// ) -> Result<Response<RoomsListReply>, Status> {
|
||||
// println!("Hello hopefully from a web browser");
|
||||
// Ok(Response::new(RoomsListReply { rooms: vec![] }))
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[tokio::main]
|
||||
// pub async fn grpc_web() -> Result<(), Box<dyn std::error::Error>> {
|
||||
// let addr = SocketAddr::from(([127, 0, 0, 1], 10000));
|
||||
// let listener = TcpListener::bind(addr).await.expect("listener");
|
||||
// let url = format!("http://{}", listener.local_addr().unwrap());
|
||||
// println!("Listening at {}", url);
|
||||
|
||||
// let svc = tonic_web::config()
|
||||
// .allow_origins(vec!["http://localhost:8000"])
|
||||
// .enable(WebApiServer::new(WebApiService));
|
||||
|
||||
// let fut = Server::builder()
|
||||
// .accept_http1(true)
|
||||
// .add_service(svc)
|
||||
// .serve_with_incoming(TcpListenerStream::new(listener));
|
||||
|
||||
// fut.await?;
|
||||
// Ok(())
|
||||
// }
|
172
api/src/main.rs
172
api/src/main.rs
|
@ -1,41 +1,155 @@
|
|||
use std::net::SocketAddr;
|
||||
use tenebrous_rpc::protos::web_api::{
|
||||
web_api_server::{WebApi, WebApiServer},
|
||||
RoomsListReply, UserIdRequest,
|
||||
use juniper::{
|
||||
graphql_object, EmptyMutation, EmptySubscription, FieldError, FieldResult, GraphQLObject,
|
||||
RootNode,
|
||||
};
|
||||
use tokio::net::TcpListener;
|
||||
use tokio_stream::wrappers::TcpListenerStream;
|
||||
use tonic::{transport::Server, Request, Response, Status};
|
||||
use once_cell::sync::OnceCell;
|
||||
use rocket::{response::content, Rocket, State};
|
||||
use std::cell::RefCell;
|
||||
use std::env;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use tenebrous_rpc::protos::dicebot::dicebot_client::DicebotClient;
|
||||
use tenebrous_rpc::protos::dicebot::GetVariableRequest;
|
||||
use tonic::{metadata::MetadataValue, transport::Channel as TonicChannel, Request as TonicRequest};
|
||||
use tracing_subscriber::filter::EnvFilter;
|
||||
|
||||
struct WebApiService;
|
||||
//grpc stuff
|
||||
async fn create_client(
|
||||
shared_secret: &str,
|
||||
) -> Result<DicebotClient<TonicChannel>, Box<dyn std::error::Error>> {
|
||||
let channel = TonicChannel::from_static("http://0.0.0.0:9090")
|
||||
.connect()
|
||||
.await?;
|
||||
|
||||
#[tonic::async_trait]
|
||||
impl WebApi for WebApiService {
|
||||
async fn list_room(
|
||||
&self,
|
||||
request: Request<UserIdRequest>,
|
||||
) -> Result<Response<RoomsListReply>, Status> {
|
||||
println!("Hello hopefully from a web browser");
|
||||
Ok(Response::new(RoomsListReply { rooms: vec![] }))
|
||||
let bearer = MetadataValue::from_str(&format!("Bearer {}", shared_secret))?;
|
||||
let client = DicebotClient::with_interceptor(channel, move |mut req: TonicRequest<()>| {
|
||||
req.metadata_mut().insert("authorization", bearer.clone());
|
||||
Ok(req)
|
||||
});
|
||||
|
||||
Ok(client)
|
||||
}
|
||||
|
||||
//api stuff
|
||||
#[derive(GraphQLObject)]
|
||||
#[graphql(description = "User variable in a room.")]
|
||||
struct UserVariable {
|
||||
room_id: String,
|
||||
variable_name: String,
|
||||
value: i32,
|
||||
}
|
||||
|
||||
//graphql shit
|
||||
#[derive(Clone)]
|
||||
struct Context {
|
||||
dicebot_client: DicebotClient<TonicChannel>,
|
||||
}
|
||||
|
||||
// To make our context usable by Juniper, we have to implement a marker trait.
|
||||
impl juniper::Context for Context {}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
struct Query;
|
||||
|
||||
#[graphql_object(
|
||||
// Here we specify the context type for the object.
|
||||
// We need to do this in every type that
|
||||
// needs access to the context.
|
||||
context = Context,
|
||||
)]
|
||||
impl Query {
|
||||
fn apiVersion() -> &str {
|
||||
"1.0"
|
||||
}
|
||||
|
||||
async fn variable(
|
||||
context: &mut Context,
|
||||
room_id: String,
|
||||
user_id: String,
|
||||
variable: String,
|
||||
) -> FieldResult<UserVariable> {
|
||||
let request = TonicRequest::new(GetVariableRequest {
|
||||
room_id: room_id.clone(),
|
||||
user_id: user_id.clone(),
|
||||
variable_name: variable.clone(),
|
||||
});
|
||||
|
||||
let response = context
|
||||
.dicebot_client
|
||||
.clone()
|
||||
.get_variable(request)
|
||||
.await?
|
||||
.into_inner();
|
||||
|
||||
Ok(UserVariable {
|
||||
room_id: room_id.clone(),
|
||||
variable_name: variable.clone(),
|
||||
value: response.value,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
type Schema = RootNode<'static, Query, EmptyMutation<Context>, EmptySubscription<Context>>;
|
||||
|
||||
fn schema() -> Schema {
|
||||
Schema::new(
|
||||
Query,
|
||||
EmptyMutation::<Context>::new(),
|
||||
EmptySubscription::<Context>::new(),
|
||||
)
|
||||
}
|
||||
|
||||
//rocket stuff
|
||||
|
||||
#[rocket::get("/")]
|
||||
fn graphiql() -> content::Html<String> {
|
||||
juniper_rocket_async::graphiql_source("/graphql", None)
|
||||
}
|
||||
|
||||
#[rocket::get("/graphql?<request>")]
|
||||
fn get_graphql_handler(
|
||||
context: &State<Context>,
|
||||
request: juniper_rocket_async::GraphQLRequest,
|
||||
schema: &State<Schema>,
|
||||
) -> juniper_rocket_async::GraphQLResponse {
|
||||
request.execute_sync(&*schema, &*context)
|
||||
}
|
||||
|
||||
#[rocket::post("/graphql", data = "<request>")]
|
||||
fn post_graphql_handler(
|
||||
context: &State<Context>,
|
||||
request: juniper_rocket_async::GraphQLRequest,
|
||||
schema: &State<Schema>,
|
||||
) -> juniper_rocket_async::GraphQLResponse {
|
||||
request.execute_sync(&*schema, &*context)
|
||||
}
|
||||
|
||||
#[rocket::main]
|
||||
pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let addr = SocketAddr::from(([127, 0, 0, 1], 10000));
|
||||
let listener = TcpListener::bind(addr).await.expect("listener");
|
||||
let url = format!("http://{}", listener.local_addr().unwrap());
|
||||
println!("Listening at {}", url);
|
||||
let filter = if env::var("RUST_LOG").is_ok() {
|
||||
EnvFilter::from_default_env()
|
||||
} else {
|
||||
EnvFilter::new("warp_async")
|
||||
};
|
||||
|
||||
let svc = tonic_web::config()
|
||||
.allow_origins(vec!["http://localhost:8000"])
|
||||
.enable(WebApiServer::new(WebApiService));
|
||||
tracing_subscriber::fmt().with_env_filter(filter).init();
|
||||
|
||||
let fut = Server::builder()
|
||||
.accept_http1(true)
|
||||
.add_service(svc)
|
||||
.serve_with_incoming(TcpListenerStream::new(listener));
|
||||
let log = warp::log("warp_server");
|
||||
let client = create_client("abc123").await?;
|
||||
|
||||
fut.await?;
|
||||
log::info!("Listening on 127.0.0.1:8080");
|
||||
let context = Context {
|
||||
dicebot_client: client,
|
||||
};
|
||||
|
||||
Rocket::build()
|
||||
.manage(client)
|
||||
.manage(schema())
|
||||
.mount(
|
||||
"/",
|
||||
rocket::routes![graphiql, get_graphql_handler, post_graphql_handler],
|
||||
)
|
||||
.launch()
|
||||
.await
|
||||
.expect("server to launch");
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ barrel = { version = "0.6", features = ["sqlite3"] }
|
|||
tempfile = "3"
|
||||
substring = "1.4"
|
||||
fuse-rust = "0.2"
|
||||
tonic = { git = "https://github.com/hyperium/tonic", branch = "master" }
|
||||
tonic = { version = "0.4" }
|
||||
prost = "0.7"
|
||||
tenebrous-rpc = { path = "../rpc" }
|
||||
|
||||
|
|
|
@ -10,12 +10,10 @@ async fn create_client(
|
|||
.await?;
|
||||
|
||||
let bearer = MetadataValue::from_str(&format!("Bearer {}", shared_secret))?;
|
||||
let client = DicebotClient::new(channel);
|
||||
|
||||
// let client = DicebotClient::with_interceptor(channel, move |mut req: Request<()>| {
|
||||
// req.metadata_mut().insert("authorization", bearer.clone());
|
||||
// Ok(req)
|
||||
// });
|
||||
let client = DicebotClient::with_interceptor(channel, move |mut req: Request<()>| {
|
||||
req.metadata_mut().insert("authorization", bearer.clone());
|
||||
Ok(req)
|
||||
});
|
||||
|
||||
Ok(client)
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@ default = ["tonic/default", "tonic-build/default"]
|
|||
wasm = [ "tonic/codegen", "tonic/prost", "tonic-build/prost"]
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build = { git = "https://github.com/hyperium/tonic", branch = "master", default_features = false }
|
||||
tonic-build = { version = "0.4", default_features = false }
|
||||
|
||||
[dependencies]
|
||||
tonic = { git = "https://github.com/hyperium/tonic", branch = "master", default_features = false }
|
||||
tonic = { version = "0.4", default_features = false }
|
||||
prost = "0.7"
|
|
@ -9,21 +9,18 @@ edition = "2018"
|
|||
[lib]
|
||||
crate-type = ["cdylib", "rlib"]
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
tonic-build = { version = "0.4", default-features = false, features = ["prost"] }
|
||||
|
||||
[dependencies]
|
||||
yew = { version = "0.17", default_features = false }#features = [ "agent", "web-sys" ] }
|
||||
yew = { version = "0.17" }
|
||||
yewtil = {version = "0.3" }
|
||||
yew-router = {version = "0.14", default_features = false }
|
||||
yewdux = {version = "^0.6", default_features = false }
|
||||
wasm-bindgen = { version = "0.2", default-features = false, features = ["serde-serialize"] }
|
||||
yew-router = {version = "0.14" }
|
||||
yewdux = {version = "^0.6" }
|
||||
wasm-bindgen = { version = "0.2" }
|
||||
grpc-web-client = "0.1"
|
||||
prost = { version = "0.7.0", default-features = false }
|
||||
tonic = { git = "https://github.com/hyperium/tonic", branch = "master", default-features = false, features = ["codegen", "prost"] }
|
||||
tenebrous-rpc = { path = "../../rpc", default_features = false, features = ["wasm"] }
|
||||
|
||||
# [dependencies.tokio]
|
||||
# version = "1"
|
||||
# features = [ "rt", "sync" ]
|
||||
# hopefully we can add grpc-web later instead of graphql.
|
||||
# prost = { version = "0.7.0", default-features = false }
|
||||
# tonic = { git = "https://github.com/hyperium/tonic", branch = "master", default-features = false, features = ["codegen", "prost"] }
|
||||
# tenebrous-rpc = { path = "../../rpc", default_features = false, features = ["wasm"] }
|
||||
|
||||
# [build-dependencies]
|
||||
# tonic-build = { version = "0.4", default-features = false, features = ["prost"] }
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
async fn test_grpc_web() {
|
||||
use grpc_web_client::Client as GrpcWebClient;
|
||||
use tenebrous_rpc::protos::web_api::web_api_client::WebApiClient as TheCloud;
|
||||
use tenebrous_rpc::protos::web_api::{RoomsListReply, UserIdRequest};
|
||||
// async fn test_grpc_web() {
|
||||
// use grpc_web_client::Client as GrpcWebClient;
|
||||
// use tenebrous_rpc::protos::web_api::web_api_client::WebApiClient as TheCloud;
|
||||
// use tenebrous_rpc::protos::web_api::{RoomsListReply, UserIdRequest};
|
||||
|
||||
let client = GrpcWebClient::new("http://localhost:10000".to_string());
|
||||
let mut client = TheCloud::new(client);
|
||||
// let client = GrpcWebClient::new("http://localhost:10000".to_string());
|
||||
// let mut client = TheCloud::new(client);
|
||||
|
||||
let request = tonic::Request::new(UserIdRequest {
|
||||
user_id: "WebTonic".into(),
|
||||
});
|
||||
// let request = tonic::Request::new(UserIdRequest {
|
||||
// user_id: "WebTonic".into(),
|
||||
// });
|
||||
|
||||
let response = client.list_room(request).await.unwrap().into_inner();
|
||||
println!("Room reply: {:?}", response);
|
||||
}
|
||||
// let response = client.list_room(request).await.unwrap().into_inner();
|
||||
// println!("Room reply: {:?}", response);
|
||||
// }
|
||||
|
|
Loading…
Reference in New Issue