'Rust Hyper and Futures
I am getting started with Hyper on Rust. I have written a simple code(based on Hyper cannot find Server module ), and it seems to be nearly there, but running into few unexpected issues. Here is the minimized code snippet, should be easily reproducible. There 5 errors currently, marked with ISSUE comment:
use futures::{future, Future};
use hyper::service::service_fn;
use hyper::{Body, Error, Method, Request, Response, Server, StatusCode};
use lazy_static::lazy_static;
use log::{debug, info, trace};
use pretty_env_logger;
use rand;
use regex::Regex;
use slab::Slab;
use std::env;
use std::fmt;
use std::net::SocketAddr;
use std::sync::{Arc, Mutex};
lazy_static! {
static ref INDEX_PATH: Regex = Regex::new("^/(index\\.html?)?$").unwrap();
static ref USER_PATH: Regex = Regex::new("^/user/((?P<user_id>\\d+?)/?)?$").unwrap();
static ref USERS_PATH: Regex = Regex::new("^/users/?$").unwrap();
}
fn mini() {
pretty_env_logger::init();
info!("Anatoly's Microservice 1.1");
let addr: SocketAddr = env::var("ADDRESS")
.unwrap_or_else(|_| "127.0.0.1:8080".into())
.parse()
.expect("can't parse ADDRESS variable");
debug!("Trying to bind server to address: {}", addr);
let builder = Server::bind(&addr);
let udb = Arc::new(Mutex::new(Slab::new()));
trace!("Creating service handler");
let server = builder.serve(move || {
// ISSUE on .serve
let user_db = Arc::clone(&udb);
service_fn(move |req| {
trace!("Recieved Request: {:?}", req);
microservice_handler(req, &user_db)
})
});
info!("Used Addr: {}", server.local_addr());
let server = server.map_err(drop); // ISSUE
debug!("Run");
hyper::rt::run(server); // ISSUUE cannot find function run in hyper rt
}
/// ISSUE associated type Item and Error not found for futures::Future
fn microservice_handler(
req: Request<Body>,
user_db: &UserDB,
) -> impl Future<Item = Response<Body>, Error = Error> {
let response = {
let method = req.method();
let path = req.uri().path();
let mut users = user_db.lock().unwrap();
if INDEX_PATH.is_match(path) {
if method == &Method::GET {
let rand_byte = rand::random::<u8>();
debug!("Generated value is: {}", rand_byte);
Response::new(INDEX.replace("#RAND#", &*rand_byte.to_string()).into())
} else {
response_with_code(StatusCode::METHOD_NOT_ALLOWED)
}
}
// --Long matching sequence here--
else {
response_with_code(StatusCode::NOT_FOUND)
}
};
future::ok(response) //ISSUE cannot infer type E
}
fn response_with_code(status_code: StatusCode) -> Response<Body> {
Response::builder()
.status(status_code)
.body(Body::empty())
.unwrap()
}
// # is multiline string
const INDEX: &'static str = r#"
<!doctype html>
<html>
<head>
<title>Rust Microservices</title>
</head>
<body>
<h3>Rust Microservices #RAND#</h3>
</body>
</html>
"#;
type UserId = u64;
#[derive(Debug)]
struct UserData;
impl fmt::Display for UserData {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("{}")
}
}
type UserDB = Arc<Mutex<Slab<UserData>>>;
The issues are:
- function run not found in module
hyper::rt - associated types Error and Item not found for
futures::Future - type annotations needed on
future::ok - no method named map_err found for struct Server
- the trait bound
for<'a> [closure@src\main.rs:58:32: 64:6]: Service<&'a AddrStream> is not satisfied
My Cargo.toml:
slab = "0.4"
futures = "0.3.21"
hyper = {version = "0.14.17", features=["full"]}
lazy_static = "1.0"
regex = "1.0"
rand = "0.8.5"
log = "0.4"
pretty_env_logger = "0.4"
dotenv = "0.15"
How do I make my example compile? Any hints would be much appreciated!
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
