basic http server

This commit is contained in:
2025-05-07 17:13:30 -07:00
parent d70f0113c1
commit ae66d51f22
7 changed files with 302 additions and 0 deletions

View File

@ -0,0 +1,2 @@
(import http-utils.request)
(import http-utils.response)

57
srv/http_utils/request.hy Normal file
View File

@ -0,0 +1,57 @@
(import hyrule.collections [assoc])
(require hyrule.control [branch])
(require hyrule.argmove [doto])
(require hyrule.collections :readers [s])
(import urllib.parse [urlsplit unquote-plus parse-qs])
(defn parse-url-encoded [query]
(dfor pair (.items (parse-qs (unquote-plus query) :keep-blank-values True))
(get pair 0)
(cond
(get pair 1 0) (get pair 1 0)
True "")))
(defn parse-data [data]
(setv request {})
(setv [head #* body] (.split data b"\r\n\r\n"))
(setv [request-line #* headers] (.split head b"\r\n"))
(setv [http-method route http-version] (.split (.decode request-line "utf-8") " "))
(doto request
(assoc :method http-method)
(assoc :route (let
[[_ _ path query _] (urlsplit route)]
(dict
:path (.join "/"
(do
(setv segments [])
(for [segment (.split (unquote-plus path) "/")]
(cond
(!= segment "..") (.append segments segment)
(and segments (!= (get segments -1) "..")) (.pop segments)))
segments))
:parameters (parse-url-encoded query))))
(assoc :version http-version)
(assoc :headers (dict
(dfor header
(map (fn [x]
(.split (.decode x "utf-8") ": ")) headers)
(get header 0)
(get header 1))))
(assoc :body (branch (in it (. request (get "headers") (get "Content-Type" "")))
"application/x-www-form-urlencoded" (parse-url-encoded (.decode (.join b"\n" body) "utf-8"))
"" ""
;;"multipart/form-data" ;(do
;; (setv content-type-header (. request (get "headers") (get "Content-Type")))
;; (when (in "=" content-type-header) (do
;; (setv boundary (get (.split content-type-header "=") -1))
;; (print "boundary" boundary)
;; (print (.split (.join b"\n" body) (.encode boundary "utf-8"))))))
else (raise (NotImplementedError f"{(get (.split (. request (get "headers") (get "Content-Type")) ";") 0)} parsing is TODO"))))))

View File

@ -0,0 +1,26 @@
(import hyrule.collections [assoc])
(defn send-code [code]
(.encode f"HTTP/1.1 {code}\r\n" "utf-8"))
(defn send-headers [headers]
(.encode (+ (.join "\r\n" (lfor [k v] (.items headers) f"{k}: {v}")) "\r\n\r\n") "utf-8"))
(defn send-body [body]
(cond
(isinstance body bytes) body
(isinstance body str) (.encode body "utf-8")))
(defn send [[code 200] [headers None] [body ""]]
(when (is headers None)
(setv headers {}))
(assoc headers "WHAT...-your-trans-gener..." "that is so cool...")
(when (not-in "Content-Type" headers)
(assoc headers "Content-Type" "text/html"))
(+
(send-code code)
(send-headers headers)
(send-body body)))