testing/transports/raw_http.ts

Raw-socket HTTP/1.1 exchanges, for tests that need to control exactly which bytes reach the server.

fetch frames a request itself and sends all of it, so some server behaviors can't be reached through it: what a server does with two requests in one write, with duplicate or malformed headers, with a request head whose body never follows, or with a chunked body that is never terminated. This writes caller-built bytes over node:net and hands back what the server sent, plus just enough parsing to read a status or one whole response.

Everything is latin1-decoded, so a string's length is its byte length.

Plain TCP only: an https: URL is not spoken to over TLS, and the host must be a name or an IPv4 address — a bracketed IPv6 literal does not connect.

view source

Declarations
#

7 declarations

raw_http_count_responses
#

testing/transports/raw_http.ts view source

(raw: string): number import {raw_http_count_responses} from '@fuzdev/fuz_app/testing/transports/raw_http.js';

Count HTTP response status lines in a raw byte stream. Deliberately unanchored (no ^/m): a second pipelined response is concatenated straight after the first response's body, which carries no trailing newline, so a line-anchored match would miss it — and missing a smuggled second response is a silent false negative. It counts exactly the status lines as long as no response header or body contains the literal HTTP/1.x NNN.

raw

type string

returns

number

raw_http_exchange
#

testing/transports/raw_http.ts view source

(base_url: string, request_bytes: string, options: RawHttpExchangeOptions): Promise<RawHttpExchange> import {raw_http_exchange} from '@fuzdev/fuz_app/testing/transports/raw_http.js';

Open a raw TCP socket to base_url, write request_bytes once, and collect what the server sends back until it closes the connection, a whole response has arrived (until: 'response'), or read_timeout_ms elapses.

Write errors are swallowed: a server that refuses a request and closes mid-upload surfaces as EPIPE / ECONNRESET on the unfinished write, and what a caller asserts on is what was read back. A write error also ends the socket, so bytes the server sent just before it can go unread — a caller that needs to read a refusal reliably sends nothing the server will leave unread.

base_url

the server's base URL; only its host and port are used

type string

request_bytes

the bytes to send, latin1-encoded

type string

options

returns

Promise<RawHttpExchange>

raw_http_first_status
#

testing/transports/raw_http.ts view source

(raw: string): number | null import {raw_http_first_status} from '@fuzdev/fuz_app/testing/transports/raw_http.js';

The status code of the first HTTP response in a raw byte stream, or null if none.

raw

type string

returns

number | null

raw_http_parse_response
#

testing/transports/raw_http.ts view source

(raw: string): RawHttpResponse | null import {raw_http_parse_response} from '@fuzdev/fuz_app/testing/transports/raw_http.js';

Parse the first response in a raw byte stream, once all of it has arrived.

The body is delimited by Transfer-Encoding: chunked or Content-Length. A response carrying neither is delimited by the connection closing, which the bytes alone don't show, so its body is whatever followed the head.

raw

the bytes read so far, latin1-decoded

type string

returns

RawHttpResponse | null

the response, or null when the head or the framed body is incomplete

RawHttpExchange
#

testing/transports/raw_http.ts view source

RawHttpExchange import type {RawHttpExchange} from '@fuzdev/fuz_app/testing/transports/raw_http.js';

What a raw exchange read back, and how it ended.

received

Every byte the server sent, latin1-decoded.

type string

readonly

closed_by_server

true when the connection ended before the exchange stopped reading — the server closed it, or it never opened (a refused or unresolvable address reads as closed, with nothing received).

type boolean

readonly

RawHttpExchangeOptions
#

testing/transports/raw_http.ts view source

RawHttpExchangeOptions import type {RawHttpExchangeOptions} from '@fuzdev/fuz_app/testing/transports/raw_http.js';

Options for raw_http_exchange.

read_timeout_ms

How long to read before giving up on the server.

type number

readonly

until?

When the exchange stops reading. 'close' reads until the server closes the connection; 'response' stops as soon as one whole response has arrived (raw_http_parse_response), for a server that answers and then keeps the connection open. Either way the read timeout bounds it.

'response' stops at the first response the bytes frame, so it is for a final response carrying Content-Length or chunked framing: a 1xx interim response ends the read, and so does the head of a response delimited by the connection closing, before its body.

type "close" | "response"

readonly
default 'close'

RawHttpResponse
#

testing/transports/raw_http.ts view source

RawHttpResponse import type {RawHttpResponse} from '@fuzdev/fuz_app/testing/transports/raw_http.js';

One parsed HTTP/1.1 response.

status

type number

readonly

headers

Response headers, names lowercased; a repeated name keeps its last value.

type Readonly<Record<string, string>>

readonly

body

The response body, with any chunked framing removed.

type string

readonly

Depends on
#

Imported by
#