如何读取 HTTP 分块响应并将分块响应发送到 Elixir 中的客户端?
How to read an HTTP chunked response and send chunked response to client in Elixir?
我正在使用 Elixir/Phoenix 并且我有一个端点 returns 分块响应,比如永无止境的日志行流。然而,日志行来自另一个服务 A,它也是 returns 分块响应。我希望我的端点读取来自服务 A 的分块响应,并将它们也分块传递给客户端。本质上,它只是服务A的代理,但是我不能让客户端直接连接到服务A,因为我需要进行一些认证。
以下是使用 Phoenix 发送块数据的示例:
def test_1(conn, _params) do
conn = conn
|> put_resp_content_type("text/event-stream")
|> send_chunked(200)
conn |> chunk("a")
conn |> chunk("b")
conn |> chunk("c")
# send data five times, once per second, to simulate a log
for n <- 1..5 do
conn |> chunk(Integer.to_string(n))
Process.sleep(1000)
end
conn
end
有一些 http 库可用于 Elixir/Erlang;我喜欢 HTTPoison
.
这是一个从 url 中读取块并在它们进入时发送它们的示例:
def test_2(conn, _params) do
url = "http://localhost:4000/test_1"
%HTTPoison.AsyncResponse{id: id} = HTTPoison.get!(url, %{}, stream_to: self())
conn = conn
|> put_resp_content_type("text/event-stream")
|> send_chunked(200)
process_httpoison_chunks(conn, id)
end
def process_httpoison_chunks(conn, id) do
receive do
%HTTPoison.AsyncStatus{id: ^id} ->
# TODO handle status
process_httpoison_chunks(conn, id)
%HTTPoison.AsyncHeaders{id: ^id, headers: %{"Connection" => "keep-alive"}} ->
# TODO handle headers
process_httpoison_chunks(conn, id)
%HTTPoison.AsyncChunk{id: ^id, chunk: chunk_data} ->
conn |> chunk(chunk_data)
process_httpoison_chunks(conn, id)
%HTTPoison.AsyncEnd{id: ^id} ->
conn
end
end
一些参考资料:
我正在使用 Elixir/Phoenix 并且我有一个端点 returns 分块响应,比如永无止境的日志行流。然而,日志行来自另一个服务 A,它也是 returns 分块响应。我希望我的端点读取来自服务 A 的分块响应,并将它们也分块传递给客户端。本质上,它只是服务A的代理,但是我不能让客户端直接连接到服务A,因为我需要进行一些认证。
以下是使用 Phoenix 发送块数据的示例:
def test_1(conn, _params) do
conn = conn
|> put_resp_content_type("text/event-stream")
|> send_chunked(200)
conn |> chunk("a")
conn |> chunk("b")
conn |> chunk("c")
# send data five times, once per second, to simulate a log
for n <- 1..5 do
conn |> chunk(Integer.to_string(n))
Process.sleep(1000)
end
conn
end
有一些 http 库可用于 Elixir/Erlang;我喜欢 HTTPoison
.
这是一个从 url 中读取块并在它们进入时发送它们的示例:
def test_2(conn, _params) do
url = "http://localhost:4000/test_1"
%HTTPoison.AsyncResponse{id: id} = HTTPoison.get!(url, %{}, stream_to: self())
conn = conn
|> put_resp_content_type("text/event-stream")
|> send_chunked(200)
process_httpoison_chunks(conn, id)
end
def process_httpoison_chunks(conn, id) do
receive do
%HTTPoison.AsyncStatus{id: ^id} ->
# TODO handle status
process_httpoison_chunks(conn, id)
%HTTPoison.AsyncHeaders{id: ^id, headers: %{"Connection" => "keep-alive"}} ->
# TODO handle headers
process_httpoison_chunks(conn, id)
%HTTPoison.AsyncChunk{id: ^id, chunk: chunk_data} ->
conn |> chunk(chunk_data)
process_httpoison_chunks(conn, id)
%HTTPoison.AsyncEnd{id: ^id} ->
conn
end
end
一些参考资料: