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.

92 lines
2.6 KiB

11 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. let response = Response::builder()
  30. .status(200)
  31. .header("Content-Type", "application/text")
  32. .body(bits.into())
  33. .unwrap();
  34. Ok(response)
  35. }
  36. async fn api_post_zero(pool: Arc<Mutex<MSQW>>) -> Result<Response<Body>> {
  37. pool.lock().await.add(false);
  38. Ok(Response::new("OK".into()))
  39. }
  40. async fn api_post_one(pool: Arc<Mutex<MSQW>>) -> Result<Response<Body>> {
  41. pool.lock().await.add(true);
  42. Ok(Response::new("OK".into()))
  43. }
  44. async fn simple_file_send(filename: &str) -> Result<Response<Body>> {
  45. // Serve a file by asynchronously reading it by chunks using tokio-util crate.
  46. if let Ok(file) = File::open(filename).await {
  47. let stream = FramedRead::new(file, BytesCodec::new());
  48. let body = Body::wrap_stream(stream);
  49. return Ok(Response::new(body));
  50. }
  51. Ok(not_found())
  52. }
  53. fn not_found() -> Response<Body> {
  54. Response::builder()
  55. .status(StatusCode::NOT_FOUND)
  56. .body(NOTFOUND.into())
  57. .unwrap()
  58. }
  59. #[tokio::main]
  60. async fn main() {
  61. let addr = ([127, 0, 0, 1], 3000).into();
  62. let pool = Arc::new(Mutex::new(MSQW::new()));
  63. let pool = &*Box::leak(Box::new(pool));
  64. let service = make_service_fn(
  65. move |_| async move {
  66. Ok::<_, hyper::Error>(service_fn(move |req| bits_api(pool.clone(), req)))
  67. });
  68. let server = Server::bind(&addr).serve(service);
  69. println!("Listening on http://{}", addr);
  70. if let Err(e) = server.await {
  71. eprintln!("server error: {}", e);
  72. }
  73. }