Usage
View SourceMix.install([
{:curl_req, github: "derekkraan/curl_req", override: true},
{:merquery, "~> 0.3.0"},
{:kino, "~> 0.14.2"},
])From cURL to Req
To generate a Req struct from a cURL command, you can either use the function CurlReq.from_curl/1 or the sigil_CURL.
import CurlReq
sigil = ~CURL(https://httpbin.org/get)function = CurlReq.from_curl("curl https://httpbin.org/get")Both produce the same Req.Request but the macro checks the validity at compile time and you don't have to escape the string. As you can see, the cURL command itself ("curl") gets ignored and produces the same request.
sigil === functionLet's see if CurlReq can understand a more complex cURL command
~CURL(curl -H "Accept-Encoding: gzip" -H "User-Agent: firefox/111" https://httpsbin.org/get)As we can see, the User-Agent ist stored in the header map but where is the Accept-Encoding header? If you look closely at the Req.Request struct, you can see that a new request step was added (&Req.Steps.compressed/1). CurlReq tries to use/translate the native functionalities of the underlying HTTP client, in this case Req.
From Req to cURL
req = Req.new(base_url: "http://httpbin.org", url: "/post", method: :post, json: %{foo: "bar"})
curl = CurlReq.to_curl(req)To read it better we can hide the double string escaping with some Kino helpers
Kino.Shorts.text(curl)As you can see, the correct Accept headers get set and the JSON body gets correctly escaped.
Flag style
You can control if you want short or long flags in the generated cURL command
CurlReq.to_curl(req, flags: :long)Flavor
You can control if you wan't to use the Req user agent instead of the native cURL command and if you want to set the implicit headers explicitly with this opion
CurlReq.to_curl(req, flavor: :req)Third party integration
CurlReq is used in Merquery which describes itself as "Powered by the wonderful Req library, Merquery is an interactive and extensible
HTTP client for Elixir and Livebook"
If you select the Plugins tab in the Smart Cell below you can activate the CurlReq plugin. This will log the request you make as a cURL command as you make the request. Just enter an URL and evaluate the cell, it will print the cURL command and after that the Req.Response.
req = Req.new(method: :get, url: "", headers: %{}, params: %{})
{req, resp} = Req.request(req)
respAnother cool feature of merquery is, that you can import your cURL commands directly. Just copy the following request
curl --compressed -H "foo: bar" -X GET http://httpbin.org/getand select the import icon from the top right of the Merquery cell below and paste it in the text area which will open.
req = Req.new(method: :get, url: "", headers: %{}, params: %{})
{req, resp2} = Req.request(req)
resp2
>>>>>>> Stashed changesAdvanced Usage
Internally everything gets converted to a CurlReq.Request struct. So you can modify it and generate the cURL and Req commands from that. Say we wouldn't know how to set the user agent with the cURL command. The solution would be to add it afterwards with CurlReq.Request.put_user_agent/2 and then encode it as a Req struct.
request = CurlReq.Curl.decode("curl -k -X POST https://example.com")request = CurlReq.Request.put_user_agent(request, "my_user_agent/1.0")CurlReq.Req.encode(request)You could also implement the CurlReq.Request behaviour for other HTTP clients. Here's an example for a non existing fake client.
defmodule MyHTTPClient do
defstruct [:url, method: :get]
@behaviour CurlReq.Request
import CurlReq.Request
@impl CurlReq.Request
def decode(%__MODULE__{} = request, _opts \\ []) do
%CurlReq.Request{}
|> put_method(request.method)
|> put_url(request.url)
end
@impl CurlReq.Request
def encode(%CurlReq.Request{} = request, _opts \\ []) do
%__MODULE__{url: URI.to_string(request.url), method: request.method}
end
end%MyHTTPClient{url: "https://example.com", method: :post}
|> MyHTTPClient.decode()
|> CurlReq.Curl.encode()"curl -X PUT https://example.com"
|> CurlReq.Curl.decode()
|> MyHTTPClient.encode()