1 // Copyright 2021 Ian Jackson and contributors to Hippotat
2 // SPDX-License-Identifier: GPL-3.0-or-later
3 // There is NO WARRANTY.
5 use hippotat::prelude::*;
7 #[derive(StructOpt,Debug)]
16 const METADATA_MAX_LEN: usize = MAX_OVERHEAD;
21 req: hyper::Request<hyper::Body>
22 ) -> Result<hyper::Response<hyper::Body>, Infallible> {
24 let mkboundary = |b: &'_ _| format!("\n--{}", b).into_bytes();
25 let (boundary, warning) = (||{
26 let mut ctypes = req.headers().get_all("Content-Type").iter();
27 let t = ctypes.next().ok_or_else(|| anyhow!("missing Content-Type"))?;
28 if ctypes.next().is_some() { throw!(anyhow!("several Content-Type")) }
29 let t = t.to_str().context("interpret Content-Type as utf-8")?;
30 let t: mime::Mime = t.parse().context("parse Content-Type")?;
31 if t.type_() != "multipart" { throw!(anyhow!("not multipart/")) }
32 let b = mime::BOUNDARY;
33 let b = t.get_param(b).ok_or_else(|| anyhow!("missing boundary=..."))?;
35 if t.subtype() != "form-data" { throw!(anyhow!("not /form-data"))}
38 let b = mkboundary(b.as_str());
39 Ok::<_,AE>((b, warning))
40 })().unwrap_or_else(|e| {
41 (mkboundary("b"), Err(e.wrap_err("guessing boundary")))
44 if let Err(w) = &warning { eprintln!("warning={}", w); }
47 let mut body = req.into_body();
48 let initial = match read_limited_bytes(METADATA_MAX_LEN, &mut body).await {
50 Err(ReadLimitedError::Truncated { sofar,.. }) => sofar,
51 Err(ReadLimitedError::Hyper(e)) => throw!(e),
54 eprintln!("boundary={:?} initial={:?}", boundary, initial);
61 eprintln!("error={}", e);
65 Ok(hyper::Response::new(hyper::Body::from("Hello World")))
71 let opts = Opts::from_args();
72 let mut hservers = vec![];
73 let (ics,(global,ipif)) = config::startup(
74 "hippotatd", LinkEnd::Server,
75 &opts.config, &opts.log, |ics|
77 let global = config::InstanceConfigGlobal::from(&ics);
78 let ipif = Ipif::start(&global.ipif, None)?;
80 let make_service = hyper::service::make_service_fn(|_conn| async {
81 Ok::<_, Infallible>(hyper::service::service_fn(handle))
84 for addr in &global.addrs {
85 let addr = SocketAddr::new(*addr, global.port);
86 let server = hyper::Server::try_bind(&addr)
88 .http1_preserve_header_case(true)
90 info!("listening on {}", &addr);
91 let task = tokio::task::spawn(server);
98 let x = future::select_all(&mut hservers).await;
99 error!("xxx hserver {:?}", &x);
101 ipif.quitting(None).await;