You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

85 lines
2.5 KiB

10 months ago
10 months ago
10 months ago
  1. use std::sync::Arc;
  2. use hyper::{Body, Method, Request, Response, Server, StatusCode, service::{make_service_fn, service_fn}};
  3. use tokio::{fs::File, sync::Mutex};
  4. use tokio_util::codec::{BytesCodec, FramedRead};
  5. use crate::msqw::MSQW;
  6. mod msqw;
  7. type GenericError = Box<dyn std::error::Error + Send + Sync>;
  8. type Result<T> = std::result::Result<T, GenericError>;
  9. static NOTFOUND: &[u8] = b"Not Found";
  10. async fn bits_api(
  11. pool: Arc<Mutex<MSQW>>,
  12. req: Request<Body>
  13. ) -> Result<Response<Body>> {
  14. match (req.method(), req.uri().path()) {
  15. (&Method::GET, "/") => simple_file_send("static/index.html").await,
  16. (&Method::GET, "/index.js") => simple_file_send("static/index.js").await,
  17. (&Method::GET, "/bits") => api_get_bits(pool).await,
  18. (&Method::POST, "/zero") => api_post_zero(pool).await,
  19. (&Method::POST, "/one") => api_post_one(pool).await,
  20. _ => {
  21. // Return 404 not found response.
  22. Ok(not_found())
  23. }
  24. }
  25. }
  26. async fn api_get_bits(pool: Arc<Mutex<MSQW>>) -> Result<Response<Body>> {
  27. // always return a u32
  28. let bits = format!("{:032b}", pool.lock().await.update());
  29. Ok(Response::new(bits.into()))
  30. }
  31. async fn api_post_zero(pool: Arc<Mutex<MSQW>>) -> Result<Response<Body>> {
  32. pool.lock().await.add(false);
  33. Ok(Response::new("OK".into()))
  34. }
  35. async fn api_post_one(pool: Arc<Mutex<MSQW>>) -> Result<Response<Body>> {
  36. pool.lock().await.add(true);
  37. Ok(Response::new("OK".into()))
  38. }
  39. async fn simple_file_send(filename: &str) -> Result<Response<Body>> {
  40. // Serve a file by asynchronously reading it by chunks using tokio-util crate.
  41. if let Ok(file) = File::open(filename).await {
  42. let stream = FramedRead::new(file, BytesCodec::new());
  43. let body = Body::wrap_stream(stream);
  44. return Ok(Response::new(body));
  45. }
  46. Ok(not_found())
  47. }
  48. fn not_found() -> Response<Body> {
  49. Response::builder()
  50. .status(StatusCode::NOT_FOUND)
  51. .body(NOTFOUND.into())
  52. .unwrap()
  53. }
  54. #[tokio::main]
  55. async fn main() {
  56. let addr = ([0, 0, 0, 0], 3000).into();
  57. let pool = Arc::new(Mutex::new(MSQW::new()));
  58. let pool = &*Box::leak(Box::new(pool));
  59. let service = make_service_fn(
  60. move |_| async move {
  61. Ok::<_, hyper::Error>(service_fn(move |req| bits_api(pool.clone(), req)))
  62. });
  63. let server = Server::bind(&addr).serve(service);
  64. println!("Listening on http://{}", addr);
  65. if let Err(e) = server.await {
  66. eprintln!("server error: {}", e);
  67. }
  68. }