updates to attempt at common lisp server

This commit is contained in:
Chris Cochrun 2023-05-30 09:29:35 -05:00
parent d8740cdb73
commit 0cad38bb05
6 changed files with 543 additions and 42 deletions

View file

@ -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"))))

376
Cargo.lock generated
View file

@ -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"

View file

@ -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"

View file

@ -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<()> {
@ -11,6 +26,7 @@ async fn main() -> io::Result<()> {
App::new()
// enable logger - always register actix-web Logger middleware last
.wrap(middleware::Logger::default())
.app_data(web::FormConfig::default().limit(1048576))
// register HTTP requests handlers
.service(form)
})
@ -20,11 +36,43 @@ async fn main() -> io::Result<()> {
}
#[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<HttpResponse, Error> {
// 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
}
}

Binary file not shown.

View file

@ -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")