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 }