【问题标题】:InputStream to Clojure Ring mapInputStream 到 Clojure 环映射
【发布时间】:2018-08-20 21:10:30
【问题描述】:

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

GET / HTTP/1.1
Content-Length: 13

Hello, world!

我想写一个程序,接受InputStream,读取这些行并根据ring specification返回一个环请求映射。

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

【问题讨论】:

  • 顺便说一句,这是一个非常奇怪的 HTTP 请求。带有正文的 GET 显然不是非法的,但服务器应该会忽略正文。

标签: clojure ring


【解决方案1】:

如果您正在寻找将文本 HTTP 输入转换为 Ring 请求映射的库,请搜索 Ring,这是处理 HTTP 生成 Ring 请求映射的首选库。 p>

【讨论】:

  • 能否请您告诉我 Ring 的哪一部分处理解析文本 http?
  • 将文本发送到进程中的 Ring/Jetty 网络服务器,并使用为您提供请求映射的处理程序。这可能看起来有点间接,但听起来比尝试重新实现 HTTP 解析以及 Ring 和 Jetty 那样容易出错。
  • 我担心将请求发送到码头网络服务器是放弃解析流的繁重方式。
【解决方案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}

【讨论】:

    【解决方案3】:

    您可能希望查看 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 ""}
    

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

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

    不确定您在这里的真正目的是什么.....?如果你真的想从头开始解析,the best option is Instaparse

    【讨论】:

    • 我已经知道环形地图的样子了,谢谢。但是,我很难将 InputStream 解析为环形映射。您对 Pedestal 的哪一部分可以用于解析有什么建议吗?
    • 你的最后一个链接坏了!
    猜你喜欢
    • 1970-01-01
    • 2023-03-15
    • 2014-04-08
    • 1970-01-01
    • 2015-08-02
    • 2012-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多