(ns middleware-example (:use ring.adapter.jetty ring.middleware.params)) (defn handler [request] {:headers {} :status 200 :body (str "Hello word!" )}) (def app handler) ;; Start the server if it hasn't already been started (defonce server (ring.adapter.jetty/run-jetty #'app {:port 7071 :join? false}))
咱们看到,handler
会接收一个request参数,并返回一个hash-map,hash-map包括headers、status和body,这个hash-map就是一个response。
党咱们访问 http://localhost:7071/ ,就会看到 Hello word!html
(defn shout [handler] (fn [request] (let [response (handler request)] (update-in response [:body] clojure.string/upper-case)))) ;; 将response中的body转换成大写 (def app (-> handler shout))
当咱们刷新页面的时候,结果就变成了 HELLO WORD!
这个例子说明,咱们能够经过middleware改变response。web
咱们能够用middle更好的解析、处理request,请看下面的例子chrome
(ns middleware-example (:use ring.adapter.jetty ring.middleware.params)) (defn print-query-params [handler] (fn [request] (println "In print-query-params, the params is:" (:query-params request)) (handler request))) (defn handler [request] (println "In handler, the params is:" (:query-params request)) (let [name ((:query-params request) "name")] {:headers {} :status 200 :body (str "Hello " name "!")})) (def app (-> handler wrap-params print-query-params)) ;; Start the server if it hasn't already been started (defonce server (ring.adapter.jetty/run-jetty #'app {:port 7071 :join? false}))
访问 http://localhost:7071?name=mike 后,在console里咱们将看到express
In print-query-params, the params is: nil In handler, the params is: {name mike}
这段代码能够说明,params是被wrap-params
所解析出来的,request在创给wrap-params
、handler
前,先被传给了print-query-params
。浏览器
(在浏览器内,咱们实际上会看到两次输出,是由于浏览器在请求url的时候,还请求了favoicon,chrome每次刷新都是两个请求,而safari只有第一次请求了favoicon,以后刷新都没有再次请求)app
首先,咱们将handler这个参数传给middleware,这个middleware会返回一个方法,
这个方法会接收一个request
参数,咱们能够在这个方法里生成新的request
,并把这个request传给handler(handler new-request)
,获得返回后,咱们又能够对response
进行操做。框架
经过app的定义(-> handler wrap-params print-query-params)
,咱们知道,middleware就像洋葱皮同样,一层层包裹handler。koa
最后面的包裹在最外层,request一层层经过middleware,每一层均可以对request进行操做,最后handler 会根据最终的request生成response,而后response又一层层传出middleware,每一层middleware有有机会对生成的response作处理。ide
就像下图同样(注意,后面的middleware,处于最外层)。ui
rack也是使用同样的模型处理中间件。rack使用use
方法注册middleware,并将注册的middleware放入@use
这个实例变量里。
rack有一个to_app
的方法,在这个方法内@use.reverse.inject(app) { |a,e| e[a] }
,把最早注册的middleware放在最外层,并包裹好。
ring、rack、koa的middleware都是使用洋葱模型,但express的middleware却不同,middleware只是一层一层传下去的,好比要记录请求时间,就须要写两个中间件。
var app = express() app.use(function (req, res, next) { console.log('Time:', Date.now()) next() })
Middleware能够用来对response和request进行处理(好比解析params),也能够中断执行(好比过滤ip)等。
但须要注意middleware的顺序,最后的middleware被放在了最外层。最外层,最早处理request,最后处理response。
https://codenoble.com/blog/un...
https://expressjs.com/en/guid...
http://liujiacai.net/blog/201...