+#[get("/file/{path:.*}")]
+async fn static_file(params: web::Path<String>, req: HttpRequest) -> Result<impl Responder> {
+ let request_path = params.into_inner();
+ let disk_path = "../static/".to_string() + &request_path;
+
+ // if the client accepts gzip encoding, try that first
+ if let Some(accept_encoding) = req.headers().get(header::ACCEPT_ENCODING) {
+ if accept_encoding.to_str().unwrap().contains("gzip") {
+ let path_gz = disk_path.clone() + ".gz";
+ if Path::new(&path_gz).is_file() {
+ log::debug!("client accepts gzip encoding, sending pre-compressed file {}", &path_gz);
+ return Ok(NamedFile::open_async(path_gz).await?
+ .customize()
+ .insert_header(header::ContentEncoding::Gzip));
+ }
+ }
+ }
+
+ // uncompressed file
+ Ok(NamedFile::open_async(disk_path).await?.customize())
+}
+
+struct WsEcho;
+
+impl Actor for WsEcho {
+ type Context = ws::WebsocketContext<Self>;
+}
+
+impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for WsEcho {
+ fn handle(&mut self, msg: Result<ws::Message, ws::ProtocolError>, ctx: &mut Self::Context) {
+ log::info!("WsEcho got message {:?}", msg);
+ match msg {
+ Ok(ws::Message::Ping(msg)) => ctx.pong(&msg),
+ Ok(ws::Message::Text(text)) => ctx.text(text),
+ Ok(ws::Message::Binary(bin)) => ctx.binary(bin),
+ Ok(ws::Message::Close(reason)) => {
+ ctx.close(reason);
+ ctx.stop();
+ },
+ _ => ctx.stop(),
+ }
+ }
+}
+
+#[get("/ws-echo")]
+async fn ws_echo(req: HttpRequest, stream: web::Payload) -> Result<HttpResponse, Error> {
+ ws::start(WsEcho {}, &req, stream)
+}
+
+struct WsRev;
+
+impl Actor for WsRev {
+ type Context = ws::WebsocketContext<Self>;
+}
+
+impl StreamHandler<Result<ws::Message, ws::ProtocolError>> for WsRev {
+ fn handle(&mut self, msg: Result<ws::Message, ws::ProtocolError>, ctx: &mut Self::Context) {
+ log::info!("WsRev got message {:?}", msg);
+ match msg {
+ Ok(ws::Message::Ping(msg)) => ctx.pong(&msg),
+ Ok(ws::Message::Text(text)) => {
+ let rev = text.chars().rev().collect::<String>();
+ ctx.text(rev);
+ },
+ Ok(ws::Message::Binary(bin)) => {
+ let mut rev = bin.to_vec();
+ rev.reverse();
+ ctx.binary(rev);
+ }
+ Ok(ws::Message::Close(reason)) => {
+ ctx.close(reason);
+ ctx.stop();
+ },
+ _ => ctx.stop(),
+ }
+ }
+}
+
+#[get("/ws-rev")]
+async fn ws_rev(req: HttpRequest, stream: web::Payload) -> Result<HttpResponse, Error> {
+ ws::start(WsRev {}, &req, stream)
+}
+
+// App is a template soup, too hard as a proper function
+macro_rules! get_app {
+ () => {
+ App::new()
+ .service(hello)
+ .service(static_file)
+ .service(Files::new("/dir", "../static"))
+ .service(ws_echo)
+ .service(ws_rev)
+ }
+}
+