Skip to content

Commit

Permalink
Implement missing features
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinschweikert committed Dec 24, 2024
1 parent c2cd5bb commit 5ed8f14
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 58 deletions.
11 changes: 8 additions & 3 deletions lib/curl_req.ex
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ defmodule CurlReq do
* `-u`/`--user`
* `-n`/`--netrc`
* `--netrc-file`
* `--compressed`
Options:
Expand Down Expand Up @@ -124,15 +125,17 @@ defmodule CurlReq do
options =
Keyword.validate!(options, flags: :short, run_steps: true, flavor: nil, flavour: :curl)

# flavor = opts[:flavor] || opts[:flavour]
# flag_style = opts[:flags]
flavor = options[:flavor] || options[:flavour]
flags = options[:flags]
run_steps = options[:run_steps]

available_steps = step_names(req, run_steps)
req = run_steps(req, available_steps)

curl_options = [flavor: flavor, flags: flags]

CurlReq.Req.decode(req)
|> CurlReq.Curl.encode(options)
|> CurlReq.Curl.encode(curl_options)
end

@doc """
Expand All @@ -150,6 +153,8 @@ defmodule CurlReq do
* `-u`/`--user`
* `-x`/`--proxy`
* `-U`/`--proxy-user`
* `-n`/`--netrc`
* `--netrc_file`
* `--compressed`
The `curl` command prefix is optional
Expand Down
109 changes: 61 additions & 48 deletions lib/curl_req/curl.ex
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ defmodule CurlReq.Curl do
command
|> String.trim()
|> String.trim_leading("curl")
|> String.replace("\\\n", " ")
|> String.replace("\n", " ")
|> CurlReq.Shell.remove_newlines()

{options, rest, invalid} =
command
Expand Down Expand Up @@ -243,9 +242,11 @@ defmodule CurlReq.Curl do
@impl CurlReq.Request
@spec encode(CurlReq.Request.t(), Keyword.t()) :: String.t()
def encode(%CurlReq.Request{} = request, options \\ []) do
flag_style = Keyword.get(options, :flags, :short)
# TODO: implement flavor
_flavor = Keyword.get(options, :flavor, nil) || Keyword.get(options, :flavour, :curl)
options =
Keyword.validate!(options, flags: :short, flavor: :curl)

flag_style = options[:flags]
flavor = options[:flavor]

cookies =
if map_size(request.cookies) != 0 do
Expand Down Expand Up @@ -276,7 +277,11 @@ defmodule CurlReq.Curl do
headers ++ [header_flag(flag_style, "content-type: application/x-www-form-urlencoded")]
end

headers = Enum.intersperse(headers, " ")
headers =
case flavor do
:curl -> headers
:req -> headers ++ header_flag(flag_style, ["user-agent: req/", CurlReq.req_version()])
end

body =
emit_if(request.body, fn ->
Expand All @@ -287,7 +292,19 @@ defmodule CurlReq.Curl do
end)

redirect = emit_if(request.redirect, [location_flag(flag_style)])
compressed = emit_if(request.compression != :none, [compressed_flag(flag_style)])

compressed =
emit_if(request.compression != :none, fn ->
case flavor do
:curl ->
[compressed_flag(flag_style)]

:req ->
[
header_flag(flag_style, ["accept-encoding: ", Atom.to_string(request.compression)])
]
end
end)

auth =
case request.auth do
Expand Down Expand Up @@ -327,25 +344,21 @@ defmodule CurlReq.Curl do
_ -> []
end

url = [to_string(request.url)]

IO.iodata_to_binary(
[
"curl",
compressed,
auth,
headers,
cookies,
body,
proxy,
proxy_auth,
redirect,
method,
url
]
|> Enum.reject(fn part -> part == [] end)
|> Enum.intersperse(" ")
)
url = [" ", to_string(request.url)]

IO.iodata_to_binary([
"curl",
compressed,
auth,
headers,
cookies,
body,
proxy,
proxy_auth,
redirect,
method,
url
])
end

defp emit_if(bool, fun) when is_function(fun) do
Expand All @@ -364,37 +377,37 @@ defmodule CurlReq.Curl do
CurlReq.Shell.escape(value)
end

defp cookie_flag(:short, value), do: ["-b ", escape(value)]
defp cookie_flag(:long, value), do: ["--cookie ", escape(value)]
defp cookie_flag(:short, value), do: [" -b ", escape(value)]
defp cookie_flag(:long, value), do: [" --cookie ", escape(value)]

defp header_flag(:short, value), do: ["-H ", escape(value)]
defp header_flag(:long, value), do: ["--header ", escape(value)]
defp header_flag(:short, value), do: [" -H ", escape(value)]
defp header_flag(:long, value), do: [" --header ", escape(value)]

defp data_flag(:short, value), do: ["-d ", escape(value)]
defp data_flag(:long, value), do: ["--data ", escape(value)]
defp data_flag(:short, value), do: [" -d ", escape(value)]
defp data_flag(:long, value), do: [" --data ", escape(value)]

defp head_flag(:short), do: "-I"
defp head_flag(:long), do: "--head"
defp head_flag(:short), do: " -I"
defp head_flag(:long), do: " --head"

defp request_flag(:short, value), do: ["-X ", escape(value)]
defp request_flag(:long, value), do: ["--request ", escape(value)]
defp request_flag(:short, value), do: [" -X ", escape(value)]
defp request_flag(:long, value), do: [" --request ", escape(value)]

defp location_flag(:short), do: "-L"
defp location_flag(:long), do: "--location"
defp location_flag(:short), do: " -L"
defp location_flag(:long), do: " --location"

defp user_flag(:short, value), do: ["-u ", escape(value)]
defp user_flag(:long, value), do: ["--user ", escape(value)]
defp user_flag(:short, value), do: [" -u ", escape(value)]
defp user_flag(:long, value), do: [" --user ", escape(value)]

defp netrc_flag(:short), do: "-n"
defp netrc_flag(:long), do: "--netrc"
defp netrc_flag(:short), do: " -n"
defp netrc_flag(:long), do: " --netrc"

defp netrc_file_flag(_, value), do: ["--netrc-file ", escape(value)]
defp netrc_file_flag(_, value), do: [" --netrc-file ", escape(value)]

defp compressed_flag(_), do: "--compressed"
defp compressed_flag(_), do: " --compressed"

defp proxy_flag(:short, value), do: ["-x ", escape(value)]
defp proxy_flag(:long, value), do: ["--proxy ", escape(value)]
defp proxy_flag(:short, value), do: [" -x ", escape(value)]
defp proxy_flag(:long, value), do: [" --proxy ", escape(value)]

defp proxy_user_flag(:short, value), do: ["-U ", escape(value)]
defp proxy_user_flag(:long, value), do: ["--proxy-user ", escape(value)]
defp proxy_user_flag(:short, value), do: [" -U ", escape(value)]
defp proxy_user_flag(:long, value), do: [" --proxy-user ", escape(value)]
end
4 changes: 2 additions & 2 deletions lib/curl_req/request.ex
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,8 @@ defmodule CurlReq.Request do
## Examples
iex> request = %CurlReq.Request{} |> CurlReq.Request.put_proxy("https://example.com")
iex> request.url
URI.new!("https://example.com")
iex> request.proxy_url
URI.parse("https://example.com")
"""
@spec put_proxy(__MODULE__.t(), URI.t() | String.t()) :: __MODULE__.t()
def put_proxy(%__MODULE__{} = request, uri) do
Expand Down
33 changes: 28 additions & 5 deletions lib/curl_req/shell.ex
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ defmodule CurlReq.Shell do
@no_quotes ~r/^[a-zA-Z-,._+:@%\/]*$/

@doc ~S"""
Examples:
iex> CurlReq.Shell.escape(~s(abc def))
~s("abc def")
Escapes the value into a shell representable version
iex> CurlReq.Shell.escape(~s({"json":"is_cool"}))
~S("{\"json\":\"is_cool\"}")
## Examples
iex> CurlReq.Shell.escape(~s(abc def))
~s("abc def")
iex> CurlReq.Shell.escape(~s({"json":"is_cool"}))
~S("{\"json\":\"is_cool\"}")
"""
def escape(arg) do
if String.match?(arg, @no_quotes) do
Expand All @@ -34,4 +37,24 @@ defmodule CurlReq.Shell do
~s("#{arg}")
end
end

@doc """
Removes newlines from the input string
## Examples
iex> """
...> curl
...> -X GET example.com
...> """
...> |> CurlReq.Shell.remove_newlines()
"curl -X GET example.com"
"""
def remove_newlines(input) when is_binary(input) do
input
|> String.replace("\\\n", " ")
|> String.replace("\n", " ")
|> String.replace("\r", "")
|> String.trim()
end
end

0 comments on commit 5ed8f14

Please sign in to comment.