wala-rust

Content-adressed HTTP file server
Info | Log | Files | Refs | README | LICENSE

response.rs (7996B)


      1 use std::str::FromStr;
      2 
      3 use log::{debug};
      4 
      5 use tiny_http::{
      6     StatusCode,
      7     Request,
      8     Response,
      9     Header,
     10     HeaderField,
     11 };
     12 use ascii::AsciiString;
     13 
     14 //use mime::Mime;
     15 //use mime::TEXT;
     16 
     17 use crate::record::{
     18     RequestResult,
     19     RequestResultType,
     20 };
     21 
     22 
     23 pub fn origin_headers() -> Vec<Header> {
     24     let mut headers: Vec<Header> = vec!();
     25     headers.push(Header{
     26         field: HeaderField::from_str("Access-Control-Allow-Origin").unwrap(),
     27         value: AsciiString::from_ascii("*").unwrap(),
     28     });
     29     headers.push(Header{
     30         field: HeaderField::from_str("Access-Control-Allow-Methods").unwrap(),
     31         value: AsciiString::from_ascii("OPTIONS, PUT, GET, HEAD").unwrap(),
     32     });
     33     headers.push(Header{
     34         field: HeaderField::from_str("Access-Control-Allow-Headers").unwrap(),
     35         value: AsciiString::from_ascii("Content-Type,Authorization,X-Filename,X-Wala-Trace").unwrap(),
     36     });
     37 
     38     let server_header_v = format!("wala/{}, tiny_http (Rust)", env!("CARGO_PKG_VERSION"));
     39     headers.push(Header{
     40             field: HeaderField::from_str("Server").unwrap(),
     41             value: AsciiString::from_ascii(server_header_v).unwrap(),
     42         });
     43 
     44     let mut cap_headers: Vec<String> = vec!();
     45     #[cfg(feature="pgpauth")]
     46     {
     47         let h = String::from("auth_pgp");
     48         cap_headers.push(h);
     49     };
     50 
     51     #[cfg(feature="magic")]
     52     {
     53         let h = String::from("magic");
     54         cap_headers.push(h);
     55     };
     56 
     57     #[cfg(feature="meta")]
     58     {
     59         let h = String::from("meta");
     60         cap_headers.push(h);
     61     };
     62 
     63     if cap_headers.len() == 0 {
     64         cap_headers.push(String::from("default")); 
     65     }
     66 
     67     let v = cap_headers.join(",");
     68     headers.push(Header{
     69         field: HeaderField::from_str("X-Wala-Cap").unwrap(),
     70         value: AsciiString::from_ascii(v).unwrap(),
     71     });
     72     headers
     73 }
     74 
     75 pub fn preflight_response(req: Request) {
     76     let auth_origin_headers = origin_headers();
     77     let res_status = StatusCode(200);
     78     let mut res = Response::empty(res_status);
     79     for v in auth_origin_headers.iter() {
     80         res.add_header(v.clone());
     81     }
     82     _ = req.respond(res);
     83     debug!("served options request");
     84     return;
     85 }
     86 
     87 // req marked as unused but seems used in all branches
     88 // TODO: return something reasonable in all cases e.g. the respond return value
     89 pub fn exec_response(req: Request, r: RequestResult) {
     90     let res_status: StatusCode;
     91     match r.typ {
     92         RequestResultType::Found => {
     93             res_status = StatusCode(200);
     94         },
     95         RequestResultType::Changed => {
     96             res_status = StatusCode(200);
     97         },
     98         RequestResultType::WriteError => {
     99             res_status = StatusCode(500);
    100         },
    101         RequestResultType::AuthError => {
    102             res_status = StatusCode(403);
    103         },
    104         RequestResultType::InputError => {
    105             res_status = StatusCode(400);
    106         },
    107         RequestResultType::RecordError => {
    108             res_status = StatusCode(404);
    109         },
    110         _ => {
    111             res_status = StatusCode(500);
    112         },
    113     }
    114 
    115     debug!("have status, {:?}", &res_status);
    116 
    117     match r.v {
    118         Some(v) => {
    119             let auth_origin_headers = origin_headers();
    120             let mut res = Response::from_string(v);
    121             res = res.with_status_code(res_status);
    122             for v in auth_origin_headers.iter() {
    123                 res.add_header(v.clone());
    124             }
    125             match r.l {
    126                 Some(l) => {
    127                     let h = Header{
    128                         field: HeaderField::from_str("Content-Length").unwrap(),
    129                         value: AsciiString::from_ascii(l.to_string()).unwrap(),
    130                     };
    131                     res.add_header(h);
    132                 },
    133                 _ => {
    134                 },
    135             };
    136 
    137             _ = req.respond(res);
    138             return;
    139         },
    140         None => {
    141             let auth_origin_headers = origin_headers();
    142             match r.f {
    143                 Some(v) => {
    144                     let mut content_type = String::new();
    145                     let mut res = Response::from_file(v);
    146                     match r.m {
    147                         Some(v) => {
    148                             content_type.push_str(v.as_ref());
    149                             let h = Header{
    150                                 field: HeaderField::from_str("Content-Type").unwrap(),
    151                                 value: AsciiString::from_ascii(content_type.clone()).unwrap(),
    152                             };
    153                             res.add_header(h);
    154                         }, 
    155                         _ => {
    156                             content_type.push_str("application/octet-stream");
    157                         },
    158                     };
    159                     match r.n {
    160                         Some(v) => {
    161                             let s = format!("attachment; filename=\"{}\"", &v);
    162                             let h = Header{
    163                                 field: HeaderField::from_str("Content-Disposition").unwrap(),
    164                                 value: AsciiString::from_ascii(s.as_str()).unwrap(),
    165                             };
    166                             res.add_header(h);
    167                         }, 
    168                         _ => {
    169                             let m = mime::Mime::from_str(&content_type).unwrap();
    170                             let s = match m.type_() {
    171                                 mime::TEXT => {
    172                                     String::from("inline")
    173                                 },
    174                                 mime::IMAGE => {
    175                                     String::from("inline")
    176                                 },
    177                                 _ => {
    178                                     String::from("attachment")
    179                                 },
    180                             };
    181                             let h = Header{
    182                                 field: HeaderField::from_str("Content-Disposition").unwrap(),
    183                                 value: AsciiString::from_ascii(s.as_str()).unwrap(),
    184                             };
    185                             res.add_header(h);
    186                         },
    187                     };
    188 
    189                     match r.l {
    190                         Some(l) => {
    191                             let h = Header{
    192                                 field: HeaderField::from_str("Content-Length").unwrap(),
    193                                 value: AsciiString::from_ascii(l.to_string()).unwrap(),
    194                             };
    195                             res.add_header(h);
    196                         },
    197                         _ => {
    198                         },
    199                     };
    200                     
    201                     res = res.with_status_code(res_status);
    202                     for v in auth_origin_headers.iter() {
    203                         res.add_header(v.clone());
    204                     }
    205                     _ = req.respond(res);
    206                     return;
    207                 },
    208                 None => {
    209                     let mut res = Response::empty(res_status);
    210                     for v in auth_origin_headers.iter() {
    211                         _ = res.add_header(v.clone());
    212                     }
    213 
    214                     match r.l {
    215                         Some(l) => {
    216                             let h = Header{
    217                                 field: HeaderField::from_str("Content-Length").unwrap(),
    218                                 value: AsciiString::from_ascii(l.to_string()).unwrap(),
    219                             };
    220                             res.add_header(h);
    221                         },
    222                         _ => {
    223                         },
    224                     };
    225 
    226                     _ = req.respond(res);
    227                     return;
    228                 },
    229             }
    230         }
    231     }
    232 
    233 }
    234 
    235 #[cfg(test)]
    236 mod tests {
    237     use tiny_http::Request;
    238     use crate::record::RequestResult;
    239     use super::exec_response;
    240 
    241     #[test]
    242     fn test_response_get_filename() {
    243 //       let r = Request{}
    244     }
    245 }