use std::{env, fs};
use gluon::{
new_vm,
vm::api::{OwnedFunction, IO},
Thread, ThreadExt,
};
#[tokio::main]
async fn main() {
env_logger::init();
let port = env::args()
.nth(1)
.map(|port| port.parse::<u16>().expect("port"))
.unwrap_or(80);
let thread = new_vm();
if let Err(err) = start(&thread, port).await {
panic!("{}", err)
}
}
async fn start(thread: &Thread, port: u16) -> Result<(), anyhow::Error> {
let thread = thread.root_thread();
let expr = fs::read_to_string("examples/http/server.glu")?;
let (mut listen, _) = thread
.run_expr_async::<OwnedFunction<fn(u16) -> IO<()>>>("examples/http/server.glu", &expr)
.await?;
listen.call_async(port).await?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use std::str;
use futures::prelude::*;
use hyper::Client;
async fn wait_for_server(port: u16) -> Result<(), anyhow::Error> {
let mut err = None;
for _ in 0..40 {
match Client::new()
.get(format!("http://localhost:{}", port).parse().unwrap())
.await
{
Ok(response) => {
return response
.into_body()
.try_fold(Vec::new(), |mut acc, buf| async move {
acc.extend_from_slice(&buf);
Ok(acc)
})
.map_ok(|body| {
assert_eq!(str::from_utf8(&body).unwrap(), "Hello World");
})
.err_into::<anyhow::Error>()
.await;
}
Err(e) => err = Some(e),
}
tokio::time::sleep(std::time::Duration::from_millis(400)).await;
}
Err(err.unwrap().into())
}
#[tokio::test]
async fn hello_world() {
let _ = env_logger::try_init();
let port = 12234;
let thread = new_vm();
let start_server = async move {
tokio::spawn(async move { start(&thread, port).await.unwrap() });
wait_for_server(port).await
};
start_server.await.unwrap_or_else(|err| panic!("{}", err));
}
#[tokio::test]
async fn echo() {
let _ = env_logger::try_init();
let port = 12235;
let thread = new_vm();
let start_server = async move {
tokio::spawn(async move { start(&thread, port).await.unwrap() });
wait_for_server(port).await
};
start_server.await.unwrap_or_else(|err| panic!("{}", err));
let request = hyper::Request::post(format!("http://localhost:{}/echo", port))
.body(hyper::Body::from("test"))
.unwrap();
Client::new()
.request(request)
.err_into::<anyhow::Error>()
.and_then(|response| {
response
.into_body()
.try_fold(Vec::new(), |mut acc, buf| async move {
acc.extend_from_slice(&buf);
Ok(acc)
})
.map_ok(|body| {
assert_eq!(str::from_utf8(&body).unwrap(), "test");
})
.err_into::<anyhow::Error>()
})
.await
.unwrap_or_else(|err: anyhow::Error| panic!("{}", err));
}
}