chiark / gitweb /
server: wip, mime type, generated ICE
[hippotat.git] / src / bin / server.rs
1 // Copyright 2021 Ian Jackson and contributors to Hippotat
2 // SPDX-License-Identifier: GPL-3.0-or-later
3 // There is NO WARRANTY.
4
5 use hippotat::prelude::*;
6
7 #[derive(StructOpt,Debug)]
8 pub struct Opts {
9   #[structopt(flatten)]
10   log: LogOpts,
11
12   #[structopt(flatten)]
13   config: config::Opts,
14 }
15
16
17 async fn handle(
18 //    context: (),
19 //    addr: SocketAddr,
20     _req: hyper::Request<hyper::Body>
21 ) -> Result<hyper::Response<hyper::Body>, Infallible> {
22
23   let (boundary, warning) = (||{
24     let mut ctypes = req.headers().get_all();
25     let t = ctypes.next().ok_or_else(|| anyhow!("missing Content-Type"))?;
26     if ctypes.next().is_soe() { throw!(anyhow!("several Content-Type")) }
27     let t: mime::Mime = t.parse().context("parse Content-Type")?;
28     if t.type_() != "multipart" { throw!(anyhow!("not multipart/")) }
29     let b = t.get_param(mime::BOUNDARY).context("missing boundary=...")?;
30     let warning = (||{
31       if t.subtype != "form-data" { throw!(anyhow("not multipart/form-data")) }
32       Ok::<_,AE>(())
33     })();
34     Ok::<_,AE>((b, warning))
35   }()).unwrap_or_else(|e| {
36     ("b", Err(e.context("guessing boundary")))
37   });
38
39   eprintln!("boundary={} warning={}", boundary, warning);
40
41
42   Ok(hyper::Response::new(hyper::Body::from("Hello World")))
43 }
44
45
46 #[tokio::main]
47 async fn main() {
48   let opts = Opts::from_args();
49   let mut hservers = vec![];
50   let (ics,(global,ipif)) = config::startup(
51     "hippotatd", LinkEnd::Server,
52     &opts.config, &opts.log, |ics|
53   {
54     let global = config::InstanceConfigGlobal::from(&ics);
55     let ipif = Ipif::start(&global.ipif, None)?;
56
57     let make_service = hyper::service::make_service_fn(|_conn| async {
58       Ok::<_, Infallible>(hyper::service::service_fn(handle))
59     });
60
61     for addr in &global.addrs {
62       let addr = SocketAddr::new(*addr, global.port);
63       let server = hyper::Server::try_bind(&addr)
64         .context("bind")?
65         .http1_preserve_header_case(true)
66         .serve(make_service);
67       info!("listening on {}", &addr);
68       let task = tokio::task::spawn(server);
69       hservers.push(task);
70     }
71
72     Ok((global, ipif))
73   });
74
75   let x = future::select_all(&mut hservers).await;
76   error!("xxx hserver {:?}", &x);
77
78   ipif.quitting(None).await;
79
80   dbg!(ics, global);
81 }