【问题标题】:How to read body of http POST request in Erlang如何在 Erlang 中读取 http POST 请求的正文
【发布时间】:2019-11-30 06:06:33
【问题描述】:

我正在用 Erlang 开发一个服务器实现,它有一个处理 HTTP 请求的接收循环。打开侦听套接字并生成接受器后,服务器已准备好接收连接。 TLS 握手完成,客户端连接到服务器并开始发送 HTTPS 请求。

服务器的接收部分使用ssl:recv/2 读取传入的请求,并且设置了套接字,以便数据包采用HttpPacket 的形式。到目前为止,“GET”请求的处理工作正常,但我需要包含“POST”请求。读取“POST”请求也可以,但我似乎无法读取请求的正文。

  1. 我应该如何阅读传入请求的正文?
  2. 可以用ssl:recv/2阅读吗?
  3. 套接字应该期待或格式化不同格式的数据吗?
  4. 您能推荐其他的吗?

我尝试过使用ssl:recv/2 和常规receive。使用receive 会冻结服务器直到超时。

case ssl:recv(Tls_socket, 0) of
    {ok, {http_request, 'POST', Data, Vsn}} ->
        do_something ...

数据最终为{abs_path, <<"/example/ex">>}。我希望数据是请求的主体。


我无法读取数据,因为套接字被设置为将数据打包为HttpPacket(即any())。不打包读取有帮助,所以剩下要做的就是解析查询。

【问题讨论】:

    标签: http post request erlang


    【解决方案1】:

    Erlang 内置的 HTTP 解析器一次解析一行。所以首先你会打电话给ssl:recv,然后收到{http_request, 'POST', Path, Vsn},就像你上面的例子一样。这对应于 HTTP 请求中的 POST /example/ex HTTP/1.1 行。然后你会一遍又一遍地调用ssl:recv,接收{http_header, _, Field, _, Value},请求中的每个标头一个,直到它返回http_eoh,意思是“标头结束”。

    此时,您应该已经收到了Content-Length 标头,因此您知道要从套接字读取多少字节。将套接字切换到“原始”模式(与 HTTP 模式相反):

    ssl:setopts(Tls_socket, [{packet, raw}]),
    

    并接收你需要的字节数:

    {ok, RequestBody} = ssl:recv(Tls_socket, ContentLength),
    

    并发送响应。

    如果您想在同一个套接字上接收另一个 HTTP 请求,请将其切换回 HTTP 模式:

    ssl:setopts(Tls_socket, [{packet, http}]),
    

    您提到了receive 超时。这取决于套接字是处于“主动”还是“被动”模式。在“被动”模式下,您需要调用ssl:recv来接收数据,而在“主动”模式下,传入的数据将作为消息发送到拥有套接字的进程。

    您可以通过传递选项{active, true} 来打开活动模式,但这会冒着您的进程接收传入数据的速度超过其处理速度的风险。通常你会设置选项{active, once},这意味着套接字向进程发送一个消息然后恢复到被动模式,需要你再次设置选项{active, once}才能接收更多数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-04
      • 2023-04-07
      • 2014-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-02
      相关资源
      最近更新 更多