updates to attempt at common lisp server
This commit is contained in:
parent
d8740cdb73
commit
0cad38bb05
6 changed files with 543 additions and 42 deletions
76
src/main.rs
76
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<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
|
||||
}
|
||||
}
|
||||
|
|
BIN
src/server/ChristianChad.png
Normal file
BIN
src/server/ChristianChad.png
Normal file
Binary file not shown.
|
@ -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")
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue