-
Notifications
You must be signed in to change notification settings - Fork 1
一些概念
对于Ring来说,一个web应用开发包含四个组件(components):
- 处理器(Handler)
- 请求(Request)
- 响应(Response)
- 中间件(Middleware)
处理器就是一些函数,定义我们的web应用.它们接收一个参数,一个代表着一个HTTP请求的map,然后返回一个代表着HTTP响应的map.
让我们来看一个例子:
(defn what-is-my-ip [request]
{:status 200
:headers {"Content-Type" "text/plain"}
:body (:remote-addr request)})
这个函数返回了一个map,Ring可以把它转化成一个HTTP响应.响应返回一个纯文本文件,它包含的IP地址被用来访问web应用。
处理函数之后将会被各种不同的方法转换成一个web应用,这些将会在下一节被介绍.
正如前面提到的,HTTP请求通过Clojure maps表现出来.这里有一些将会一直存在的标准keys,但是请求可以(经常会)包含自定义的keys,自定义的keys通过中间件(middleware)被添加.
这些标准的keys有:
-
:server-port
服务器端口. -
:server-name
解析后的服务器名称,或者服务器IP地址. -
:remote-addr
客户端的IP地址,或者发送请求的最后代理 -
:uri
请求URI(域名之后的完整路径). -
:query-string
查询字符串,如果存在的话. -
:scheme
传输协议,:http
或:https
. -
:request-method
HTTP请求方法,:get
,:head
,:options
,:put
,:post
, 或者:delete
中的一个. -
:headers
包含在一个Clojure map中的相应的头部值的字符串,需要小写表示 -
:body
对于请求body的一个输入流,如果需要的话.
Ring以前的版本也有下列keys.它们现在是被弃用的.
-
:content-type
The MIME type of the request body, if known. -
:content-length
The number of bytes in the request body, if known. -
:character-encoding
The name of the character encoding used in the request body, if known.
响应map通过处理器(handler)被创建,包含三种keys
-
:status
HTTP状态码,例如200, 302, 404等. -
:headers
一个Clojure map里面存放着header names到header values.这些值要么是字符串,在这种情况下一个name/value header将会被发送到HTTP响应,或者是一个字符串的集合,这种情况下一个name/value header将会对每个值发送. -
:body
响应body的一种表示,如果一个响应body适合响应状态码.body可以是四种类型之一:-
String
body直接被发送到客户端. -
ISeq
序列(seq)中的每一个元素被当做一个字符串发送到客户端. -
File
被引用文件的内容发送给客户端. -
InputStream
将流的内容发送到客户端.当流耗尽的时候,会被关闭.
-
中间件是高层函数为了添加额外的功能到处理器(handler).中间件的第一个参数应该是一个handler,然后它的返回值应该是一个新的处理器函数,这个函数将会调用原始的处理器.
这里有一个例子:
(defn wrap-content-type [handler content-type]
(fn [request]
(let [response (handler request)]
(assoc-in response [:headers "Content-Type"] content-type))))
这个中间件函数通过处理器,添加了一个"Content-type"头到每个响应.
包装这个中间件到一个处理器上:
(def app
(wrap-content-type handler "text/html"))
这里定义了一个新的处理器,app
包含中间件wrap-content-type
包装过的处理器handler
.
线程化的宏(->
)可以使中间件连接在一起:
(def app
(-> handler
(wrap-content-type "text/html")
(wrap-keyword-params)
(wrap-params)))
中间件经常使用在Ring中,而且用于提供更多的功能,除了处理原始的HTTP请求之外.在Ring标准库中,参数,会话和文件上传全部是通过中间件被处理的.