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 }