Skip to content

Fetch an HTTP response with an explicit limit ​

The embedded kinmokusei/http client keeps transport policy and response size visible. This example supplies an in-memory Go http.RoundTripper, so the complete response path executes without opening a socket or depending on an external service.

Source ​

ts
import { sendWith } from "kinmokusei/http";
import go fmt from "fmt";
import go http from "net/http";
import go io from "io";
import go strings from "strings";

class StaticTransport implements http.RoundTripper {
  public function roundTrip(request: *http.Request): Result<*http.Response> {
    const headers: http.Header = makeMap[bstring, bstring[]]();
    headers.Set("X-Source", "warm");
    const response = http.Response{
      StatusCode: http.StatusOK,
      Header: headers,
      Body: io.NopCloser(strings.NewReader("hello")),
      Request: request,
    };
    return ok(&response);
  }
}

function main(): void {
  const client = http.Client{Transport: new StaticTransport()};
  const [request, requestErr] = http.NewRequest(
    http.MethodGet,
    "http://fixture.invalid",
    nil,
  );
  if (requestErr !== nil) {
    fmt.Println("unexpected:", requestErr.Error());
    return;
  }

  const [response, err] = sendWith(&client, request, int64(5));
  if (err !== nil) {
    fmt.Println("unexpected:", err.Error());
    return;
  }
  const [text, textErr] = response.text();
  if (textErr !== nil) { fmt.Println(textErr); return; }
  fmt.Println(
    response.status,
    response.ok(),
    response.header("X-Source"),
    text,
  );
  const bodyCopy = response.bytes();
  bodyCopy[0] = byte(88);
  fmt.Println(bstring(bodyCopy), response.rawText());

  const [_, limitErr] = sendWith(&client, request, int64(4));
  fmt.Println(limitErr !== nil);
}

Run ​

sh
keika check bounded-http-fetch.km
keika run bounded-http-fetch.km

Expected output:

text
200 true warm hello
Xello hello
true

Success path ​

StaticTransport is a Kinmokusei class that explicitly implements the imported Go http.RoundTripper interface. Its roundTrip method returns a normal *http.Response through Result, which lowers to the interface's (*http.Response, error) method shape.

sendWith uses the caller-owned http.Client, reads and closes the response body, clones the response headers, and returns a Response value. The limit is measured in response-body bytes; the five-byte body hello fits an int64(5) limit exactly.

response.ok() means the status is from 200 through 299. Other HTTP statuses still produce a successful Response; transport, request construction, body reading, cancellation, and configured-limit failures use the Result<Response> error path.

response.text() returns Result<string> after UTF-8 validation. The example handles its error explicitly. response.bytes() returns a new slice; changing its first byte produces Xello, while response.rawText() still returns hello. Callers cannot mutate the stored body through the returned slice.

Oversize path ​

The second call permits only four bytes. The adapter reads at most one byte beyond the configured limit, closes the body, and returns an error instead of exposing a truncated success value. The final true confirms that boundary without depending on the diagnostic text.

In an application, use fetch or fetchLimited for a context-bound GET. Use send for another caller-built request and sendWith when timeout, transport, or connection-pool policy belongs to an explicit http.Client.

See the kinmokusei/http API for every client function and HTTP applications for server and lifecycle choices.

Kinmokusei is a pre-1.0 project. Documentation describes implemented behavior.