# `http_process_transport`

The `http_process_transport` library provides an alternative implementation of the `http_transport_protocol` protocol. Based on the `process` library and external commands, it provides TLS support for HTTPS and WSS connections. The current implementation uses `openssl s_client` to expose a reusable client-side byte stream suitable for the existing `http_client_core` predicates. The current server-side implementation defaults to `ncat` to own the public listener socket and expose accepted connections to the parent object using a loopback relay listener plus peer metadata parsed from helper diagnostics.

This library requires backend support for the `process` and `socket` libraries. Sequential client-side transport, including reusable connections, one-shot client exchanges, and connection pools, depends on binary process pipes.

When using a backend that doesn’t support threads, this library still supports client-side reusable connections, sequential client pooling, one-shot and reusable client exchanges, and serial single-connection HTTPS and WSS serving. Worker-based serving modes and shutdown control still require backend thread support.

## Requirements

The `openssl` and `ncat` commands must be available on the current `PATH`.

On macOS, both commands can be installed using e.g. Homebrew:

    $ brew install openssl nmap

Or using MacPorts:

    $ sudo port install openssl nmap

On Ubuntu, both commands can be installed using:

    $ sudo apt install openssl ncat

On RedHat distributions (8.x and later):

    $ sudo dnf install openssl nmap-ncat

For older RedHat distributions:

    $ sudo yum install openssl nmap-ncat

On Windows, both commands can be installed using e.g. Chocolatey:

    > choco install openssl
    > choco install nmap

## API documentation

Open the ../../apis/library_index.html#http_process_transport link in a web browser.

## Loading

To load the library, load the `loader.lgt` file:

    | ?- logtalk_load(http_process_transport(loader)).

## Testing

To test this library, load the `tester.lgt` file:

    | ?- logtalk_load(http_process_transport(tester)).

## Current scope

- reusable client connections (`open_connection/4`, `close_connection/1`)

- reusable client connection pools (`open_connection_pool/4`, `close_connection_pool/1`)

- reusable-connection and one-shot exchanges (`exchange/3-4`, `exchange_sequence/3-4`)

- helper-backed plain TCP listeners (`open_listener/4`, `close_listener/1`)

- helper-backed TLS listeners (`open_listener/4` with `listener_transport(tls)`)

- server-side serving (`serve_once/3`, `serve_websocket_once/5`, `serve_listener/4-5`, `serve_until_shutdown/4`, `request_shutdown/1`)

- the same public connection and pool handle shapes used by `http_socket_transport` to keep downstream endpoint validation compatible

## Current limitations

- worker-based serving modes and shutdown control require backend thread support

- the `openssl` executable must be available on the `PATH` unless overridden with the `openssl_executable/1` option

- server-side listeners require `ncat` on the `PATH` unless overridden with the `listener_helper_executable/1` option to use `socat` instead

- the TLS listener implementation is limited to server-side stream exposure and handshake handling; advanced TLS options such as ALPN, client certificate verification, and protocol version tuning are not provided

Connection options accepted by `open_connection/4`:

- `type(binary)`

- `type(text)`

- `connection_transport(tcp)`

- `connection_transport(tls)`

- `openssl_executable(Executable)`

- `server_name(Name)`

- `openssl_arguments(Arguments)`

Notes on those options:

- `type(binary)` and `type(text)` match the shared `http_socket_transport` client-side option surface; the selected value is applied to the client connection streams after the helper process is started

- `connection_transport(tcp)` is the default and uses `ncat` as the helper process

- `connection_transport(tls)` uses `openssl s_client` for the client connection helper process

- the default `server_name(default)` value maps to the requested host except for colon-containing hosts, where the SNI option is omitted by default when `connection_transport(tls)` is selected

- `openssl_arguments/1` can be used to pass verification, CA, ALPN, or client certificate flags directly to `openssl s_client` when `connection_transport(tls)` is selected

Connection-pool options accepted by `open_connection_pool/4`:

- `min_size(N)`

- `max_size(N)`

- `connection_options(Options)`

Listener options accepted by `open_listener/4`:

- `backlog(N)`

- `type(binary)`

- `type(text)`

- `listener_transport(tcp)`

- `listener_transport(tls)`

- `listener_helper_executable(Executable)`

- `temporary_tls_credentials(Prefix)`

- `tls_certificate_file(File)`

- `tls_key_file(File)`

Notes on those listener options:

- `type/1` is accepted for drop-in compatibility with `http_socket_transport` but does not change the internal relay socket type used by the listener implementation

- `listener_helper_executable/1` is a compatibility option name for selecting the helper executable used for the public listener and loopback relay

- `temporary_tls_credentials(Prefix)` generates a temporary self-signed certificate and key owned by the listener when `listener_transport(tls)` is selected; both files are deleted by `close_listener/1` and by the `serve_until_shutdown/4-5` finalization path

- `tls_certificate_file/1` and `tls_key_file/1` are required together when `listener_transport(tls)` is selected unless `temporary_tls_credentials/1` is used instead

- `temporary_tls_credentials/1` is mutually exclusive with `tls_certificate_file/1` and `tls_key_file/1`

Helper predicate:

- `temporary_tls_credentials_files(Prefix, CertificateFile, KeyFile)` computes the temporary certificate and key file paths for a given prefix without creating those files; this is useful for client-side trust configuration when the listener itself owns certificate creation via `temporary_tls_credentials(Prefix)`

Serving options accepted by `serve_listener/5`:

- `shutdown(keep_open)`

- `shutdown(close)`

- `workers(serial)`

- `workers(per_connection)`

- `workers(pool(Size))`

- `workers(pool(Size, rolling))`

Serving options accepted by `serve_until_shutdown/4`:

- `workers(serial)`

- `workers(per_connection)`

- `workers(pool(Size))`

- `workers(pool(Size, rolling))`

Example:

    :- initialization((
        logtalk_load(http_process_transport(loader)),
        http_core::request(get, origin('/'), http(1,1), [host-host('example.com')], empty, [], Request),
        http_process_transport::exchange(
            'example.com',
            443,
            Request,
            Response
        ),
        writeq(Response), nl,
        halt
    )).

The one-shot exchange predicates add `Connection: close` automatically when the request does not already specify connection handling, mirroring the existing `http_socket_transport` behavior.

On the server side, a long-lived helper listener keeps ownership of the public listener socket and relays each accepted connection into a local loopback listener. Peer addresses are recovered from helper diagnostics, allowing the parent object to keep returning `ClientInfo` terms while still exposing real binary streams to `http_server_core` and the existing WebSocket layers. The same listener shape is used for both plain TCP and TLS listeners, which allows the higher-level HTTP and WebSocket layers to serve HTTPS and WSS requests without depending on backend-specific SSL predicates.

## Live smoke tests

The normal `tester.lgt` driver only runs non-network tests. Opt-in live smoke tests are provided in `tests_live.lgt` and can be run using `tester_live.lgt`:

    | ?- logtalk_load(http_process_transport(tester_live)).

The live smoke tests cover two parts:

- external HTTPS client-side smoke tests against a configurable public endpoint

- local loopback server-side smoke tests for plain HTTP, HTTPS, and WSS using the `http_process_transport` listener path

The client-side live smoke tests default to the proven endpoint:

- host: `httpbin.org`

- port: `443`

- path: `/`

The endpoint can be overridden using environment variables before running the driver:

- `LOGTALK_HTTP_SOCKET_PROCESS_LIVE_HOST`

- `LOGTALK_HTTP_SOCKET_PROCESS_LIVE_PORT`

- `LOGTALK_HTTP_SOCKET_PROCESS_LIVE_PATH`

These live tests exercise the one-shot exchange path, reusable connections, sequential reuse on the same connection, and pooled reuse while keeping the normal automated test suite free of external network dependencies.

The server-side live smoke tests generate a temporary self-signed certificate, open local loopback listeners, and then verify:

- plain `serve_once/3`

- TLS `serve_once/3`

- WSS `serve_websocket_once/5` plus a small frame round-trip on the upgraded streams