--- layout: doc title: HTTP server ---
The server uses an event-driven, non-blocking I/O model that makes it lightweight and scalable. It's written to conform to the standard Clojure web server Ring spec, with asynchronous and websocket extenstion. HTTP Kit is (almost) drop-in replacement of ring-jetty-adapter
A new unified Async/Websocket API(working in progress)
run-server
starts a Ring-compatible HTTP server, routing using compojure
:ip
: which IP to bind, default to 0.0.0.0
:port
: which port listens incomming request, default to 8090:thread
: How many threads to compute response from request, default to 4:worker-name-prefix
: woker thread name prefix, default to worker-
: worker-1
worker-2
....:queue-size
: max requests queued waiting for threadpool to compute response before reject, 503(Service Unavailable) is returned to client if queue is full, default to 20K:max-body
: length limit for request body in bytes, 413(Request Entity Too Large) is returned if exceeds this limit, default to 8388608(8M):max-line
: length limit for HTTP inital line and per header,
414(Request-URI Too Long) will be returned if exceeds this limit, default to 4096(4K),
relevant discusstion on stackoverflowif-ws-request
or when-ws-request
: get the websocket connection, returns websocket handshake
on-mesg
: register a fn to be called when there is string message from clientsend-mesg
: send string message to client. Clojure data can be converted to string using
JSON or ednclose-conn
: close the websocket connectionon-close
: register a fn to be called when the connecton is closedFor WebSocket Secure connection, one option is stud (self-signed certificate may not work with websocket)
A realtime chart example: https://github.com/http-kit/chat-websocket
{% highlight clojure %} (defn chat-handler [req] (when-ws-request req ws-con ; ws-con bind to the websocket connection (on-mesg ws-con (fn [msg] (send-mesg ws-con msg) ;; echo back (close-conn ws-con))) ;; close the connection (on-close ws-con (fn [status] (println ws-con "closed"))))) (run-server chat-handler {:port 8080}) {% endhighlight %}respond
accept a standard ring-response (:status :headers :body) or just the :body
All request-level middlewares applied to req
before passing to aync-handler
(like any other handler)
The response is sent to client without response-level middlewares applied (a limitation, suggestions welcome)
Optional timeout facilities: timer
A realtime chart example: https://github.com/http-kit/chat-polling
{% highlight clojure %} (defn async-handler [req] ; respond is a one-time function, can be called on any thread to send the response to client (async-response respond ; just :body, can also be {:status _ :headers _ :body _} (future (respond "hello world async")))) (run-server async-handler {:port 8080}) {% endhighlight %}Compojure Can be used to do the routing, based on uri and method
{% highlight clojure %} (:use [compojure.route :only [files not-found]] [compojure.handler :only [site]] ; form, query params decode; cookie; session, etc [compojure.core :only [defroutes GET POST DELETE ANY context]] org.httpkit.server) (defn show-landing-page [req] ;; ordinary clojure function, accept request map ;; return landing page's html string. possible template library: ;; mustache (https://github.com/shenfeng/mustache.clj, https://github.com/fhd/clostache...) ;; enlive (https://github.com/cgrand/enlive), hiccup(https://github.com/weavejester/hiccup) ) (defn update-userinfo [req] ;; ordinary clojure function (let [user-id (-> req :params :id) ; param from uri password (-> req :params :password)] ; form param .... )) (defroutes all-routes (GET "/" [] show-landing-page) (GET "/ws" [] chat-handler) ;; websocket (GET "/async" [] async-handler) ;; asynchronous(long polling) (context "/user/:id" [] (GET / [] get-user-by-id) (POST / [] update-userinfo)) (route/files "/static/") ;; static file url prefix /static, in `public` folder (route/not-found "Page not found.
")) ;; all other, return 404 (run-server (site #'all-routes) {:port 8080}) {% endhighlight %}http-kit runs alone happly, handy for development and quick deployment. Use reverse proxy like Nginx, Lighthttpd, etc in serious production is encouraged. They also add https support.
Sample Nginx configration:
{% highlight sh %} upstream http_backend { server 127.0.0.1:8090; # http-kit listen on 8090 # keepalive(resue TCP connection) improves performance keepalive 32; # both http-kit and nginx are good at concurrency } server { location /static/ { # static content alias /var/www/xxxx/public/; } location / { proxy_pass http://http_backend; # tell http-kit to keep the connection proxy_http_version 1.1; proxy_set_header Connection ""; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; access_log /var/log/nginx/xxxx.access.log; } } {% endhighlight %}