-
Notifications
You must be signed in to change notification settings - Fork 602
Open
Description
The function put_req_cookie/3 wasn't working for my case because my plug application expected encrypted cookies with certain attributes, such as domain and path. I dug through the code, turns out it simply puts the header {"cookie", "#{key}=#{value}"}.
I had to "reverse-engineer" put_resp_cookie/4 to come up with a solution. This issue is meant to document such workaround in case someone else stumble upon the same problem - although, it would be nice if Plug.Test.put_req_cookie/3 were made symmetric to Plug.Conn.put_resp_cookie/4.
defmodule Ex.Plug.Test do
@moduledoc ~S"""
Extends `Plug.Test`.
"""
@doc """
Puts a request cookie.
"""
@spec put_req_cookie(Plug.Conn.t(), binary, binary, keyword) :: Plug.Conn.t()
# mostly from https://github.com/elixir-plug/plug/blob/main/lib/plug/conn.ex#L1671-L1678
def put_req_cookie(%Plug.Conn{} = conn, key, value, opts \\ [])
when is_binary(key) and is_binary(value) and is_list(opts) do
conn = Plug.Test.delete_req_cookie(conn, key)
{to_send_value, opts} = maybe_sign_or_encrypt_cookie(conn, key, value, opts)
cookie = Map.new([{:value, to_send_value} | opts])
value = Plug.Conn.Cookies.encode(key, cookie)
%{conn | req_headers: [{"cookie", value} | conn.req_headers]}
end
# from https://github.com/elixir-plug/plug/blob/main/lib/plug/conn.ex#L1680-L1701
defp maybe_sign_or_encrypt_cookie(conn, key, value, opts) do
{sign?, opts} = Keyword.pop(opts, :sign, false)
{encrypt?, opts} = Keyword.pop(opts, :encrypt, false)
case {sign?, encrypt?} do
{true, true} ->
raise ArgumentError,
":encrypt automatically implies :sign. Please pass only one or the other"
{true, false} ->
{Plug.Crypto.sign(conn.secret_key_base, key <> "_cookie", value, max_age(opts)), opts}
{false, true} ->
{Plug.Crypto.encrypt(conn.secret_key_base, key <> "_cookie", value, max_age(opts)), opts}
{false, false} when is_binary(value) ->
{value, opts}
{false, false} ->
raise ArgumentError, "cookie value must be a binary unless the cookie is signed/encrypted"
end
end
# from https://github.com/elixir-plug/plug/blob/main/lib/plug/conn.ex#L1703-L1706
defp max_age(opts) do
max_age = Keyword.get(opts, :max_age) || 86400
[keys: Plug.Keys, max_age: max_age]
end
endNot my finest, but it's honest work.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels