I have a simple rest sort of skin around a large text file that I need to query interactively. It can involve a heavy compute so I used rust. I have put a simple restful skin with Iron. Note that I haven't done much with rust. This is just running on localhost.
pub fn query<'a>(parsed: &'a Parsed, context:&Context) -> {
// parsed.keys is a hash containing config informtion
// context is what I query
let local_port = format!("{}:{}", "localhost", parsed.keys[AS_SERVER]);
fn test_connect<'a>(r: &'a mut Request, c:&'a Context) -> IronResult<Response> {
let url = r.url.to_string();
let result = // some logic
Ok(Response::with((status::Ok, format!("requested=\"{}:{}\"\n", url, result))))
}
let mut router = Router::new();
router.get("*", move |r: &mut Request| test_connect(r, &context));
let connection_status = Iron::new(router).http(&local_port[..]);
connection_status.ok().expect("could not connect");
}
Now my question is how do I get control to return out of the listening loop in
Iron::new(router).http(&local_port[..]);
I just want to say curl http://localhost/done
and have the listen function exit and so some logging and and move on. Is this possible to do this? I have tried panic-ing, but even that won't exit the listening loop?
I tried returning something like Err(IronError::new(StringError(url),status::ServiceUnavailable))
That status::ServiceUnavailable
is just something random - it needed something: I know it's not semantically correct, not sure what to use. But the error doesn't have any handler on it, so it goes away silently.
I suppose I will set something up with aftermiddleware, but I don't know what?
One way of doing it is to set up messages between your handler and the thread that started the server. When the message is sent, the main thread can call Listening::close
In this example, I used a Condvar
. I'd expect you could also use a channel, but wasn't able to quickly copy and paste the example channel and get it working... ^_^
extern crate iron;
use iron::prelude::*;
use iron::status;
use std::sync::{Arc, Mutex, Condvar};
fn main() {
// Copied from docs
let pair = Arc::new((Mutex::new(false), Condvar::new()));
let pair2 = pair.clone();
let handler = move |_: &mut Request| {
// Copied from docs
let &(ref lock, ref cvar) = &*pair2;
let mut should_exit = lock.lock().unwrap();
*should_exit = true;
cvar.notify_one();
Ok(Response::with((status::Ok, "Hello World!")))
};
// Hold onto the listener
let mut serv = Iron::new(handler).http("localhost:3210").unwrap();
println!("Now listening...");
// Copied from docs
let &(ref lock, ref cvar) = &*pair;
let mut should_exit = lock.lock().unwrap();
while !*should_exit {
should_exit = cvar.wait(should_exit).unwrap();
}
serv.close().unwrap();
println!("Exiting...");
}