commit f23ac0aba3e6caacf4541ca1ffb952a1c149c253
parent 000292e482d8c174a165e588a42976eef497c9c7
Author: lash <dev@holbrook.no>
Date:   Tue, 21 Jun 2022 10:07:13 +0000
Factor out immutable put
Diffstat:
| M | src/main.rs | | | 87 | ++++++++++++++++++++++++++++++++++++------------------------------------------- | 
| M | src/mutable.rs | | | 52 | ---------------------------------------------------- | 
2 files changed, 40 insertions(+), 99 deletions(-)
diff --git a/src/main.rs b/src/main.rs
@@ -9,20 +9,23 @@ use tiny_http::{
 use std::net::{Ipv4Addr, SocketAddrV4};
 use std::str::FromStr;
 use std::path::{PathBuf, Path};
-use std::fs::copy as fs_copy;
 use std::fs::File;
-use std::io::Write;
-use sha2::{Sha256, Digest};
+use std::fmt::Error;
 
 use env_logger;
 
 mod auth;
-mod mutable;
+mod record;
 
 use auth::{
     AuthSpec,
     AuthResult,
 };
+use record::{
+    put_immutable,
+    RequestError,
+    RequestErrorType,
+};
 
 use log::{debug, info, error};
 
@@ -58,6 +61,32 @@ fn exec_auth(auth_spec: AuthSpec) -> Option<AuthResult> {
 }
 
 
+fn exec_error(e: RequestError, req: Request) {
+    let res_status: StatusCode;
+    match e.typ {
+        RequestErrorType::WriteError => {
+            res_status = StatusCode(500);
+        },
+        RequestErrorType::AuthError => {
+            res_status = StatusCode(403);
+        },
+        RequestErrorType::FormatError => {
+            res_status = StatusCode(400);
+        },
+        _ => {
+            res_status = StatusCode(500);
+        },
+    }
+    match e.v {
+        Some(v) => {
+            req.respond(Response::from_string(v));
+        },
+        None => {
+            req.respond(Response::empty(res_status));
+        }
+    }
+}
+
 fn main() {
     env_logger::init();
 
@@ -198,52 +227,16 @@ fn main() {
             },
         };
 
-        let tempfile = match NamedTempFile::new() {
-            Ok(of) => {
-                debug!("writing to tempfile {:?} expected size {}", of.path(), expected_size);
-
-                let f = req.as_reader();
-                let mut buf: [u8; 65535] = [0; 65535];
-                let mut h = Sha256::new();
-                loop {
-                    match f.read(&mut buf[..]) {
-                        Ok(v) => {
-                            if v == 0 {
-                                break;
-                            }
-                            total_size += v;
-                            let data = &buf[..v];
-                            h.update(data);
-                            of.as_file().write(data);
-                        },
-                        Err(e) => {
-                            error!("cannot read from request body: {}", e);
-                            break;
-                        },
-                    }
-                }
-
-                if expected_size != total_size {
-                    res_status = StatusCode(400);
-                    let mut res = Response::empty(res_status);
-                    req.respond(res);
-                    continue;
-                }
-                let z = h.finalize();
-                hash = hex::encode(z);
-                info!("have hash {} for content", hash);
-                of
+        let f = req.as_reader();
+        match put_immutable(&path, f, expected_size) {
+            Ok(v) => {
+                hash = hex::encode(v); 
             },
             Err(e) => {
-                res_status = StatusCode(500);
-                let mut res = Response::empty(res_status);
-                req.respond(res);
+                exec_error(e, req);
                 continue;
-            }
-        };
-
-        let final_path = path.join(&hash);
-        fs_copy(tempfile.path(), final_path.as_path());
+            },
+        }
 
         res_status = StatusCode(200);
         let mut res = Response::from_string(hash);
diff --git a/src/mutable.rs b/src/mutable.rs
@@ -1,53 +1 @@
-use std::str::FromStr;
-use std::convert::Infallible;
 
-use sha2::{Sha256, Digest};
-
-use crate::auth::AuthResult;
-
-pub struct ResourceKey { 
-    v: Vec<u8>,
-}
-
-impl FromStr for ResourceKey {
-    type Err = Infallible;
-
-    fn from_str(s: &str) -> Result<ResourceKey, Infallible> {
-            let mut h = Sha256::new();
-            h.update(&s[..]);
-            let k = ResourceKey{
-                v: h.finalize().to_vec(),
-            };
-            Ok(k)
-    }
-}
-
-impl ResourceKey {
-    pub fn pointer_for(&self, subject: &AuthResult) -> Vec<u8> {
-        let mut h = Sha256::new();
-        h.update(&self.v);
-        h.update(&subject.identity);
-        h.finalize().to_vec()
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::ResourceKey;
-    use super::AuthResult;
-    use hex;
-
-    #[test]
-    fn test_pointer() {
-        let resource = ResourceKey{
-            v: vec!(0x66, 0x6f, 0x6f),
-        };
-        let subject = AuthResult{
-            identity: vec!(0x62, 0x61, 0x72),
-        };
-        let r = resource.pointer_for(&subject);
-
-        let foobar_digest = hex::decode("c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2").unwrap();
-        assert_eq!(r, foobar_digest);
-    }
-}