defmodule Kadabra do @moduledoc """ HTTP/2 client for Elixir. """ alias Kadabra.{Connection} def open(uri, scheme, opts \\ []) do port = opts[:port] || 443 reconnect = fetch_reconnect_option(opts) nopts = opts |> List.keydelete(:port, 0) |> List.keydelete(:reconnect, 0) start_opts = [scheme: scheme, ssl: nopts, port: port, reconnect: reconnect] case Connection.start_link(uri, self(), start_opts) do {:ok, pid} -> {:ok, pid} {:error, reason} -> {:error, reason} end end defp fetch_reconnect_option(opts) do if List.keymember?(opts, :reconnect, 0) do opts[:reconnect] else true end end def close(pid), do: GenServer.cast(pid, {:send, :goaway}) def ping(pid), do: GenServer.cast(pid, {:send, :ping}) def info(pid, opts \\ []) do case GenServer.call(pid, :get_info) do {:ok, info} -> width = opts[:width] || 120 headers = opts[:data] || [:id, :status, :headers, :body] stream_table_opts = [width: width, data: headers] stream_data = info.streams |> Map.values |> Enum.map(& Map.put(&1, :body, String.slice(&1.body, 0..40))) |> Enum.sort_by(& &1.id) |> Scribe.format(stream_table_opts) """ == Connection Information == Uri: #{info.uri} Scheme: #{info.scheme} Client: #{inspect(info.client)} SSL Socket: #{inspect(info.socket)} Next Available Stream ID: #{info.stream_id} Buffer: #{inspect(info.buffer)} == Streams == #{stream_data} """ |> Pane.console _else -> :error end end def request(pid, headers) do GenServer.cast(pid, {:send, :headers, headers}) end def request(pid, headers, payload) do GenServer.cast(pid, {:send, :headers, headers, payload}) end def get(pid, path) do headers = [ {":method", "GET"}, {":path", path}, ] request(pid, headers) end def post(pid, path, payload) do headers = [ {":method", "POST"}, {":path", path}, ] request(pid, headers, payload) end @doc ~S""" Makes HTTP/2 PUT request. ## Examples iex> {:ok, pid} = Kadabra.open('http2.golang.org', :https) iex> Kadabra.put(pid, "/crc32", "test") :ok iex> stream = receive do ...> {:end_stream, stream} -> stream ...> end iex> stream.status 200 iex> stream.body "bytes=4, CRC32=d87f7e0c" """ def put(pid, path, payload) do headers = [ {":method", "PUT"}, {":path", path}, ] request(pid, headers, payload) end end