DEV Community

Carlo Colombo
Carlo Colombo

Posted on • Originally published at blog.litapp.ovh

Elixir - Simple Req Cookie Jar

A simple req cookie jar plugin. It can be used when automating or scraping websites that implement cookie based sessions. The cookies are set using set-cookie header and are sent back to the server in the headers of each following request. The implementation is naive and probably misses advanced and corner cases.

# create the cookie jar
CookieJar.new()

# attach the plugin to the req
req = Req.new(base_url: "http://baseurl.example.com")
|> CookieJar.attach()

# when the response includes the set-cookie header, it store its value in the jar
%{body: "Ok."} = req
|> Req.post!(
         url: "/api/v2/auth/login",
         form: [username: "admin", password: "password"])

# all subsequent requests have the cookie set in the headers
%{status: 200} = req
|> Req.get!(url: "/api/v2/info?filter=foo")
Enter fullscreen mode Exit fullscreen mode

The cookie is stored in an Agent. Req response and request steps are respectively used to collect the cookie string and to add to the cookie header when requests are performed.

defmodule ReqCookieJar do
  use Agent

  def new() do
    Agent.start_link(fn -> "" end, name: __MODULE__)
  end

  defp get_cookie do
    Agent.get(__MODULE__, & &1)
  end

  defp set_cookie([]), do: nil
  defp set_cookie(val) do
    Agent.update(__MODULE__, fn (_) -> val end)
  end

  def attach(%Req.Request{} = request) do
    request
    |> Req.Request.append_response_steps(
      cookie_jar: fn({req, res})->
        Req.Response.get_header(res, "set-cookie")
        |> set_cookie()

        {req,res}
      end
    )
    |> Req.Request.append_request_steps(
      cookie_jar: &Req.Request.put_header(&1, "cookie", get_cookie())
    )
  end
end
Enter fullscreen mode Exit fullscreen mode

Top comments (0)