diff --git a/.dir-locals.el b/.dir-locals.el index d71a4fa..791e609 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -1,4 +1,5 @@ -;;; Directory Local Variables +;;; Directory Local Variables -*- no-byte-compile: t -*- ;;; For more information see (info "(emacs) Directory Variables") -((nil . ((compile-command . "hugo server --noHTTPCache")))) +((nil . ((compile-command . "hugo server --noHTTPCache"))) + (rustic-mode . ((rustic-rustfmt-args . "--edition 2021")))) diff --git a/Cargo.lock b/Cargo.lock index 50ef6d1..0cfad6c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -92,6 +92,44 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "actix-multipart" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee489e3c01eae4d1c35b03c4493f71cb40d93f66b14558feb1b1a807671cc4e" +dependencies = [ + "actix-multipart-derive", + "actix-utils", + "actix-web", + "bytes", + "derive_more", + "futures-core", + "futures-util", + "httparse", + "local-waker", + "log", + "memchr", + "mime", + "serde", + "serde_json", + "serde_plain", + "tempfile", + "tokio", +] + +[[package]] +name = "actix-multipart-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ec592f234db8a253cf80531246a4407c8a70530423eea80688a6c5a44a110e7" +dependencies = [ + "darling", + "parse-size", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "actix-router" version = "0.5.1" @@ -272,6 +310,113 @@ dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "async-channel" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf46fee83e5ccffc220104713af3292ff9bc7c64c7de289f66dae8e38d826833" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-executor" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" +dependencies = [ + "async-lock", + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" +dependencies = [ + "async-channel", + "async-executor", + "async-io", + "async-lock", + "blocking", + "futures-lite", + "once_cell", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite", + "log", + "parking", + "polling", + "rustix", + "slab", + "socket2", + "waker-fn", +] + +[[package]] +name = "async-lock" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa24f727524730b077666307f2734b4a1a1c57acb79193127dcc8914d5242dd7" +dependencies = [ + "event-listener", +] + +[[package]] +name = "async-std" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +dependencies = [ + "async-channel", + "async-global-executor", + "async-io", + "async-lock", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-task" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" + +[[package]] +name = "atomic-waker" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" + [[package]] name = "autocfg" version = "1.1.0" @@ -299,6 +444,21 @@ dependencies = [ "generic-array", ] +[[package]] +name = "blocking" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" +dependencies = [ + "async-channel", + "async-lock", + "async-task", + "atomic-waker", + "fastrand", + "futures-lite", + "log", +] + [[package]] name = "brotli" version = "3.3.4" @@ -356,6 +516,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "concurrent-queue" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -436,6 +605,51 @@ dependencies = [ "typenum", ] +[[package]] +name = "ctor" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -502,6 +716,12 @@ dependencies = [ "libc", ] +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + [[package]] name = "fastrand" version = "1.9.0" @@ -551,6 +771,21 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.28" @@ -558,6 +793,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -566,6 +802,49 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-macro" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + [[package]] name = "futures-sink" version = "0.3.28" @@ -584,10 +863,16 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ + "futures-channel", "futures-core", + "futures-io", + "futures-macro", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", + "slab", ] [[package]] @@ -611,6 +896,18 @@ dependencies = [ "wasi", ] +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "h2" version = "0.3.19" @@ -728,6 +1025,12 @@ dependencies = [ "tokio-native-tls", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.3.0" @@ -810,6 +1113,15 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + [[package]] name = "language-tags" version = "0.3.2" @@ -869,6 +1181,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", + "value-bag", ] [[package]] @@ -1010,6 +1323,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "parking" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" + [[package]] name = "parking_lot" version = "0.12.1" @@ -1033,6 +1352,12 @@ dependencies = [ "windows-sys 0.45.0", ] +[[package]] +name = "parse-size" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "944553dd59c802559559161f9816429058b869003836120e262e8caec061b7ae" + [[package]] name = "paste" version = "1.0.12" @@ -1063,6 +1388,22 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys 0.48.0", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1280,6 +1621,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_plain" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6018081315db179d0ce57b1fe4b62a12a0028c9cf9bbef868c9cf477b3c34ae" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1343,6 +1693,12 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "syn" version = "1.0.109" @@ -1392,9 +1748,13 @@ name = "tfcconnection" version = "0.1.0" dependencies = [ "actix", + "actix-multipart", "actix-rt", "actix-web", + "async-std", "env_logger", + "futures", + "futures-util", "multer", "reqwest", "serde", @@ -1564,6 +1924,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "value-bag" +version = "1.0.0-alpha.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55" +dependencies = [ + "ctor", + "version_check", +] + [[package]] name = "vcpkg" version = "0.2.15" @@ -1576,6 +1946,12 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + [[package]] name = "want" version = "0.3.0" diff --git a/Cargo.toml b/Cargo.toml index 6624faa..d3221ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,3 +14,7 @@ env_logger = "0.10.0" reqwest = { version = "0.11.18", features = ["json", "multipart"] } serde = "1.0.163" serde_json = "1.0.96" +async-std = "1.12.0" +actix-multipart = "0.6.0" +futures = "0.3.28" +futures-util = "0.3.28" diff --git a/src/main.rs b/src/main.rs index 67c3a5f..f5050c2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,21 @@ +use actix_multipart::{ + form::{ + tempfile::{TempFile, TempFileConfig}, + MultipartForm, + }, + Multipart, +}; +use actix_web::{middleware, post, web, App, Error, HttpResponse, HttpServer, Result}; +// use serde::Deserialize; +use futures_util::StreamExt as _; use std::{env, io}; -use actix_web::{middleware, web, App, HttpServer, get, post, Responder, http::header::ContentType, HttpResponse, HttpRequest, http::{StatusCode, Method}, HttpMessage}; -use multer::Multipart; + +// #[derive(Debug, MultipartForm)] +// struct HealthForm { +// firstname: String, +// lastname: String, +// birthdate: String, +// } #[actix_web::main] async fn main() -> io::Result<()> { @@ -9,22 +24,55 @@ async fn main() -> io::Result<()> { HttpServer::new(|| { App::new() - // enable logger - always register actix-web Logger middleware last + // enable logger - always register actix-web Logger middleware last .wrap(middleware::Logger::default()) - // register HTTP requests handlers + .app_data(web::FormConfig::default().limit(1048576)) + // register HTTP requests handlers .service(form) }) - .bind("0.0.0.0:4242")? - .run() - .await + .bind("0.0.0.0:4242")? + .run() + .await } #[post("/health-form")] -async fn form(req: HttpRequest) -> HttpResponse { - println!("{req:?}"); - println!("{:?}", req.content_type()); - println!("{:?}", req); - println!("{:?}", req.headers().get("content-type")); - // let multipart = Multipart::new(stream, boundary); - HttpResponse::Ok().respond_to(&req) +async fn form(mut form: Multipart) -> Result { + // println!("{form:?}"); + while let Some(item) = form.next().await { + let mut field = item?; + // let mut value = ""; + let name = field.name(); + let content_type = field.content_type().unwrap().to_string(); + if content_type == "application/octet-stream" { + // Handle file field + // You can save the file or process its contents here + while let Some(chunk) = field.try_next().await? { + // Process file chunk + } + } else { + // Handle other field types (e.g., text fields) + let field_value = field + .try_next() + .await? + .expect("Field value not found") + .to_utf8() + .expect("Failed to decode field value as UTF-8"); + + // Process the field value (e.g., store in a database, perform validation, etc.) + println!("Field {}: {}", name, field_value); + } + // while let Some(chunk) = field.try_next().await { + // let value = std::str::from_utf8(&chunk?).unwrap(); + // println!("{:?}: {:?}", name, value); + // } + } + Ok(HttpResponse::Ok().into()) +} + +fn get_boundary(s: &str) -> &str { + if let Some(index) = s.find("=") { + &s[(index + 1)..] + } else { + s + } } diff --git a/src/server/ChristianChad.png b/src/server/ChristianChad.png new file mode 100644 index 0000000..579a686 Binary files /dev/null and b/src/server/ChristianChad.png differ diff --git a/src/server/main.lisp b/src/server/main.lisp index a8c37aa..9cd04c6 100644 --- a/src/server/main.lisp +++ b/src/server/main.lisp @@ -1,23 +1,19 @@ (load "~/quicklisp/setup.lisp") -(ql:quickload :hunchentoot) -(ql:quickload :clack) -(ql:quickload :drakma) -(ql:quickload :com.inuoe.jzon) -(ql:quickload :rfc2388) +(ql:quickload '(hunchentoot clack dexador com.inuoe.jzon serapeum)) (uiop:define-package tfc-server - (:use :cl :hunchentoot :com.inuoe.jzon :clack)) + (:use :cl :uiop :com.inuoe.jzon :clack)) (in-package :tfc-server) -(defun handler (env) '(200 nil ("Hello World, bleh!"))) +;; (defun handler (env) '(200 nil ("Hello World, bleh!"))) -(clack:stop (clack:clackup (lambda (env) - '(200 nil ("Hello, World!"))) -(clack.handler:stop *clack-server*) +;; (clack:stop (clack:clackup (lambda (env) +;; '(200 nil ("Hello, World!"))) +;; (clack.handler:stop *clack-server*) -(defparameter *clack-server* (clack:clackup (lambda (env) - (funcall 'handler env)))) +;; (defparameter *clack-server* (clack:clackup (lambda (env) +;; (funcall 'handler env)))) (hunchentoot:start (make-instance 'hunchentoot:easy-acceptor :port 4242)) @@ -26,6 +22,8 @@ (setf (hunchentoot:content-type*) "text/plain") (format nil "Hey~@[ ~A~]!" name)) +(setf hunchentoot:*default-connection-timeout* 160) + (hunchentoot:define-easy-handler (respond :uri "/health-form") () (setf (hunchentoot:content-type*) "application/json") (let ((request-type (hunchentoot:request-method hunchentoot:*request*))) @@ -36,23 +34,95 @@ (setq *stream* (hunchentoot::content-stream hunchentoot:*request*)) (let* ((stream (hunchentoot::content-stream hunchentoot:*request*)) (data (hunchentoot::get-post-data :request *last*)) + (content-type (hunchentoot:header-in "content-type" *last*)) + (boundary (let ((position (position #\= content-type))) + (when position + (subseq content-type (1+ position))))) + (string-data (flexi-streams:octets-to-string data)) + (parts (ppcre:split boundary string-data)) + ;; (multipart-parser (fast-http:make-multipart-parser content-type + ;; (lambda (field-name field-headers field-metadata field-body-bytes) + ;; (uiop:println field-name) + ;; (uiop:println field-headers) + ;; (uiop:println field-metadata) + ;; (uiop:println field-body-bytes) + ;; ))) ) - (uiop:println (sb-sys:fd-stream-fd stream)) - (uiop:println (open-stream-p stream)) - (uiop:println (write-byte 8 stream)) - ;; (uiop:println (flex:octets-to-string data)) - ;; (let* ((header (rfc2388:parse-header "multipart/form-data" :value)) - ;; (boundary (or (assoc "boundary" (rfc2388:header-parameters header) - ;; :test #'string-equal) - ;; (error "Form data is missing a boundary: ~S" - ;; "multipart/form-data")))) - ;; (uiop:println (rfc2388:parse-mime data boundary))) - ;; ) + ;; (uiop:println (fast-http:http-multipart-parse multipart-parser (lambda (field-name field-headers field-metadata field-body-bytes) + ;; (uiop:println field-name) + ;; (uiop:println field-headers) + ;; (uiop:println field-metadata) + ;; (uiop:println field-body-bytes) + ;; ) string-data)) + ;; (println multipart-parser) + (println content-type) + (println boundary) + ;; (println string-data) + (setq *last-data* parts) + (uiop:println (hunchentoot::parse-multipart-form-data *last* *utf-8-external-format*)) - (uiop:println "OTHER") - (uiop:println (hunchentoot::parse-multipart-form-data *last* *hunchentoot-default-external-format*)) - ;; (uiop:println (hunchentoot::headers-in *last*)) + (loop :for i :in *last-data* + :do (let* ((content-disposition (nth 1 + (serapeum:lines i :eol-style :cr :honor-crlf t))) + (start (if content-disposition (position #\" content-disposition))) + (end (if start (position #\" content-disposition :start (1+ start)) nil)) + (name (if end (if start (subseq content-disposition (1+ start) end) nil) nil)) + (content (if (string= name "image") + (rest (rest (rest + (serapeum:lines i :eol-style :cr :honor-crlf t)))) + (nth 3 (serapeum:lines i :eol-style :cr :honor-crlf t)))) + (image-content-type (if (string= name "image") (nth 2 (serapeum:lines i :eol-style :cr :honor-crlf t)))) + (file-start (if (string= name "image") (position #\" content-disposition :start 44))) + (file-end (if file-start (position #\" content-disposition :start (1+ file-start)) nil)) + (image-file-name (if (string= name "image") (subseq content-disposition (1+ file-start) file-end) nil)) + (image-stream (if (string= name "image") (open image-file-name + :direction :output + :if-does-not-exist :create + :if-exists :overwrite)))) + ;; This gets rid of beginning and ending NIL values + ;; (if name (if (string/= name "image") (format t "~&~A: ~A" name content)) nil) + + (if (string= name "image") (setq content (butlast content))) + ;; (uiop:println image-content-type) + ;; (uiop:println content) + ;; (uiop:println (string= "" image-file-name)) + + (if (string/= "" image-file-name) + (if (string= name "image") + (with-open-file (image-stream (pathname (truename image-file-name)) + :direction :output + :element-type '(unsigned-byte 8) + :if-exists :overwrite + :if-does-not-exist :create) + (write-sequence (flex:string-to-octets (write-to-string content)) image-stream)))) + ;; (if (string= name "image") (format t "~A" (pathname (truename image-file-name)))) + + ;; (if (string= name "image") (setq file-path (serapeum:write-stream-into-file + ;; *image-stream* + ;; (pathname (truename image-file-name)) + ;; :if-exists :overwrite + ;; :if-does-not-exist :create))) + ;; (if (string= name "image") (format t "~&~A:~A" name content)) + )) + + + + ;; This actually worked, but the ending is wrong + ;; (loop :for i :in *last-data* + ;; :do (let* ((content (nth 1 + ;; (serapeum:lines i :eol-style :cr :honor-crlf t))) + ;; (start (position #\" content)) + ;; (end (position #\" content :from-end t)) + ;; (name (if start (subseq content (1+ start) end) nil))) + ;; (uiop:println name))) + + + + + + + ;; (uiop:println "OTHER") ;; (uiop:println (hunchentoot::get-request-data stream)) ;; (uiop:println (rfc2388:parse-mime data boundary)) ;; (let* ((data (hunchentoot:raw-post-data :force-text t)) @@ -66,11 +136,13 @@ ;; data) ))))) + (defun display-stream (stream) (loop for line = (read-line stream nil) while line do (format t "~A~%" line))) (defvar *last*) +(defvar *last-data*) (defvar *stream*) (defvar *token* "boFFRM68vvXbO-DO7S9YDg86lHX027-hd07mn0dh")