代码之家  ›  专栏  ›  技术社区  ›  erdos

输入流到Clojure环图

  •  1
  • erdos  · 技术社区  · 8 年前

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

    GET / HTTP/1.1
    Content-Length: 13
    
    Hello, world!
    

    我想写一个程序 InputStream ,读取这些行并根据 ring specification .

    你能为此推荐一个Clojure图书馆吗?我快速查看了支持环的Web服务器源代码(例如 http-kit )但到目前为止还没有成功。

    3 回复  |  直到 8 年前
        1
  •  2
  •   Olim Saidov    8 年前

    这当然可以通过HTTP工具包库实现。但有两个问题:

    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
  •  3
  •   amalloy    8 年前

    如果您正在寻找一个库来将文本HTTP输入转换成一个环请求映射,那么只需搜索环,即处理HTTP的首要库。 生成环请求映射。

        3
  •  -1
  •   Alan Thompson    8 年前

    你可能想复习一下Clojure食谱, online here 或者更好的打印形式。

    Web development with Clojure 也是一本好书。

    我还有一个“你好世界” example using the Pedestal library here .


    以下是使用底座的请求地图示例:

    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 .

    推荐文章