about summary refs log tree commit diff
path: root/src/micropub
diff options
context:
space:
mode:
Diffstat (limited to 'src/micropub')
-rw-r--r--src/micropub/mod.rs84
1 files changed, 83 insertions, 1 deletions
diff --git a/src/micropub/mod.rs b/src/micropub/mod.rs
index dc74d6e..b81ac17 100644
--- a/src/micropub/mod.rs
+++ b/src/micropub/mod.rs
@@ -57,6 +57,82 @@ impl MicropubError {
     }
 }
 
+pub mod media {
+    use futures_util::{Stream, StreamExt};
+    use bytes::buf::Buf;
+    use warp::{Filter, Rejection, Reply, multipart::{FormData, Part}};
+
+    pub fn query() -> impl Filter<Extract = (impl Reply,), Error = Rejection> + Clone {
+        warp::get()
+            .and(crate::util::require_host())
+            .map(|host| "media endpoint query...")
+    }
+
+    pub fn options() -> impl Filter<Extract = (impl Reply,), Error = Rejection> + Clone {
+        warp::options()
+            .map(|| warp::reply::json::<Option<()>>(&None))
+            // TODO: why doesn't this work?
+            // .map(warp::reply::with::header("Allow", "GET, POST"))
+            .map(|reply| warp::reply::with_header(reply, "Allow", "GET, POST"))
+    }
+
+    pub fn upload() -> impl Filter<Extract = (impl Reply,), Error = Rejection> + Clone {
+        warp::post()
+            .and(crate::util::require_host())
+            .and(warp::multipart::form().max_length(1024*1024*150/*mb*/))
+            .and_then(|host, mut form: FormData| async move {
+                // TODO get rid of the double unwrap() here
+                let file: Part = form.next().await.unwrap().unwrap();
+                log::debug!("Uploaded: {:?}, type: {:?}", file.filename(), file.content_type());
+
+                let mut data = file.stream();
+                while let Some(buf) = data.next().await {
+                    // TODO save it into a file
+                    log::debug!("buffer length: {:?}", buf.map(|b| b.remaining()));
+                }
+                Ok::<_, warp::Rejection>(warp::reply::with_header(
+                    warp::reply::with_status(
+                        "",
+                        warp::http::StatusCode::CREATED
+                    ),
+                    "Location",
+                    "./awoo.png"
+                ))
+            })
+    }
+
+    pub fn media() -> impl Filter<Extract = (impl Reply,), Error = Rejection> + Clone {
+        upload()
+            .or(query())
+            .or(options())
+    }
+}
+
+async fn _post<D: Storage>(db: D, host: warp::host::Authority, user: crate::indieauth::User) -> impl warp::Reply {
+    todo!("post to database {:?} for host {:?} using user {:?}", db, host, user);
+    #[allow(unreachable_code)]
+    ""
+}
+
+pub fn post<D: Storage, T>(db: D, token_endpoint: String, http: hyper::Client<T, hyper::Body>) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone
+where T: hyper::client::connect::Connect + Clone + Send + Sync + 'static {
+    warp::post()
+        .map(move || db.clone())
+        .and(crate::util::require_host())
+        .and(crate::indieauth::require_token(token_endpoint, http))
+        // TODO get body and process it
+        .then(_post)
+}
+
+pub fn options() -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Copy {
+    warp::options()
+        // TODO make it reply with a basic description of Micropub spec
+        .map(|| warp::reply::json::<Option<()>>(&None))
+        // TODO: why doesn't this work?
+        // .map(warp::reply::with::header("Allow", "GET, POST"))
+        .map(|reply| warp::reply::with_header(reply, "Allow", "GET, POST"))
+}
+
 async fn _query<D: Storage>(db: D, host: warp::host::Authority, query: MicropubQuery, user: crate::indieauth::User) -> impl warp::Reply {
     let user_authority = warp::http::Uri::try_from(user.me.as_str()).unwrap().authority().unwrap().clone();
     // TODO compare with potential list of allowed websites
@@ -161,6 +237,13 @@ pub async fn recover(err: Rejection) -> Result<impl warp::Reply, Infallible> {
     Ok(warp::reply::with_status(warp::reply::json(&error), error.into()))
 }
 
+pub fn micropub<D: Storage, T>(db: D, token_endpoint: String, http: hyper::Client<T, hyper::Body>) -> impl Filter<Extract = (impl warp::Reply,), Error = Infallible> + Clone
+where T: hyper::client::connect::Connect + Clone + Send + Sync + 'static {
+    query(db.clone(), token_endpoint.clone(), http.clone())
+        .or(post(db.clone(), token_endpoint.clone(), http.clone()))
+        .or(options())
+        .recover(recover)
+}
 #[cfg(test)]
 impl MicropubQuery {
     fn config() -> Self {
@@ -178,7 +261,6 @@ impl MicropubQuery {
     }
 }
 
-
 #[cfg(test)]
 mod tests {
     use hyper::body::HttpBody;