簡體   English   中英

如何使用Plug.Conn讀取phoenix控制器中的小塊數據

[英]How to read small chunks of data in phoenix controller, using Plug.Conn

我的目標是能夠在phoenix控制器中處理分塊的HTTP請求。 我認為解決方案是使用Plug.Conn.read_body但是我收到錯誤或超時。

目前我認為最好的解決方案是自定義解析器。

defmodule Plug.EventStreamParser do
  @behaviour Plug.Parsers
  alias Plug.Conn

  def parse(conn, "text", "event-stream", _headers, _opts) do
    Conn.read_body(conn, length: 2, read_length: 1, read_timeout: 1_000)
    |> IO.inspect
    {:ok, %{}, conn}
  end
end

但是我總是在檢查線上得到{:error :timeout}

Plug.Conn.read_body/2只讀取請求正文的一個塊。 您需要遞歸調用它才能讀取所有內容。 你也不需要編寫一個Parser來只讀塊(如果我正確理解你的問題,我認為Parser甚至不能這樣做); 如果請求的Content-Type不是默認情況下Plug解析的,則可以從控制器調用Plug.Conn.read_body/2

這是一個從控制器遞歸調用Plug.Conn.read_body/2的小實現:

defmodule MyApp.PageController do
  use MyApp.Web, :controller

  def index(conn, _params) do
    {:ok, conn} = read_body(conn, [length: 1024, read_length: 1024], fn chunk ->
      # We just print the size of each chunk we receive.
      IO.inspect byte_size(chunk)
    end)
    text conn, "ok"
  end

  def read_body(conn, opts, f) do
    case Plug.Conn.read_body(conn, opts) do
      {:ok, binary, conn} ->
        f.(binary)
        {:ok, conn}
      {:more, binary, conn} ->
        f.(binary)
        read_body(conn, opts, f)
      {:error, term} ->
        {:error, term}
    end
  end
end

這將以大約1024字節的塊的形式讀取正文(不能保證返回的二進制文件與請求的大小完全相同)。 使用以下請求POST 4000個字節:

$ head -c 4000 /dev/urandom | curl -XPOST http://localhost:4000 --data-binary @- -H 'Content-Type: application/vnd.me.raw'
ok

以下內容記錄到控制台:

[info] POST /
[debug] Processing by MyApp.PageController.index/2
  Parameters: %{}
  Pipelines: [:api]
1024
1024
1024
928
[info] Sent 200 in 3ms

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM