Skip to content

Commit 0cb4132

Browse files
authored
fix: Forward request headers onto sync backend (#107)
Fixes #105
1 parent 867ca80 commit 0cb4132

File tree

2 files changed

+71
-8
lines changed

2 files changed

+71
-8
lines changed

lib/phoenix/sync/electric/client_adapter.ex

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ defmodule Phoenix.Sync.Electric.ClientAdapter do
5151
defp live?(live), do: live == "true"
5252

5353
defp fetch_upstream(sync_client, conn, request, shape) do
54+
request = put_req_headers(request, conn.req_headers)
55+
5456
response =
5557
case Client.Fetch.request(sync_client.client, request) do
5658
%Client.Fetch.Response{} = response -> response
@@ -68,18 +70,33 @@ defmodule Phoenix.Sync.Electric.ClientAdapter do
6870
end
6971

7072
conn
71-
|> put_headers(response.headers)
73+
|> put_resp_headers(response.headers)
7274
|> Plug.Conn.send_resp(response.status, body)
7375
end
7476

75-
defp put_headers(conn, headers) do
76-
headers
77-
|> Map.delete("transfer-encoding")
78-
|> Enum.reduce(conn, fn {header, values}, conn ->
79-
Enum.reduce(values, conn, fn value, conn ->
80-
Plug.Conn.put_resp_header(conn, header, value)
77+
defp put_req_headers(request, headers) do
78+
merged_headers =
79+
Enum.reduce(headers, request.headers, fn {header, value}, acc ->
80+
Map.update(acc, header, [value], fn existing -> [value | List.wrap(existing)] end)
8181
end)
82-
end)
82+
|> expand_headers()
83+
84+
%{request | headers: merged_headers}
85+
end
86+
87+
defp put_resp_headers(conn, headers) do
88+
resp_headers =
89+
headers
90+
|> Map.delete("transfer-encoding")
91+
|> expand_headers()
92+
93+
Plug.Conn.merge_resp_headers(conn, resp_headers)
94+
end
95+
96+
# turn headers into a list which is more compatible than a map
97+
# representation as it preserves multiple values for a header.
98+
defp expand_headers(headers) when is_map(headers) do
99+
Enum.flat_map(headers, fn {k, v} -> Enum.map(List.wrap(v), &{k, &1}) end)
83100
end
84101
end
85102
end
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
defmodule Phoenix.Sync.Electric.ClientAdapterTest do
2+
use ExUnit.Case, async: true
3+
4+
import Plug.Test
5+
6+
alias Phoenix.Sync.Electric.ClientAdapter
7+
8+
defmodule MockFetch do
9+
def validate_opts(opts), do: {:ok, opts}
10+
11+
def fetch(request, parent: parent) do
12+
send(parent, {:fetch_request, request})
13+
14+
%Electric.Client.Fetch.Response{
15+
status: 200,
16+
headers: %{},
17+
body: ["[]"]
18+
}
19+
end
20+
end
21+
22+
test "forwards request headers to sync server" do
23+
{:ok, client} =
24+
Electric.Client.new(
25+
base_url: "elixir://#{inspect(__MODULE__.Fetch)}",
26+
fetch: {MockFetch, parent: self()}
27+
)
28+
29+
adapter = %ClientAdapter{client: client}
30+
31+
conn =
32+
conn(:get, "/v1/shapes", %{})
33+
|> Plug.Conn.put_req_header("my-header-1", "my-header-1-value-1")
34+
|> Plug.Conn.prepend_req_headers([{"my-header-1", "my-header-1-value-2"}])
35+
|> Plug.Conn.put_req_header("my-header-2", "my-header-2-value")
36+
37+
assert %{status: 200} = Phoenix.Sync.Adapter.PlugApi.call(adapter, conn, %{offset: -1})
38+
assert_receive {:fetch_request, request}
39+
40+
assert request.headers == [
41+
{"my-header-1", "my-header-1-value-1"},
42+
{"my-header-1", "my-header-1-value-2"},
43+
{"my-header-2", "my-header-2-value"}
44+
]
45+
end
46+
end

0 commit comments

Comments
 (0)