Skip to content

Commit

Permalink
Add a serving multiplexer to server both web and grpc requests on the…
Browse files Browse the repository at this point in the history
… same port.
  • Loading branch information
dinowernli committed May 4, 2024
1 parent 32b8b4a commit 0d390a4
Show file tree
Hide file tree
Showing 7 changed files with 248 additions and 25 deletions.
119 changes: 119 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ edition = "2021"
[dependencies]
async-std = {version = "1.12", features = ["attributes"]}
async-trait = "0.1.80"
axum = "0.6.12"
bytes = "1.6"
chrono = "0.4"
futures = "0.3"
hyper="0.14.25"
multiplex-tonic-hyper = "0.1"
im = "15"
prost = "0.12"
rand = "0.8"
Expand All @@ -22,6 +25,7 @@ tracing = "0.1.40"
tracing-subscriber = {version = "0.3.1", features = ["env-filter"]}
tower = "0.4.13"
pin-project = "1.1"
url = "2.5"

[build-dependencies]
tonic-build = "0.11"
73 changes: 73 additions & 0 deletions src/keyvalue/http.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
use axum::routing::get;
use axum::Router;
use hyper::{Body, StatusCode};
use std::str::FromStr;
use std::sync::Arc;
use tonic::Request;
use url::Url;

use crate::keyvalue::keyvalue_proto::key_value_server::KeyValue;
use crate::keyvalue::keyvalue_proto::GetRequest;
use crate::keyvalue::KeyValueService;

#[derive(Clone)]
pub struct HttpHandler {
service: Arc<KeyValueService>,
}

impl HttpHandler {
pub fn new(service: Arc<KeyValueService>) -> Self {
Self { service }
}

pub fn routes(self: Arc<Self>) -> Router {
let hello = move |req: hyper::Request<Body>| async move { self.handle_get(req).await };
Router::new().route("/get", get(hello))
}

fn invalid(message: String) -> hyper::Response<Body> {
hyper::Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::from(format!("{}\n", message)))
.unwrap()
}

async fn handle_get(&self, request: hyper::Request<Body>) -> hyper::Response<Body> {
// Bit of a hack to the URL library to parse this.
let full = format!("https://some.dummy.example.com{}", request.uri());
let parsed = match Url::from_str(full.as_str()) {
Ok(u) => u,
_ => return HttpHandler::invalid("must pass query".to_string()),
};

let key = match parsed
.query_pairs()
.find(|(k, v)| k == "key")
.map(|(k, v)| v)
{
Some(value) => value,
_ => return HttpHandler::invalid("must pass key parameter".to_string()),
};

let request = Request::new(GetRequest {
key: key.clone().as_bytes().to_vec(),
version: -1,
});

// TODO - donotmerge - replace these "unwrap"s with better error handling

let output = match self.service.get(request).await {
Ok(proto) => {
let inner = proto.into_inner();
let value = String::from_utf8(inner.entry.unwrap().value).unwrap();
format!("{}={}, version={}\n", key, value, inner.version)
}
Err(status) => format!("{}\n", status.to_string()),
};

hyper::Response::builder()
.status(StatusCode::OK)
.body(Body::from(output))
.unwrap()
}
}
6 changes: 4 additions & 2 deletions src/keyvalue/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@
// cluster. Users of this module are expected to run the service in their grpc
// server and/or use the generated grpc client code to make requests.

pub use crate::keyvalue::store::{MapStore};
pub use crate::keyvalue::store::{MapStore, Store};
pub use http::HttpHandler;
pub use service::KeyValueService;

pub mod grpc {
pub use crate::keyvalue::keyvalue_proto::key_value_client::KeyValueClient;
pub use crate::keyvalue::keyvalue_proto::key_value_server::KeyValueServer;
pub use crate::keyvalue::keyvalue_proto::{PutRequest};
pub use crate::keyvalue::keyvalue_proto::PutRequest;
}

pub(in crate::keyvalue) mod http;
#[path = "generated/keyvalue_proto.rs"]
pub(in crate::keyvalue) mod keyvalue_proto;
pub(in crate::keyvalue) mod service;
Expand Down
4 changes: 2 additions & 2 deletions src/keyvalue/store.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
extern crate bytes;
extern crate im;

use std::collections::VecDeque;
use bytes::Bytes;
use im::HashMap;
use prost::Message;
use keyvalue_proto::{Entry, Operation, Snapshot};
use prost::Message;
use std::collections::VecDeque;

use crate::keyvalue::keyvalue_proto;
use crate::keyvalue::keyvalue_proto::operation::Op::Set;
Expand Down
Loading

0 comments on commit 0d390a4

Please sign in to comment.