Created
January 17, 2016 07:10
-
-
Save redraiment/0222d1ca0a69fa50cd0f to your computer and use it in GitHub Desktop.
简易的HTTP服务器,用于检测各种HTTP Client对KeepAlive的支持
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns me.zzp.http | |
(:require [clojure.string :refer [blank?]]) | |
(:import java.io.PrintStream | |
java.net.ServerSocket | |
java.util.Scanner | |
java.util.concurrent.atomic.AtomicLong) | |
(:gen-class)) | |
(defonce generitor (AtomicLong.)) | |
(defn info [id message] | |
(println (format "[%d] %s" id message))) | |
(defn http-read-header [scanner] | |
(loop [content-length 0 | |
headers (StringBuilder.)] | |
(let [line (if (.hasNextLine scanner) (.nextLine scanner) "")] | |
(if (blank? line) | |
[content-length (.toString headers)] | |
(recur (if-let [[_ length] (re-matches #"Content-Length: (\d+)" line)] | |
(Long/parseLong length) | |
content-length) | |
(.. headers | |
(append "\n ") | |
(append line))))))) | |
(defn http-read [scanner] | |
(let [[length headers] (http-read-header scanner)] | |
(if (zero? length) | |
headers | |
(apply str headers "\n " | |
(for [_ (range length)] | |
(if (.hasNext scanner "(?s).") | |
(.next scanner "(?s).") | |
"")))))) | |
(defn http-write [stream message] | |
(. stream print | |
(format "HTTP/1.1 200 OK\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Length: %d\r\n\r\n%s" (alength (.getBytes message)) message))) | |
(defn process [logger client] | |
(logger "open") | |
(let [scanner (.useDelimiter (Scanner. (.getInputStream client)) "") | |
stream (PrintStream. (.getOutputStream client))] | |
(while (.hasNextLine scanner) | |
(logger "receive request") | |
(logger (http-read scanner)) | |
(logger "send response") | |
(http-write stream "OK") | |
(logger "done"))) | |
(.close client) | |
(logger "close")) | |
(defn -main [& args] | |
(let [server (ServerSocket. (int 8000))] | |
(println "server start @ 8000") | |
(loop [] | |
(let [client (.accept server)] | |
(future (process (partial info (.incrementAndGet generitor)) client)) | |
(recur))))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment