                              (assoc memo (keyword k) (str/trim v))))
                       (sorted-map) headers)}))
 
+(defn compose [lines]
+  (reduce
+    (fn [res, el] (str/join (list res el "\r\n")))
+    lines))
+
+(defmulti generate-response (fn [code _] code))
+(defmethod generate-response :404 [_ _]
+  (let [page-content "<h1>404 Not Found</h1>"]
+    (compose
+      (list
+        "HTTP/1.1 404 Not Found"
+        "Content-Type: text/html; charset=utf-8"
+        (format "content-length: %s" (count page-content))
+        ""
+        page-content))))
+
+(defmethod generate-response :200 [_ res-as-string]
+  (compose (list
+             "HTTP/1.1 200 OK"
+             "content-type: text/html; charset=utf-8"
+             (format "content-length: %s" (count res-as-string))
+             ""
+             res-as-string)))
+
 (defn run-server [port]
   (println (format "server accepting request on %s" port))
   (loop [server (new ServerSocket port)]

            in (new BufferedReader (new InputStreamReader (.getInputStream socket)))]
        (let [lines (consume-buffer in)]
          (if (not (empty? lines))
            (let [request (parse-request lines)]
              (pp/pprint request)
              (let [[_ & relative] ((request :request-line) :uri)]
                (if (and (not (empty? relative)) (fs/exists? (str/join relative)))
                  (.println out (generate-response :200 (slurp(str/join relative))))
                  (.println out (generate-response :404 nil)))))
            (.println out (generate-response :404 nil)))
          (.flush out)
          (.close out)
          (.close in)
          (.close socket)
          (recur server))))))


