
# tecs.io.http


Asynchronous HTTP and HTTPS.

```teal
local endpoint <const> = tecs.io.URI.new(
    "https://example.com/manifest.json"
)
tecs.io.http.newClient({userAgent = "mygame/1.0"})
    :send({url = endpoint})
    :map(function(response: tecs.io.http.Response): string
        local body <const> = response.body
        if body is tecs.io.ReadableStream then
            return body:readAll()
        end
        error("the response destination is not readable")
    end)
    :onSettle(function(manifest: tecs.Future<string>)
        print(manifest.value)
    end)
```

The process runtime turns every open client once per iteration, so requests
advance without game code pumping them.

An HTTP error status still produces a ready response. A failed future means
that DNS, connection, TLS, timeout, or streaming produced no response.

Call `Client:close` when you no longer need its connection pool. Losing the
last Lua reference does not cancel its requests. A headless tool calls
[`tecs.runtime.poll`](/modules/runtime/#tecs.runtime.poll);
[`Application`](/modules/Application/) calls it once per frame.

## 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 the futures using it. |
| [`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 what a completed transfer settles to regardless of status code. |

### 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}).value
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 the futures using it.

Closing the client cancels every pending request, releases the pool,
and remains safe to repeat. A client also drives its futures as their
source, but an application or `tecs.runtime.poll` normally performs
that work rather than game code calling `poll` or `advance` directly.


```teal
interface tecs.io.http.Client is Closeable
    sliceMs: number
    defaultWaitMs: number

    advance: function(self, ms: number): integer
    cancel: function(self, future: Future<any>)
    pending: function(self): integer
    poll: function(self): integer
    pump: function(self): integer
    send: function(self, request: Request): Future<Response>
end
```

#### Interfaces

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

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

Engine-owned. Sets the maximum duration of one blocking future
wait slice. Ordinary game code should ignore it.


```teal
tecs.io.http.Client.sliceMs: number
```

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

Engine-owned. Sets the timeout used when `Future:wait` receives no
explicit timeout. Ordinary game code should ignore it.


```teal
tecs.io.http.Client.defaultWaitMs: number
```

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

Waits briefly for an event and drains the events then ready.

`Future:wait` calls this through its source. Application code
normally does not call it directly.


```teal
function tecs.io.http.Client.advance(self, ms: number): integer
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Client` | The open client to advance. |
| `ms` | `number` | The caller supplies the maximum milliseconds to wait. |

##### Returns

| Type | Description |
| --- | --- |
| `integer` | Returns the number of response events processed. |

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

Cancels the request belonging to a future.

A settled future or a future from another source changes nothing.


```teal
function tecs.io.http.Client.cancel(self, future: Future<any>)
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Client` | The client that owns the request. |
| `future` | [`Future`](/modules/Future/)`<any>` | The caller supplies the request future to cancel. |

##### Returns

None.

<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.poll"></a>
#### tecs.io.http.Client:poll <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Polls this client as a future source without blocking.

Application code normally lets the process runtime call this.


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

##### Arguments

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

##### Returns

| Type | Description |
| --- | --- |
| `integer` | Returns the number of response events processed. |

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

Drains every response event currently ready without blocking.

Application code normally lets the process runtime call this.


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

##### Arguments

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

##### Returns

| Type | Description |
| --- | --- |
| `integer` | Returns the number of response events processed. |

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

Starts one HTTP transfer and returns immediately.

A transport failure settles the future as failed. An HTTP error
status settles it as ready with that status in the response.


```teal
function tecs.io.http.Client.send(
    self, request: Request
): Future<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, body, destination, timeouts, and byte limit. |

##### Returns

| Type | Description |
| --- | --- |
| [`Future`](/modules/Future/)`<Response>` | Returns a future settled by the process runtime. |

<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. `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 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 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.


```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.


```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
        into: string | WritableStream
        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
    into: string | WritableStream
    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.into"></a>
##### tecs.io.http.plugin.Request.into <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets where the body goes. Left out, the response
carries a replayable in-memory [`Stream`](/modules/io/#tecs.io.Stream).
A snapshot rejects a
`tecs.io.newHandleStream` here because its live handle cannot
be reconstructed.


```teal
tecs.io.http.plugin.Request.into: string | WritableStream
```

<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.


```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 the body wherever it went.


```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, and the future it stands for is not a field on it: a future
holds listeners and the source that settles them, so nothing a save
writes can carry one. Transient for the same reason, which is what makes
a save taken mid-request coherent: the `Request` survives, this does not,
and the load sends it again.


```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
    into: string | iotypes.WritableStream
    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 stream opens one reader when
this request begins and feeds it through a bounded upload queue.


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

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

Caller-writable. Sets where response chunks are written. A string
is a file path.


```teal
tecs.io.http.Request.into: string | iotypes.WritableStream
```

<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 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 what a completed transfer
settles to regardless of status code.


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

    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.


```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 response bytes in memory or in the requested
destination.


```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.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. |