     headers = [{"host", request.authority}] ++ payload_headers ++ request.headers
     head = [start_line(request), header_lines(headers), @crlf]
     {head, body}
+  end
+
+  @doc """
+  ## Examples
+
+      iex> "GET /path?qs HTTP/1.1\\r\\nhost: example.com\\r\\naccept: text/plain\\r\\n\\r\\n"
+      ...> |> Raxx.HTTP1.parse_request()
+      {:ok,
+       %Raxx.Request{
+         authority: "example.com",
+         body: false,
+         headers: [{"accept", "text/plain"}],
+         method: :GET,
+         mount: [],
+         path: ["path"],
+         query: "qs",
+         raw_path: "/path",
+         scheme: :http
+       }, {:complete, ""}, ""}
+
+      iex> "POST /path HTTP/1.1\\r\\nhost: example.com\\r\\ntransfer-encoding: chunked\\r\\ncontent-type: text/plain\\r\\n\\r\\n"
+      ...> |> Raxx.HTTP1.parse_request()
+      {:ok,
+       %Raxx.Request{
+         authority: "example.com",
+         body: true,
+         headers: [{"content-type", "text/plain"}],
+         method: :POST,
+         mount: [],
+         path: ["path"],
+         query: nil,
+         raw_path: "/path",
+         scheme: :http
+       }, :chunked, ""}
+
+      iex> "POST /path HTTP/1.1\\r\\nhost: example.com\\r\\ncontent-length: 13\\r\\n\\r\\n"
+      ...> |> Raxx.HTTP1.parse_request()
+      {:ok,
+       %Raxx.Request{
+         authority: "example.com",
+         body: true,
+         headers: [{"content-length", "13"}],
+         method: :POST,
+         mount: [],
+         path: ["path"],
+         query: nil,
+         raw_path: "/path",
+         scheme: :http
+       }, {:bytes, 13}, ""}
+
+      iex> "GET /path?qs HT"
+      ...> |> Raxx.HTTP1.parse_request()
+      {:more, "GET /path?qs HT"}
+
+      iex> "GET /path?qs HTTP/1.1\\r\\nhost: exa"
+      ...> |> Raxx.HTTP1.parse_request()
+      {:more, "GET /path?qs HTTP/1.1\\r\\nhost: exa"}
+
+  """
+  def parse_request(buffer, scheme \\ :http) do
+    case :erlang.decode_packet(:http_bin, buffer, []) do
+      {:ok, {:http_request, method, {:abs_path, path_and_query}, _version}, rest} ->
+        case parse_headers(rest) do
+          {:ok, headers, rest2} ->
+            case Enum.split_with(headers, fn {key, _value} -> key == "host" end) do
+              {[{"host", host}], headers} ->
+                {headers, body, state} = decode_payload(headers)
+
+                request =
+                  Raxx.request(method, path_and_query)
+                  |> Map.put(:scheme, scheme)
+                  |> Map.put(:authority, host)
+                  |> Map.put(:headers, headers)
+                  |> Map.put(:body, body)
+
+                {:ok, request, state, rest2}
+            end
+
+          {:more, :undefined} ->
+            {:more, buffer}
+        end
+
+      {:more, :undefined} ->
+        {:more, buffer}
+    end
+  end
+
+  defp parse_headers(buffer, headers \\ []) do
+    case :erlang.decode_packet(:httph_bin, buffer, []) do
+      {:ok, :http_eoh, rest} ->
+        {:ok, Enum.reverse(headers), rest}
+
+      {:ok, {:http_header, _, key, _, value}, rest} ->
+        parse_headers(rest, [{String.downcase("#{key}"), value} | headers])
+
+      {:more, :undefined} ->
+        {:more, :undefined}
+    end
   end
 
   @doc """


        case rest do
          <<chunk::binary-size(size), "\r\n", rest::binary>> ->
            {chunk, rest}

          _incomplete_chunk ->
            {nil, buffer}
        end

      [rest] ->
        {nil, rest}
    end
  end


  @crlf "\r\n"

  @doc """
  # NOTE set_body should add content-length otherwise we don't know if to delete it to match on other end, when serializing

  ## Examples
      iex> request = Raxx.request(:GET, "http://example.com/path?qs")
      ...> |> Raxx.set_header("accept", "text/plain")
