sys/sysmod/http/
line_hook.rs1use super::{ActixError, WebResult};
6use crate::taskserver::Control;
7
8use actix_web::{HttpRequest, HttpResponse, Responder, http::header::ContentType, web};
9use log::info;
10
11#[actix_web::get("/line/")]
12async fn index_get() -> impl Responder {
13 let body = r#"<!DOCTYPE html>
14<html lang="en">
15 <head>
16 <title>LINE Webhook</title>
17 </head>
18 <body>
19 <h1>LINE Webhook</h1>
20 <p>Your request is GET.</p>
21 </body>
22</html>
23"#;
24
25 HttpResponse::Ok()
26 .content_type(ContentType::html())
27 .body(body)
28}
29
30#[actix_web::post("/line/")]
31async fn index_post(req: HttpRequest, body: String, ctrl: web::Data<Control>) -> WebResult {
32 info!("LINE github webhook");
33
34 let headers = req.headers();
36 let signature = if let Some(s) = headers.get("x-line-signature") {
37 if let Ok(s) = s.to_str() {
38 s
39 } else {
40 return Err(ActixError::new("Bad x-line-signature header", 400));
41 }
42 } else {
43 return Err(ActixError::new("x-line-signature required", 400));
44 };
45 info!("x-line-signature: {signature}");
46
47 {
48 let line = ctrl.sysmods().line.lock().await;
49 if let Err(err) = line.verify_signature(signature, &body) {
51 return Err(ActixError::new(&err.to_string(), 401));
52 }
53
54 if let Err(e) = line.process_post(&body) {
55 return Err(ActixError::new(&e.to_string(), 400));
56 }
57 }
58 Ok(HttpResponse::Ok()
59 .content_type(ContentType::plaintext())
60 .body(""))
61}