Skip to content

Instantly share code, notes, and snippets.

@suciptoid
Created October 30, 2025 05:30
Show Gist options
  • Select an option

  • Save suciptoid/518df056c25d75e29aa976949ff6bfa6 to your computer and use it in GitHub Desktop.

Select an option

Save suciptoid/518df056c25d75e29aa976949ff6bfa6 to your computer and use it in GitHub Desktop.
Converts curl -i response format into Elixir Req.Response struct.
defmodule CurlReqResponse do
@moduledoc """
Converts curl -i response format into Elixir Req.Response struct.
"""
@doc """
Parses a curl -i response string and returns a Req.Response struct.
## Examples
iex> curl_response = \"\"\"
...> HTTP/1.1 200 OK
...> Content-Type: application/json
...> Content-Length: 27
...>
...> {"message":"Hello World"}
...> \"\"\"
iex> CurlReqResponse.parse(curl_response)
%Req.Response{
status: 200,
headers: %{"content-type" => ["application/json"], "content-length" => ["27"]},
body: "{\\"message\\":\\"Hello World\\"}"
}
"""
def parse(curl_response) when is_binary(curl_response) do
# Try different separators: \r\n\r\n, \n\n, or no body
{headers_section, body} =
case String.split(curl_response |> String.trim, "\r\n\r\n", parts: 2) do
[h, b] -> {h, b}
[h] ->
case String.split(h, "\n\n", parts: 2) do
[h2, b] -> {h2, b}
[h2] -> {h2, ""}
end
end
lines = String.split(headers_section, ~r/\r?\n/)
[status_line | header_lines] = lines
status = parse_status_line(status_line)
headers = parse_headers(header_lines)
body = String.trim_trailing(body)
%Req.Response{
status: status,
headers: headers,
body: body
}
end
defp parse_status_line(status_line) do
# Extract status code from lines like "HTTP/1.1 200 OK"
case Regex.run(~r/HTTP\/[\d.]+ (\d+)/, status_line) do
[_, status_code] -> String.to_integer(status_code)
_ -> 0
end
end
defp parse_headers(header_lines) do
header_lines
|> Enum.reject(&(&1 == ""))
|> Enum.map(&parse_header_line/1)
|> Enum.group_by(fn {key, _value} -> key end, fn {_key, value} -> value end)
|> Map.new()
end
defp parse_header_line(line) do
case String.split(line, ":", parts: 2) do
[key, value] ->
key = key |> String.trim() |> String.downcase()
value = String.trim(value)
{key, value}
_ ->
{"", ""}
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment