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