InputStream到Clojure Ring映射

时间:2018-08-20 21:10:30

标签: clojure ring

我看到当Web浏览器连接到HTTP服务器时,将发送以下行:

GET / HTTP/1.1
Content-Length: 13

Hello, world!

我想编写一个程序,它使用一个InputStream,读取这些行并根据ring specification返回一个Ring请求映射。

您可以为此建议一个Clojure库吗?我快速浏览了具有环支持的Web服务器源代码(例如http-kit),但到目前为止没有成功。

3 个答案:

答案 0 :(得分:3)

如果您正在寻找一个将文本HTTP输入转换为Ring请求映射的库,请仅搜索Ring,即同时处理HTTP 生成Ring请求映射的首屈一指的库。

>

答案 1 :(得分:2)

这肯定可以通过http-kit库实现。但是有两个问题:

  1. org.httpkit.server.ClojureRing是私有的。您必须通过反射访问其方法。
  2. :remote-addr值是从分配给请求的InetSocketAddress对象中读取的,或者您需要在请求字符串中包含X-Forwarded-For标头。

这里正在演示:

(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}

答案 2 :(得分:-1)

您可能希望阅读online here或更高版本的Clojure Cookbook。

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 ""}

更新-几乎不需要解析。您可以使用非常简单的地图生成振铃响应:

(defn respond-hello [request]  ; we ignore the request 
  {:status 200 :body "Hello, world!"})

不确定在这里之后的真实情况吗?如果您真的想从头开始进行解析,请the best option is Instaparse