     * `transport` - Whether to use TLS or plain TCP. The default varies depending on the port used. Port 443 defaults to tls.
                     All other ports default to tcp.
     * `transport_opts` - Transport options. They are TCP options or TLS options depending on the selected transport. Default: [].
-    * `tls_opts` - TLS transport options. Default: []
-    * `tcp_opts` - TCP trasnport options. Default: []
+                          Gun version: 1.3
+    * `tls_opts` - TLS transport options. Default: []. Gun from master branch.
+    * `tcp_opts` - TCP trasnport options. Default: []. Gun from master branch.
     * `ws_opts` - Options specific to the Websocket protocol. Default: %{}.
         * `compress` - Whether to enable permessage-deflate compression. This does not guarantee that compression will
                         be used as it is the server that ultimately decides. Defaults to false.

          tls_opts
        end

      tcp_opts = Map.get(opts, :tcp_opts, [])

      {:ok, pid, opts} =
        if opts[:conn] && opts[:original] == "#{uri.host}:#{uri.port}" do
          {:ok, opts[:conn], Map.put(opts, :receive, false)}
        else
          transport_opts = Map.get(opts, :transport_opts, [])

          gun_opts = Map.take(opts, @gun_keys)

          # if gun used from master
          opts_with_master_keys =
            Map.put(gun_opts, :tls_opts, tls_opts)
            |> Map.put(:tcp_opts, tcp_opts)

          host = to_charlist(uri.host)

          {:ok, pid} =
            case :gun.open(host, uri.port, opts_with_master_keys) do
              {:error, {:options, {key, _}}} when key in [:tcp_opts, :tls_opts] ->
                :gun.open(
                  host,
                  uri.port,
                  Map.put(gun_opts, :transport_opts, transport_opts)
                )

              {:error, error} ->
                {:error, error}

              {:ok, pid} ->
                {:ok, pid}
            end

          # If there were redirects, and passed `closed_conn: false`, we need to close opened connections to these intermediate hosts.
          {:ok, pid, Map.put(opts, :close_conn, true)}
        end

      {pid, format_url(uri.path, uri.query), opts}
    end

    defp open_stream(pid, method, url, headers, body, :stream) do

      do: do_request(method, url, headers, body, opts)

    defp do_request(method, url, headers, body, opts) do
      with uri <- URI.parse(url),
           path_with_query <- format_url(uri.path, uri.query),
           {pid, opts} <- open_conn(uri, opts),
           stream <- open_stream(pid, method, path_with_query, headers, body, opts[:send_body]) do
        read_response(pid, stream, opts)
      end
    end

    defp open_conn(uri, %{conn: conn, original: original} = opts) do
      if original == "#{uri.host}:#{uri.port}" do
        {conn, Map.put(opts, :receive, false)}
      else
        # current url is different from the original, maybe there were redirects
        # so we can't use transferred connection
        open_conn(uri, Map.delete(opts, :conn))
      end
    end

    defp open_conn(uri, opts) do
      opts =
        if uri.scheme == "https" and uri.port != 443 do
          Map.put(opts, :transport, :tls)
