Repository: derekkraan/curl_req
Pull request #4 (2024-06-04 08:35:18)

Add cookie handling
This PR supports the `-b/--cookie` flag in both directions (`to_curl`/`from_curl`)


Patch:
diff --git a/README.md b/README.md
index b73c4d2..b85a671 100644
--- a/README.md
+++ b/README.md
@@ -62,7 +62,7 @@ Contributions are welcome! There are gaps in the library, and this is open sourc
 - [x] curl -H
 - [x] curl -X
 - [x] curl -d
-- [ ] curl -b
+- [x] curl -b
 - [x] curl long form options (--header, --data, etc)
 - [ ] Req Plugin to log curl command (like `TeslaCurl`)
 
diff --git a/lib/curl_req.ex b/lib/curl_req.ex
index 80c4708..e301cbe 100644
--- a/lib/curl_req.ex
+++ b/lib/curl_req.ex
@@ -55,8 +55,16 @@ defmodule CurlReq do
   def to_curl(req) do
     req = run_steps(req)
 
+    cookies =
+      case Map.get(req.headers, "cookie") do
+        nil -> []
+        [cookies] -> ["-b", cookies]
+      end
+
     headers =
-      Enum.flat_map(req.headers, fn {key, value} ->
+      req.headers
+      |> Enum.reject(fn {key, _val} -> key == "cookie" end)
+      |> Enum.flat_map(fn {key, value} ->
         ["-H", "#{key}: #{value}"]
       end)
 
@@ -74,7 +82,7 @@ defmodule CurlReq do
 
     url = [to_string(req.url)]
 
-    CurlReq.Shell.cmd_to_string("curl", headers ++ body ++ method ++ url)
+    CurlReq.Shell.cmd_to_string("curl", headers ++ cookies ++ body ++ method ++ url)
   end
 
   @doc """
diff --git a/lib/curl_req/macro.ex b/lib/curl_req/macro.ex
index 041b722..4425932 100644
--- a/lib/curl_req/macro.ex
+++ b/lib/curl_req/macro.ex
@@ -2,7 +2,6 @@ defmodule CurlReq.Macro do
   @moduledoc false
 
   # TODO: handle newlines
-  # TODO: support -b (cookies)
 
   def parse(command) do
     command =
@@ -14,8 +13,8 @@ defmodule CurlReq.Macro do
       command
       |> OptionParser.split()
       |> OptionParser.parse(
-        strict: [header: :keep, request: :string, data: :keep],
-        aliases: [H: :header, X: :request, d: :data]
+        strict: [header: :keep, request: :string, data: :keep, cookie: :string],
+        aliases: [H: :header, X: :request, d: :data, b: :cookie]
       )
 
     url = String.trim(url)
@@ -29,6 +28,7 @@ defmodule CurlReq.Macro do
     |> add_header(options)
     |> add_method(options)
     |> add_body(options)
+    |> add_cookie(options)
   end
 
   defp add_header(req, options) do
@@ -63,4 +63,11 @@ defmodule CurlReq.Macro do
 
     Req.merge(req, body: body)
   end
+
+  defp add_cookie(req, options) do
+    case Keyword.get(options, :cookie) do
+      nil -> req
+      cookie -> Req.Request.put_header(req, "cookie", cookie)
+    end
+  end
 end


Test patch:
diff --git a/test/curl_req_test.exs b/test/curl_req_test.exs
index 017a759..36a4e0b 100644
--- a/test/curl_req_test.exs
+++ b/test/curl_req_test.exs
@@ -3,12 +3,22 @@ defmodule CurlReqTest do
   doctest CurlReq
   import CurlReq
 
+  @req_version :application.get_key(:req, :vsn) |> elem(1)
+
+  defp default_header(), do: "-H \"accept-encoding: gzip\" -H \"user-agent: req/#{@req_version}\""
+
   describe "to_curl" do
     test "works with base URL" do
-      assert "curl -H \"accept-encoding: gzip\" -H \"user-agent: req/0.4.14\" -X GET https://catfact.ninja/fact" ==
+      assert "curl #{default_header()} -X GET https://catfact.ninja/fact" ==
                Req.new(url: "/fact", base_url: "https://catfact.ninja/")
                |> CurlReq.to_curl()
     end
+
+    test "cookies get extracted from header" do
+      assert Req.new(url: "http://example.com", headers: %{"cookie" => ["name1=value1"]})
+             |> CurlReq.to_curl() ==
+               "curl #{default_header()} -b \"name1=value1\" -X GET http://example.com"
+    end
   end
 
   describe "macro" do
@@ -52,5 +62,19 @@ defmodule CurlReqTest do
                  body: "name=foo&mail=bar"
                }
     end
+
+    test "cookie" do
+      assert ~CURL(http://example.com -b "name1=value1") ==
+               %Req.Request{
+                 url: URI.parse("http://example.com"),
+                 headers: %{"cookie" => ["name1=value1"]}
+               }
+
+      assert ~CURL(http://example.com -b "name1=value1; name2=value2") ==
+               %Req.Request{
+                 url: URI.parse("http://example.com"),
+                 headers: %{"cookie" => ["name1=value1; name2=value2"]}
+               }
+    end
   end
 end