New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Custom lifetimes for callback request headers and futures #30
Comments
You're doing the same mistake again and again. This is not related to Tungstenite. Did you read the tutorial? https://tokio.rs/docs/getting-started/futures/ Also, your reference to the |
@Relrin why do you suspect lifetimes to be a problem in this place. According to the errors you posted in your question, rust compiler does not like the type which you passed in This is the As you can see from the documentation for this function, it tells exactly the same the Rust compiler wrote in the error. |
@agalakhov @application-developer-DA pub fn run(&self, address: SocketAddr) {
let mut core = Core::new().unwrap();
let handle = core.handle();
let socket = TcpListener::bind(&address, &handle).unwrap();
println!("Listening on: {}", address);
let server = socket.incoming().for_each(|(stream, addr)| {
let engine_inner = self.engine.clone();
let connections_inner = self.connections.clone();
let auth_middleware_inner = self.auth_middleware.clone();
let handle_inner = handle.clone();
let mut headers: Headers = HashMap::new();
let copy_headers_callback = |request: &Request| {
for &(ref name, ref value) in request.headers.iter() {
headers.insert(name.to_string(), value.clone());
}
Ok(None)
};
accept_hdr_async(stream, copy_headers_callback)
// Process the messages
.and_then(move |ws_stream| { You will receive an error that was generated by the compiler:
|
Because it does not live long enough. Your function is asynchronous, that is, you can't tell WHEN the callback will be called. The |
I'd tried to prolong the life an object via using So, the compiler said "your headers should somewhere outside" of the scope of The current implementation looks like this: pub type Headers = HashMap<String, Box<[u8]>>;
pub struct Proxy {
engine: Rc<RefCell<Engine>>,
connections: Rc<RefCell<HashMap<SocketAddr, mpsc::UnboundedSender<Message>>>>,
auth_middleware: Rc<RefCell<Box<Middleware>>>,
}
impl Proxy {
pub fn new(router: Box<Router>, cli: &CliOptions) -> Proxy {
let auth_middleware: Box<Middleware> = Box::new(EmptyMiddleware::new(cli));
Proxy {
engine: Rc::new(RefCell::new(Engine::new(router))),
connections: Rc::new(RefCell::new(HashMap::new())),
auth_middleware: Rc::new(RefCell::new(auth_middleware)),
}
}
pub fn run(&self, address: SocketAddr) {
let mut core = Core::new().unwrap();
let handle = core.handle();
let socket = TcpListener::bind(&address, &handle).unwrap();
println!("Listening on: {}", address);
let server = socket.incoming().for_each(|(stream, addr)| {
let engine_inner = self.engine.clone();
let connections_inner = self.connections.clone();
let auth_middleware_inner = self.auth_middleware.clone();
let handle_inner = handle.clone();
let mut headers: Rc<RefCell<Headers>> = Rc::new(RefCell::new(HashMap::new()));
let copy_headers_callback = |request: &Request| {
let headers_inner = headers.clone();
for &(ref name, ref value) in request.headers.iter() {
headers_inner.borrow_mut().insert(name.to_string(), value.clone());
}
Ok(None)
};
accept_hdr_async(stream, copy_headers_callback)
// Process the messages
.and_then(move |ws_stream| {
// Create a channel for the stream, which other sockets will use to
// send us messages. It could be used for broadcasting your data to
// another users in the future.
let (tx, rx) = mpsc::unbounded();
connections_inner.borrow_mut().insert(addr, tx);
// Split the WebSocket stream so that it will be possible to work
// with the reading and writing halves separately.
let (sink, stream) = ws_stream.split();
// TODO: fire it before starting the processing messages
let _auth_future = auth_middleware_inner.borrow().process_request(&headers.borrow(), &handle_inner);
// Read and process each message
let connections = connections_inner.clone();
let ws_reader = stream.for_each(move |message: Message| {
engine_inner.borrow().handle(&message, &addr, &connections);
Ok(())
});
// Write back prepared responses
let ws_writer = rx.fold(sink, |mut sink, msg| {
sink.start_send(msg).unwrap();
Ok(sink)
});
// Wait for either half to be done to tear down the other
let connection = ws_reader.map(|_| ()).map_err(|_| ())
.select(ws_writer.map(|_| ()).map_err(|_| ()));
// Close the connection after using
handle_inner.spawn(connection.then(move |_| {
connections_inner.borrow_mut().remove(&addr);
println!("Connection {} closed.", addr);
Ok(())
}));
Ok(())
})
// An error occurred during the WebSocket handshake
.or_else(|err| {
println!("{}", err.description());
Ok(())
})
});
// Run the server
core.run(server).unwrap();
}
} A generated error is still the same:
|
Because you did not prolong anything. This time you have a short-living reference to This is usually done so:
Please read thr Rust lifetimes tutorial and understand the difference between cloning a |
Switch from sha1 to sha-1
Like as mentioned in the issue about headers, I'd decided to move a part of callback code to the future and using it later. But I'm getting errors, when trying to assign a custom lifetime to a code, where client headers is going to outlive futures, so that I could use it inside of futures (like, to check a token inside of the main processing part). After the moment when the client will end sending requests (or the connecting will be closed by the server by some certain reason), header should deleted.
Code:
Errors:
Any ideas how it could be fixed?
The text was updated successfully, but these errors were encountered: