InputStream 到 Clojure Ring 映射
InputStream to Clojure Ring map
我看到当 Web 浏览器连接到 HTTP 服务器时,会发送以下行:
GET / HTTP/1.1
Content-Length: 13
Hello, world!
我想编写一个程序,它接受一个 InputStream
,读取这些行和 returns 根据 ring specification 的 Ring 请求映射。
能否为此推荐一个 Clojure 库?我快速查看了支持环的 Web 服务器源代码(例如 http-kit),但到目前为止没有成功。
您可能希望查看 Clojure Cookbook,online here,甚至更好的印刷形式。
Web development with Clojure也是本好书
我也有一个"Hello World"example using the Pedestal library here.
这是使用 Pedestal 的示例请求映射:
request =>
{:protocol "HTTP/1.1",
:async-supported? true,
:remote-addr "127.0.0.1",
:servlet-response
#object[io.pedestal.test$test_servlet_response$reify__34946 0x3e71aa38 "io.pedestal.test$test_servlet_response$reify__34946@3e71aa38"],
:servlet
#object[io.pedestal.http.servlet.FnServlet 0x7168112e "io.pedestal.http.servlet.FnServlet@7168112e"],
:headers {"content-length" "0", "content-type" ""},
:server-port -1,
:servlet-request
#object[io.pedestal.test$test_servlet_request$reify__34934 0x3422eca "io.pedestal.test$test_servlet_request$reify__34934@3422eca"],
:content-length 0,
:content-type "",
:path-info "/echo/abcdef/12345",
:character-encoding "UTF-8",
:url-for #<Delay@5190186c: :not-delivered>,
:uri "/echo/abcdef/12345",
:server-name nil,
:query-string nil,
:path-params {:list-id "abcdef", :item-id "12345"},
:body
#object[io.pedestal.test.proxy$javax.servlet.ServletInputStream$ff19274a 0x2aff7cc4 "io.pedestal.test.proxy$javax.servlet.ServletInputStream$ff19274a@2aff7cc4"],
:scheme nil,
:request-method :get,
:context-path ""}
Update - 几乎不需要解析。您可以使用非常简单的映射生成响铃响应:
(defn respond-hello [request] ; we ignore the request
{:status 200 :body "Hello, world!"})
不确定你真正想要的是什么......?如果你真的想从头开始解析,the best option is Instaparse.
如果您正在寻找一个将文本 HTTP 输入转换为 Ring 请求映射的库,那么搜索 Ring 就够了,它是处理 HTTP 和 生成 Ring 的首屈一指的库请求地图。
这肯定可以通过 http-kit 库来实现。但是有两个问题:
- class
org.httpkit.server.ClojureRing
是私有的。您必须通过反射访问它的方法。
:remote-addr
值是从分配给请求的 InetSocketAddress
object 中读取的,或者您需要在请求字符串中包含 X-Forwarded-For
header。
这是工作演示:
(let [request "POST / HTTP/1.1\nContent-Length: 13\nX-Forwarded-For: 127.0.0.1\n\nHello, world!"
bytes (java.nio.ByteBuffer/wrap (.getBytes request))
decoder (org.httpkit.server.HttpDecoder.
8388608 4096 ProxyProtocolOption/DISABLED)
method (.getMethod org.httpkit.server.ClojureRing
"buildRequestMap"
(into-array [org.httpkit.server.HttpRequest]))]
(.setAccessible method true)
(.invoke method nil (object-array [(.decode decoder bytes)])))
=>
{:remote-addr "127.0.0.1",
:headers {"content-length" "13", "x-forwarded-for" "127.0.0.1"},
:async-channel nil,
:server-port 80,
:content-length 13,
:websocket? false,
:content-type nil,
:character-encoding "utf8",
:uri "/",
:server-name nil,
:query-string nil,
:body #object[org.httpkit.BytesInputStream 0x4f078b2 "BytesInputStream[len=13]"],
:scheme :http,
:request-method :post}
我看到当 Web 浏览器连接到 HTTP 服务器时,会发送以下行:
GET / HTTP/1.1
Content-Length: 13
Hello, world!
我想编写一个程序,它接受一个 InputStream
,读取这些行和 returns 根据 ring specification 的 Ring 请求映射。
能否为此推荐一个 Clojure 库?我快速查看了支持环的 Web 服务器源代码(例如 http-kit),但到目前为止没有成功。
您可能希望查看 Clojure Cookbook,online here,甚至更好的印刷形式。
Web development with Clojure也是本好书
我也有一个"Hello World"example using the Pedestal library here.
这是使用 Pedestal 的示例请求映射:
request =>
{:protocol "HTTP/1.1",
:async-supported? true,
:remote-addr "127.0.0.1",
:servlet-response
#object[io.pedestal.test$test_servlet_response$reify__34946 0x3e71aa38 "io.pedestal.test$test_servlet_response$reify__34946@3e71aa38"],
:servlet
#object[io.pedestal.http.servlet.FnServlet 0x7168112e "io.pedestal.http.servlet.FnServlet@7168112e"],
:headers {"content-length" "0", "content-type" ""},
:server-port -1,
:servlet-request
#object[io.pedestal.test$test_servlet_request$reify__34934 0x3422eca "io.pedestal.test$test_servlet_request$reify__34934@3422eca"],
:content-length 0,
:content-type "",
:path-info "/echo/abcdef/12345",
:character-encoding "UTF-8",
:url-for #<Delay@5190186c: :not-delivered>,
:uri "/echo/abcdef/12345",
:server-name nil,
:query-string nil,
:path-params {:list-id "abcdef", :item-id "12345"},
:body
#object[io.pedestal.test.proxy$javax.servlet.ServletInputStream$ff19274a 0x2aff7cc4 "io.pedestal.test.proxy$javax.servlet.ServletInputStream$ff19274a@2aff7cc4"],
:scheme nil,
:request-method :get,
:context-path ""}
Update - 几乎不需要解析。您可以使用非常简单的映射生成响铃响应:
(defn respond-hello [request] ; we ignore the request
{:status 200 :body "Hello, world!"})
不确定你真正想要的是什么......?如果你真的想从头开始解析,the best option is Instaparse.
如果您正在寻找一个将文本 HTTP 输入转换为 Ring 请求映射的库,那么搜索 Ring 就够了,它是处理 HTTP 和 生成 Ring 的首屈一指的库请求地图。
这肯定可以通过 http-kit 库来实现。但是有两个问题:
- class
org.httpkit.server.ClojureRing
是私有的。您必须通过反射访问它的方法。 :remote-addr
值是从分配给请求的InetSocketAddress
object 中读取的,或者您需要在请求字符串中包含X-Forwarded-For
header。
这是工作演示:
(let [request "POST / HTTP/1.1\nContent-Length: 13\nX-Forwarded-For: 127.0.0.1\n\nHello, world!"
bytes (java.nio.ByteBuffer/wrap (.getBytes request))
decoder (org.httpkit.server.HttpDecoder.
8388608 4096 ProxyProtocolOption/DISABLED)
method (.getMethod org.httpkit.server.ClojureRing
"buildRequestMap"
(into-array [org.httpkit.server.HttpRequest]))]
(.setAccessible method true)
(.invoke method nil (object-array [(.decode decoder bytes)])))
=>
{:remote-addr "127.0.0.1",
:headers {"content-length" "13", "x-forwarded-for" "127.0.0.1"},
:async-channel nil,
:server-port 80,
:content-length 13,
:websocket? false,
:content-type nil,
:character-encoding "utf8",
:uri "/",
:server-name nil,
:query-string nil,
:body #object[org.httpkit.BytesInputStream 0x4f078b2 "BytesInputStream[len=13]"],
:scheme :http,
:request-method :post}