wala-rust

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

request.rs (8336B)


      1 use std::path::Path;
      2 use std::str::FromStr;
      3 use tiny_http::{
      4     Method,
      5     Response,
      6     Request,
      7     StatusCode,
      8 };
      9 use crate::record::{
     10     put_immutable,
     11     put_mutable,
     12     get as get_record,
     13     ResourceKey,
     14     RequestResult,
     15     RequestResultType,
     16 };
     17 use crate::auth::{
     18     AuthResult,
     19 };
     20 use std::io::Read;
     21 
     22 #[cfg(feature = "meta")]
     23 use crate::meta::{
     24     get_type as get_meta_type,
     25     get_filename as get_meta_filename,
     26 };
     27 
     28 use log::{
     29     debug,
     30     error,
     31 };
     32 
     33 /// Handle client input by method type.
     34 ///
     35 /// # Arguments
     36 ///
     37 /// * `method` - The HTTP method of the client request.
     38 /// * `url` - The local part of the URL of the client request.
     39 /// * `f` - Reader providing the content body of a client PUT request.
     40 /// * `expected_size` - Size hint for content body.
     41 /// * `path` - Absolute path to storage directory.
     42 /// * `auth_result` -  Result of authentication (if any) the client has provided with the request.
     43 pub fn process_method(method: &Method, url: String, mut f: impl Read, expected_size: usize, path: &Path, auth_result: AuthResult) -> RequestResult {
     44     match method {
     45         Method::Put => {
     46             if !auth_result.valid() {
     47                 return RequestResult::new(RequestResultType::AuthError);
     48             }
     49             if auth_result.active() {
     50                 let mut res: RequestResult;
     51                 let rk = ResourceKey::from_str(url.as_str()).unwrap();
     52                 debug!("mutable put, authenticated as {:?} using mutable key {} -> {}", auth_result, &url, &rk);
     53                 //let ptr = rk.pointer_for(&auth_result);
     54                 match put_mutable(path, f, expected_size, &rk, &auth_result) {
     55                     Ok(v) => {
     56                         let digest_hex = hex::encode(v.digest);
     57                         let alias_hex = hex::encode(v.alias.unwrap());
     58                         res = RequestResult::new(RequestResultType::Changed);
     59                         res = res.with_content(digest_hex);
     60                         res = res.with_auth(auth_result);
     61                         res = res.with_aliased(alias_hex);
     62                     },
     63                     Err(e) => {
     64                         let err_str = format!("{:?}", e);
     65                         error!("{}", err_str);
     66                         res = RequestResult::new(RequestResultType::RecordError);
     67                         res = res.with_content(String::from(err_str));
     68                     },
     69                 };
     70                 return res;
     71             } else {
     72                 debug!("immutable put");
     73                 let mut res: RequestResult;
     74                 match put_immutable(path, f, expected_size) {
     75                     Ok(v) => {
     76                         let digest_hex = hex::encode(v.digest);
     77                         res = RequestResult::new(RequestResultType::Changed);
     78                         res = res.with_content(digest_hex);
     79                     },
     80                     Err(e) => {
     81                         let err_str = format!("{}", e);
     82                         res = RequestResult::new(RequestResultType::RecordError);
     83                         res = res.with_content(String::from(err_str));
     84                     },
     85                 };
     86                 return res;
     87             }
     88         },
     89         Method::Get => {
     90             if &url == "" {
     91                 let mut res = RequestResult::new(RequestResultType::Found);
     92                 res = res.with_content(String::new());
     93                 return res;
     94             }
     95             let digest = match hex::decode(&url) {
     96                 Err(e) => {
     97                     let err_str = format!("{}", e);
     98                     let mut res = RequestResult::new(RequestResultType::InputError);
     99                     res = res.with_content(String::from(err_str));
    100                     return res;
    101                 },
    102                 Ok(v) => {
    103                     v
    104                 },
    105             };
    106 
    107             let full_path_buf = path.join(&url);
    108             debug!("url {} resolved to {:?}", &url, &full_path_buf);
    109 
    110             match get_record(digest.clone(), full_path_buf.as_path()) {
    111                 Some(v) => {
    112                     let mut res = RequestResult::new(RequestResultType::Found);
    113                     res = res.with_file(v);
    114 
    115                     #[cfg(feature = "meta")]
    116                     {
    117                         res.m = get_meta_type(path, &digest);
    118                         res.n = get_meta_filename(path, &digest);
    119                     }
    120                     return res;
    121                 },
    122                 None => {
    123                     return RequestResult::new(RequestResultType::RecordError);
    124                 },
    125             };
    126         },
    127         _ => {},
    128     };
    129     RequestResult::new(RequestResultType::InputError)
    130 }
    131 
    132 #[cfg(test)]
    133 mod tests {
    134     use tempfile::tempdir;
    135     use tiny_http::Method;
    136     use super::process_method;
    137     use std::fs::{
    138         read,
    139         write,
    140         File,
    141     };
    142     use std::path::Path;
    143     use crate::auth::AuthResult;
    144     use crate::record::RequestResultType;
    145     use env_logger;
    146 
    147 
    148     #[test]
    149     fn test_get_ok() {
    150         let d = tempdir().unwrap();
    151         let url = String::from("deadbeef");
    152         let data = "foobar";
    153 
    154         let fp = d.path().join(&url); //.as_path().to_string().unwrap();
    155         write(&fp, data);
    156         let f = File::open(&fp).unwrap();
    157 
    158         let method = Method::Get;
    159 
    160         let auth = AuthResult {
    161             identity: vec!(),
    162             error: false,
    163         };
    164 
    165         let res = process_method(&method, url, f, 6, &d.path(), auth);
    166         assert_eq!(res.typ, RequestResultType::Found);
    167     }
    168 
    169     #[test]
    170     fn test_get_bogus() {
    171         let d = tempdir().unwrap();
    172         let url = String::from("teadbeef");
    173         let data = "foobar";
    174 
    175         let fp = d.path().join(&url); //.as_path().to_string().unwrap();
    176         write(&fp, data);
    177         let f = File::open(&fp).unwrap();
    178 
    179         let method = Method::Get;
    180 
    181         let auth = AuthResult {
    182             identity: vec!(),
    183             error: false,
    184         };
    185 
    186         let res = process_method(&method, url, f, 6, &d.path(), auth);
    187         assert_eq!(res.typ, RequestResultType::InputError);
    188     }
    189 
    190     #[test]
    191     fn test_put_immutable() {
    192         let d = tempdir().unwrap();
    193         let mut url = String::from("deadbeef");
    194         let data = "foobar";
    195 
    196         let fp = d.path().join(&url); //.as_path().to_string().unwrap();
    197         write(&fp, data);
    198         let f = File::open(&fp).unwrap();
    199 
    200         let method = Method::Put;
    201 
    202         let auth = AuthResult {
    203             identity: vec!(),
    204             error: false,
    205         };
    206     
    207         url = String::new();
    208         let res = process_method(&method, url, f, 6, &d.path(), auth);
    209         assert_eq!(res.typ, RequestResultType::Changed);
    210 
    211         let content_ref = String::from("c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2");
    212         assert_eq!(res.v.unwrap(), content_ref);
    213 
    214     }
    215 
    216     #[test]
    217     fn test_put_mutable() {
    218         let d = tempdir().unwrap();
    219         let url = String::from("deadbeef");
    220         let data = "foobar";
    221 
    222         let fp = d.path().join(&url); //.as_path().to_string().unwrap();
    223         write(&fp, data);
    224         let f = File::open(&fp).unwrap();
    225 
    226         let method = Method::Put;
    227 
    228         let auth = AuthResult {
    229             identity: vec!(0x66, 0x6f, 0x6f),
    230             error: false,
    231         };
    232 
    233         let res = process_method(&method, url, f, 6, &d.path(), auth);
    234         assert_eq!(res.typ, RequestResultType::Changed);
    235 
    236         let content_ref = String::from("129208a8eac1bedd060645411baaae4aabc5d9e4c858942defe139b5ba15aba6");
    237         assert_eq!(res.v.unwrap(), content_ref);
    238 
    239         let fp_immutable = d.path().join(&content_ref);
    240         let r = read(fp_immutable).unwrap();
    241 
    242         assert_eq!(data.as_bytes(), r);
    243     }
    244 
    245     #[test]
    246     fn test_put_mutable_noauth() {
    247         let d = tempdir().unwrap();
    248         let url = String::from("deadbeef");
    249         let data = "foobar";
    250 
    251         let fp = d.path().join(&url); //.as_path().to_string().unwrap();
    252         write(&fp, data);
    253         let f = File::open(&fp).unwrap();
    254 
    255         let method = Method::Put;
    256 
    257         let auth = AuthResult {
    258             identity: vec!(0x2a),
    259             error: true,
    260         };
    261 
    262         let res = process_method(&method, url, f, 6, &d.path(), auth);
    263         assert_eq!(res.typ, RequestResultType::AuthError);
    264     }
    265 }