
# tecs.io.http


Cooperative HTTP and HTTPS.

```teal
local client <const> = tecs.io.http.newClient({userAgent = "mygame/1.0"})
local response <const> = client:send({
    url = tecs.io.URI.new("https://example.com/manifest.json"),
})
print(response.status)
print(assert(response.body:readAll(1024 * 1024)))
```

`send` returns when status and headers exist. Inside a system it suspends only
until that boundary; outside an update it blocks its caller. The body is a
one-shot streaming Reader backed by bounded native chunks, so a slow consumer
applies transport backpressure instead of accumulating the full response.
Arbitrary streaming request bodies run in client-owned cooperative work, so
their Reader may itself wait on a socket, process, transform, or HTTP response
without blocking the SDL pump. On the SDL storage backend, a file stream is
opened and read directly by Tokio instead. It stays bounded without retaining
the complete file or crossing Lua for every chunk.

An HTTP error status still returns a response. DNS, connection, TLS, timeout,
or streaming failures raise at the suspended call.

Raw `tecs.io` sockets use the process-wide `mio` readiness reactor. HTTP
deliberately uses Reqwest and Tokio for its connection pool, TLS, redirects,
and protocol work. Both implementations resume the same direct Lua call, and
neither parks one worker thread per waiting socket.

A request holds one of its client's `maxConnections` slots until its response
body ends, so close or discard a body you do not intend to read.

Call `Client:close` when you no longer need its connection pool. Losing the
last Lua reference does not cancel its requests. Application shutdown closes
any remaining clients and drains their internal upload tasks to settlement,
within a bounded number of scheduler steps that it logs whenever it has to
abandon work. An [`Application`](/modules/Application/) owns progress; a
direct headless call drives the client while it blocks.

## Module contents

### Constructors

| Constructor | Description |
| --- | --- |
| [`newClient`](/modules/io/http/#tecs.io.http.newClient) | Builds a client. |

### Types

| Type | Kind | Description |
| --- | --- | --- |
| [`Client`](/modules/io/http/#tecs.io.http.Client) | <span class="tealdoc-kind-badge tealdoc-kind-interface">interface</span> | A Client owns one connection pool and its active requests. |
| [`ClientOptions`](/modules/io/http/#tecs.io.http.ClientOptions) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | Settings copied when an HTTP client is built. |
| [`plugin`](/modules/io/http/#tecs.io.http.plugin) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | Read-only. plugin exposes requests and responses as ECS components. |
| [`Request`](/modules/io/http/#tecs.io.http.Request) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | Request describes one request and requires only url. |
| [`Response`](/modules/io/http/#tecs.io.http.Response) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | Response describes status, headers, and a progressive response body. |

### Functions

| Function | Kind | Description |
| --- | --- | --- |
| [`getOpenClientCount`](/modules/io/http/#tecs.io.http.getOpenClientCount) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Returns the open-client count. |

## Constructors

<a id="tecs.io.http.newClient"></a>
### tecs.io.http.newClient <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Builds a client.



```teal
function tecs.io.http.newClient(options: ClientOptions): Client
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `options` | [`ClientOptions`](/modules/io/http/#tecs.io.http.ClientOptions) | The caller supplies client defaults or omits this record to use every default. Each `insecureHosts` entry logs a warning. |

#### Returns

| Type | Description |
| --- | --- |
| [`Client`](/modules/io/http/#tecs.io.http.Client) | Returns an open client that remains active until `close`. |


#### Examples

```teal
local http <const> = tecs.io.http
local endpoint, reason = tecs.io.URI.new("https://example.com/status")
if endpoint == nil then
    error(reason)
end
local client <const> = http.newClient({
    userAgent = "mygame/1.0",
    timeoutMs = 10000,
    maxBytes = 1024 * 1024,
})
local response <const> = client:send({url = endpoint})
print(response.status, response.url:host())
response.body:close()
client:close()
```

## Types

<a id="tecs.io.http.Client"></a>
### tecs.io.http.Client <span class="tealdoc-kind-badge tealdoc-kind-interface">interface</span>

A `Client` owns one connection pool and its active requests.

Closing the client cancels every pending request, releases the pool,
and remains safe to repeat. The Application drives active requests.


```teal
interface tecs.io.http.Client is Closeable
    pending: function(self): integer
    send: function(self, request: Request): Response
end
```

#### Interfaces

| Interface |
| --- |
| [`Closeable`](/modules/#tecs.Closeable) |

<a id="tecs.io.http.Client.pending"></a>
#### tecs.io.http.Client:pending <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Returns the number of unsettled requests.



```teal
function tecs.io.http.Client.pending(self): integer
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Client` | The client to inspect. |

##### Returns

| Type | Description |
| --- | --- |
| `integer` | Returns zero after every request settles or is canceled. |

<a id="tecs.io.http.Client.send"></a>
#### tecs.io.http.Client:send <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Sends one HTTP request and returns its response.

A transport failure raises. An HTTP error status returns normally
with that status in the response. Inside a system, the call
suspends the world update only while the transfer is pending.


```teal
function tecs.io.http.Client.send(self, request: Request): Response
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Client` | The open client that owns the request. |
| `request` | `Request` | The caller supplies the URL and optional method, headers, upload body, timeouts, and byte limit. |

##### Returns

| Type | Description |
| --- | --- |
| `Response` | Returns status, headers, and a one-shot streaming body. |

<a id="tecs.io.http.ClientOptions"></a>
### tecs.io.http.ClientOptions <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

Settings copied when an HTTP client is built.

`userAgent` and `headers` set request defaults. `timeoutMs` defaults to
30000, `connectTimeoutMs` to 10000, and `stallTimeoutMs` to zero, which
disables the no-progress timeout. `maxRedirects` defaults to five,
`maxConnections` to 16, and `maxConnectionsPerHost` to six; a request
holds one slot of each until its response body ends. `maxBytes`
defaults to zero for no response limit. `compressed` defaults to true.

`insecureHosts` disables certificate verification for named hosts and
logs a warning for each. `proxy` accepts the textual spelling of an
absolute [`URI`](/modules/io/URI/), follows environment variables
when nil, and forces a direct connection when empty. `noProxy` uses
Reqwest's exclusion syntax, and `proxyCredentials` uses
`user:password`.


```teal
record tecs.io.http.ClientOptions
    userAgent: string
    headers: {string: string}
    timeoutMs: number
    connectTimeoutMs: number
    stallTimeoutMs: number
    maxRedirects: integer
    maxConnections: integer
    maxConnectionsPerHost: integer
    maxBytes: integer
    compressed: boolean
    insecureHosts: {string}
    proxy: string
    noProxy: string
    proxyCredentials: string
end
```

<a id="tecs.io.http.ClientOptions.userAgent"></a>
#### tecs.io.http.ClientOptions.userAgent <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets `User-Agent` on every request.


```teal
tecs.io.http.ClientOptions.userAgent: string
```

<a id="tecs.io.http.ClientOptions.headers"></a>
#### tecs.io.http.ClientOptions.headers <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets headers sent on every request. Per-request
headers override these without regard to case.


```teal
tecs.io.http.ClientOptions.headers: {string: string}
```

<a id="tecs.io.http.ClientOptions.timeoutMs"></a>
#### tecs.io.http.ClientOptions.timeoutMs <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets positive milliseconds allowed for a whole
transfer. Defaults to 30000.


```teal
tecs.io.http.ClientOptions.timeoutMs: number
```

<a id="tecs.io.http.ClientOptions.connectTimeoutMs"></a>
#### tecs.io.http.ClientOptions.connectTimeoutMs <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets positive milliseconds allowed to establish
a connection. Defaults to 10000.


```teal
tecs.io.http.ClientOptions.connectTimeoutMs: number
```

<a id="tecs.io.http.ClientOptions.stallTimeoutMs"></a>
#### tecs.io.http.ClientOptions.stallTimeoutMs <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets milliseconds a response may make no progress.
Zero disables this timeout.


```teal
tecs.io.http.ClientOptions.stallTimeoutMs: number
```

<a id="tecs.io.http.ClientOptions.maxRedirects"></a>
#### tecs.io.http.ClientOptions.maxRedirects <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets redirects followed. Defaults to five; zero
follows none.


```teal
tecs.io.http.ClientOptions.maxRedirects: integer
```

<a id="tecs.io.http.ClientOptions.maxConnections"></a>
#### tecs.io.http.ClientOptions.maxConnections <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets requests allowed to use sockets at once.
Defaults to 16.

A request holds its slot from the moment it acquires one until its
response body ends, because the socket stays open for that whole
time and this limit is what bounds open sockets. A caller that
reads a body slowly therefore keeps its slot, and a caller that
never reads one keeps it until `timeoutMs` expires. Close or
discard a body you do not intend to read, and raise this limit
rather than expecting an unread body to release its slot early.


```teal
tecs.io.http.ClientOptions.maxConnections: integer
```

<a id="tecs.io.http.ClientOptions.maxConnectionsPerHost"></a>
#### tecs.io.http.ClientOptions.maxConnectionsPerHost <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets requests allowed to use sockets to one host.
Defaults to six. A request holds its host slot for as long as it
holds a `maxConnections` slot.


```teal
tecs.io.http.ClientOptions.maxConnectionsPerHost: integer
```

<a id="tecs.io.http.ClientOptions.maxBytes"></a>
#### tecs.io.http.ClientOptions.maxBytes <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets maximum response-body bytes. Zero is
unbounded.


```teal
tecs.io.http.ClientOptions.maxBytes: integer
```

<a id="tecs.io.http.ClientOptions.compressed"></a>
#### tecs.io.http.ClientOptions.compressed <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Accepts gzip and deflate response compression when
true. Defaults to true.


```teal
tecs.io.http.ClientOptions.compressed: boolean
```

<a id="tecs.io.http.ClientOptions.insecureHosts"></a>
#### tecs.io.http.ClientOptions.insecureHosts <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Lists host names whose TLS certificates are not
verified.


```teal
tecs.io.http.ClientOptions.insecureHosts: {string}
```

<a id="tecs.io.http.ClientOptions.proxy"></a>
#### tecs.io.http.ClientOptions.proxy <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the textual spelling of an absolute proxy
[`URI`](/modules/io/URI/). Nil follows the environment; an empty
string forces a direct connection. This option accepts a string,
not a `URI` object.


```teal
tecs.io.http.ClientOptions.proxy: string
```

<a id="tecs.io.http.ClientOptions.noProxy"></a>
#### tecs.io.http.ClientOptions.noProxy <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Lists hosts excluded from an explicitly configured
proxy.


```teal
tecs.io.http.ClientOptions.noProxy: string
```

<a id="tecs.io.http.ClientOptions.proxyCredentials"></a>
#### tecs.io.http.ClientOptions.proxyCredentials <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets proxy credentials in `user:password` form.


```teal
tecs.io.http.ClientOptions.proxyCredentials: string
```

<a id="tecs.io.http.plugin"></a>
### tecs.io.http.plugin <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

Read-only. `plugin` exposes requests and responses as ECS components.


```teal
record tecs.io.http.plugin
    record Request is Component
        url: URI
        method: string
        headers: {string: string}
        body: string | ReadableStream
        timeoutMs: number
        stallTimeoutMs: number
        maxBytes: integer
    end

    record Response is Component
        status: integer
        headers: {string: string}
        body: Stream
        url: URI
        error: string
    end

    record Pending is Component
    end

    clientOf: function(World): Client
    close: function(World)
    install: function(World, Options)
end
```

<a id="tecs.io.http.plugin.Request"></a>
#### tecs.io.http.plugin.Request <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

What a game spawns to make a request. The fields of a `Request`,
because there is no second vocabulary for the same thing.


```teal
record tecs.io.http.plugin.Request is Component
    url: URI
    method: string
    headers: {string: string}
    body: string | ReadableStream
    timeoutMs: number
    stallTimeoutMs: number
    maxBytes: integer
end
```

##### Interfaces

| Interface |
| --- |
| [`Component`](/modules/ecs/#tecs.ecs.Component) |

<a id="tecs.io.http.plugin.Request.url"></a>
##### tecs.io.http.plugin.Request.url <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets an absolute HTTP or HTTPS
[`URI`](/modules/io/URI/).


```teal
tecs.io.http.plugin.Request.url: URI
```

<a id="tecs.io.http.plugin.Request.method"></a>
##### tecs.io.http.plugin.Request.method <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the method. Defaults to `"GET"`.


```teal
tecs.io.http.plugin.Request.method: string
```

<a id="tecs.io.http.plugin.Request.headers"></a>
##### tecs.io.http.plugin.Request.headers <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets headers merged over the client's defaults
without regard to case. A `Content-Length` must contain decimal
digits and must match a body whose length is known.


```teal
tecs.io.http.plugin.Request.headers: {string: string}
```

<a id="tecs.io.http.plugin.Request.body"></a>
##### tecs.io.http.plugin.Request.body <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets what to send. A snapshot rejects a
`tecs.io.newHandleStream` here because its live handle cannot
be reconstructed.


```teal
tecs.io.http.plugin.Request.body: string | ReadableStream
```

<a id="tecs.io.http.plugin.Request.timeoutMs"></a>
##### tecs.io.http.plugin.Request.timeoutMs <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets milliseconds for this transfer, overriding
the client's value.


```teal
tecs.io.http.plugin.Request.timeoutMs: number
```

<a id="tecs.io.http.plugin.Request.stallTimeoutMs"></a>
##### tecs.io.http.plugin.Request.stallTimeoutMs <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets tolerated milliseconds without progress,
overriding the client's value.


```teal
tecs.io.http.plugin.Request.stallTimeoutMs: number
```

<a id="tecs.io.http.plugin.Request.maxBytes"></a>
##### tecs.io.http.plugin.Request.maxBytes <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the body byte limit, overriding the client's
value.


```teal
tecs.io.http.plugin.Request.maxBytes: integer
```

<a id="tecs.io.http.plugin.Response"></a>
#### tecs.io.http.plugin.Response <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

What replaces a `Request` once the transfer settles.

Present whatever happened, because "the request finished" is the event
a system waits for and a failure is one of the ways it can finish.
`error` is what says which.


```teal
record tecs.io.http.plugin.Response is Component
    status: integer
    headers: {string: string}
    body: Stream
    url: URI
    error: string
end
```

##### Interfaces

| Interface |
| --- |
| [`Component`](/modules/ecs/#tecs.ecs.Component) |

<a id="tecs.io.http.plugin.Response.status"></a>
##### tecs.io.http.plugin.Response.status <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Engine-owned. Reports the HTTP status code, or zero when the
transfer never received one.


```teal
tecs.io.http.plugin.Response.status: integer
```

<a id="tecs.io.http.plugin.Response.headers"></a>
##### tecs.io.http.plugin.Response.headers <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Engine-owned. Reports response headers with lower-cased names, in
the joined form `Response.headers` uses. A component is one value
per name, so a repeated `set-cookie` keeps only its first value
here; a system that needs every cookie sends its request through a
client and reads `Response:getAll`.


```teal
tecs.io.http.plugin.Response.headers: {string: string}
```

<a id="tecs.io.http.plugin.Response.body"></a>
##### tecs.io.http.plugin.Response.body <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Engine-owned. Provides a one-shot progressive response body.
Despawning this entity closes a body that remains unread.


```teal
tecs.io.http.plugin.Response.body: Stream
```

<a id="tecs.io.http.plugin.Response.url"></a>
##### tecs.io.http.plugin.Response.url <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Engine-owned. Reports the URI that actually answered, or nil when
the request failed before it supplied a valid URI.


```teal
tecs.io.http.plugin.Response.url: URI
```

<a id="tecs.io.http.plugin.Response.error"></a>
##### tecs.io.http.plugin.Response.error <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Engine-owned. Reports why the transfer did not complete, or nil
when it did. A 404 is not one of these: it is a `status` of 404 and
no error.


```teal
tecs.io.http.plugin.Response.error: string
```

<a id="tecs.io.http.plugin.Pending"></a>
#### tecs.io.http.plugin.Pending <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

On an entity whose request is in flight. Internal, and the reason a
request is sent once rather than every frame.

A marker, while the callback and transfer state remain in the plugin.
It is transient because runtime transport state cannot be saved. A save
taken mid-request keeps the `Request`, drops this marker, and sends the
request again after loading.


```teal
record tecs.io.http.plugin.Pending is Component
end
```

##### Interfaces

| Interface |
| --- |
| [`Component`](/modules/ecs/#tecs.ecs.Component) |

<a id="tecs.io.http.plugin.clientOf"></a>
#### tecs.io.http.plugin.clientOf <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

The world's client, or nil when the plugin is not installed.


```teal
function tecs.io.http.plugin.clientOf(World): Client
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `#1` | [`World`](/modules/ecs/#tecs.World) |  |

##### Returns

| Type | Description |
| --- | --- |
| `Client` |  |

<a id="tecs.io.http.plugin.close"></a>
#### tecs.io.http.plugin.close <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Closes the world's client and forgets it.


```teal
function tecs.io.http.plugin.close(World)
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `#1` | [`World`](/modules/ecs/#tecs.World) |  |

##### Returns

None.

<a id="tecs.io.http.plugin.install"></a>
#### tecs.io.http.plugin.install <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Installs the plugin: `world:addPlugin(tecs.io.http.plugin.install)`.

Takes options because the plugin builds the world's client, and a game
that wants a `userAgent` on it has nowhere else to say so:
`world:addPlugin(function(w) http.plugin.install(w, {...}) end)`.


```teal
function tecs.io.http.plugin.install(World, Options)
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `#1` | [`World`](/modules/ecs/#tecs.World) |  |
| `#2` | `Options` |  |

##### Returns

None.

<a id="tecs.io.http.Request"></a>
### tecs.io.http.Request <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

`Request` describes one request and requires only
`url`.


```teal
record tecs.io.http.Request
    url: URI
    method: string
    headers: {string: string}
    body: string | iotypes.ReadableStream
    timeoutMs: number
    stallTimeoutMs: number
    maxBytes: integer
end
```

<a id="tecs.io.http.Request.url"></a>
#### tecs.io.http.Request.url <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets an absolute URL with an `http` or `https`
scheme.


```teal
tecs.io.http.Request.url: URI
```

<a id="tecs.io.http.Request.method"></a>
#### tecs.io.http.Request.method <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the method. Defaults to GET.


```teal
tecs.io.http.Request.method: string
```

<a id="tecs.io.http.Request.headers"></a>
#### tecs.io.http.Request.headers <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets headers merged over the client's defaults.
A `Content-Length` must contain decimal digits and must match a
body whose length is known.


```teal
tecs.io.http.Request.headers: {string: string}
```

<a id="tecs.io.http.Request.body"></a>
#### tecs.io.http.Request.body <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets bytes to send. A general stream opens one
reader and feeds a bounded upload queue. On the SDL storage backend,
a file stream is opened and read directly by the native HTTP lane.
The client owns cooperative work that waits on a composed reader.


```teal
tecs.io.http.Request.body: string | iotypes.ReadableStream
```

<a id="tecs.io.http.Request.timeoutMs"></a>
#### tecs.io.http.Request.timeoutMs <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Overrides the client's positive whole-transfer
timeout.


```teal
tecs.io.http.Request.timeoutMs: number
```

<a id="tecs.io.http.Request.stallTimeoutMs"></a>
#### tecs.io.http.Request.stallTimeoutMs <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Overrides the client's no-progress timeout.


```teal
tecs.io.http.Request.stallTimeoutMs: number
```

<a id="tecs.io.http.Request.maxBytes"></a>
#### tecs.io.http.Request.maxBytes <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Overrides the client's body limit. Zero is
unbounded.


```teal
tecs.io.http.Request.maxBytes: integer
```

<a id="tecs.io.http.Response"></a>
### tecs.io.http.Response <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

`Response` describes status, headers, and a progressive response body.
`headers` joins a repeated header's values, and `Response:getAll`
reports them one by one, which is what `set-cookie` needs.


```teal
record tecs.io.http.Response
    status: integer
    headers: {string: string}
    body: iotypes.Stream
    url: URI

    getAll: function(self, name: string): {string}
    ok: function(self): boolean
end
```

<a id="tecs.io.http.Response.status"></a>
#### tecs.io.http.Response.status <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Read-only. Reports the status after redirects.


```teal
tecs.io.http.Response.status: integer
```

<a id="tecs.io.http.Response.headers"></a>
#### tecs.io.http.Response.headers <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Read-only. Reports final response headers with lower-cased names.
A name the server sent more than once holds its values joined with
`", "`, which RFC 9110 permits for every field except `Set-Cookie`.
A repeated `set-cookie` holds only the first value here, because
joining cookies changes what they mean. `Response:getAll` reports
every value of any name.


```teal
tecs.io.http.Response.headers: {string: string}
```

<a id="tecs.io.http.Response.body"></a>
#### tecs.io.http.Response.body <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Read-only. Provides a one-shot progressive response body. Reading
may suspend a system or block a direct caller until bytes arrive.
The caller must consume, discard, or close this owned stream.


```teal
tecs.io.http.Response.body: iotypes.Stream
```

<a id="tecs.io.http.Response.url"></a>
#### tecs.io.http.Response.url <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Read-only. Reports the effective URL after redirects.


```teal
tecs.io.http.Response.url: URI
```

<a id="tecs.io.http.Response.getAll"></a>
#### tecs.io.http.Response:getAll <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Returns every value the server sent for one header name.

This is the accessor for a repeated header, and the only correct
way to read `set-cookie`, which cannot be joined.


```teal
function tecs.io.http.Response.getAll(self, name: string): {string}
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Response` | The response to read. |
| `name` | `string` | The caller supplies a header name, and the lookup ignores case. |

##### Returns

| Type | Description |
| --- | --- |
| `{string}` | Returns a new array in the order the server sent the values, or an empty array when the response has no such header. The array belongs to the caller. |

<a id="tecs.io.http.Response.ok"></a>
#### tecs.io.http.Response:ok <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Whether the status is in the 2xx range.


```teal
function tecs.io.http.Response.ok(self): boolean
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Response` |  |

##### Returns

| Type | Description |
| --- | --- |
| `boolean` |  |

## Functions

<a id="tecs.io.http.getOpenClientCount"></a>
### tecs.io.http.getOpenClientCount <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Returns the open-client count.



```teal
function tecs.io.http.getOpenClientCount(): integer
```

#### Arguments

None.

#### Returns

| Type | Description |
| --- | --- |
| `integer` | Returns the process-wide count of clients not yet closed. |