# `HTTP.Request`
[🔗](https://github.com/gsmlg-dev/http_fetch/blob/v0.21.16/apps/http_core/lib/http/request.ex#L1)

HTTP request configuration struct.

This module provides a structured way to build HTTP requests with proper
conversion to the internal HTTP/1.1 wire format. It handles method normalization,
header processing, body encoding, and FormData support.

## Supported Methods

- `:get` - GET requests
- `:head` - HEAD requests
- `:post` - POST requests (with body)
- `:put` - PUT requests (with body)
- `:delete` - DELETE requests
- `:patch` - PATCH requests (with body)

Any nonempty ASCII HTTP token is accepted, including DAV methods such as
`:propfind` and `:report`. Atom methods are uppercased; binary methods retain
their case because extension methods are case-sensitive. Whitespace, control
characters, non-ASCII bytes and token separators are rejected before normalization.

By default, GET, HEAD, and DELETE request bodies are omitted for compatibility.
Set `request_mode: :proxy` to retain entities for all admitted methods.
HEAD response bodies remain empty regardless of the request mode.

## Usage

    # Basic request
    request = %HTTP.Request{
      method: :get,
      url: URI.parse("https://api.example.com/data"),
      headers: HTTP.Headers.new([{"Accept", "application/json"}])
    }

    # POST with JSON body
    request = %HTTP.Request{
      method: :post,
      url: URI.parse("https://api.example.com/posts"),
      headers: HTTP.Headers.new([{"Authorization", "Bearer token"}]),
      content_type: "application/json",
      body: JSON.encode!(%{title: "Hello"}),
      transport_options: [timeout: 10_000]
    }

    # FormData upload
    form = HTTP.FormData.new()
           |> HTTP.FormData.append_field("name", "John")
           |> HTTP.FormData.append_file("photo", "photo.jpg", file_stream)

    request = %HTTP.Request{
      method: :post,
      url: URI.parse("https://api.example.com/upload"),
      body: form
    }

## Default Headers

The library automatically adds a `User-Agent` header if not provided,
containing information about the runtime environment (OS, architecture,
OTP version, Elixir version, and library version).

# `body_content`

```elixir
@type body_content() :: any()
```

# `content_type`

```elixir
@type content_type() :: String.t() | charlist() | nil
```

# `duplex`

```elixir
@type duplex() :: :half | nil
```

# `method`

```elixir
@type method() :: atom() | String.t()
```

# `request_mode`

```elixir
@type request_mode() :: :fetch | :proxy
```

# `t`

```elixir
@type t() :: %HTTP.Request{
  body: body_content(),
  content_type: content_type(),
  duplex: duplex(),
  headers: HTTP.Headers.t(),
  method: method(),
  request_mode: request_mode(),
  transport_options: Keyword.t(),
  url: url()
}
```

# `url`

```elixir
@type url() :: URI.t()
```

# `to_iodata`

```elixir
@spec to_iodata(t()) :: iolist()
```

Converts an `HTTP.Request` struct into HTTP/1.1 wire iodata.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
