Skip to content

Req v0.2.0

Latest

Choose a tag to compare

@github-actions github-actions released this 02 Nov 03:38
· 2 commits to main since this release
88617b3

Req.mojo 0.2.0

Req is a synchronous HTTP client for Mojo. Version 0.2.0 adds HTTP/2,
file and multipart uploads, proxies, connection pool limits, and more ways to
stream responses and test HTTP integrations.

What's new

  • Use opt-in HTTP/2 with connection reuse and overlapping response streams,
    with HTTP/1.1 fallback enabled by default.
  • Upload files incrementally, send finite byte chunks, and combine multipart
    files with ordinary form fields.
  • Route requests through HTTP/HTTPS proxies, including authenticated proxies,
    or opt in to proxy and CA environment settings.
  • Limit physical connections and keepalive retention; configure capacity waits
    with Timeout.pool and handle PoolTimeout separately.
  • Read response streams as decoded bytes, original encoded bytes, text, or lines.
  • Add request/response hooks and supply mock or custom transports for tests.
  • Inspect redirect history, the next prepared request, per-response cookies,
    and elapsed time.

Install with Pixi

From a Pixi workspace configured for Mojo,
add the official Modular Community channel and install or upgrade Req:

pixi workspace channel add --prepend https://repo.prefix.dev/modular-community
pixi add "req==0.2.0"

The community package
is awaiting publication. The version-pinned command becomes available once
0.2.0 is published to the channel.
Until then, use the precompiled downloads
or source build below.

Req uses Mojo 1.1.0 on Linux x86-64, Linux ARM64, and macOS ARM64.
Pixi installs the matching compiler and native dependencies. The package includes
Req's precompiled module, CPU JSON modules, and native shared library; no C build
or extra linker flags are needed.

Send your first request

Save this as main.mojo in your workspace root:

import req


def main() raises:
    var response = req.get("https://example.com")
    response.raise_for_status()
    print(response.status_code)
    print(response.headers["Content-Type"])
    print(response.text())

Run it directly with pixi run mojo main.mojo, or compile and run it:

pixi run mojo build main.mojo -o main
pixi run ./main

HTTP/2, proxies, and pool limits

import req


def main() raises:
    var owner = req.Client(
        http2=True,
        limits=req.Limits(max_connections=10, max_keepalive_connections=5),
        timeout=req.Timeout(connect=3.0, read=10.0, write=10.0, pool=2.0),
    )
    with owner.context() as client:
        var response = client.get("https://example.com")
        response.raise_for_status()
        print(response.http_version)

HTTP/2 is opt-in and requires libcurl with HTTP/2 support; HTTP/1.1 fallback
remains enabled. HTTP/2-only mode (http1=False, http2=True) requires libcurl
8.10 or later. Add proxy="http://127.0.0.1:8080" for an explicit HTTP/HTTPS
proxy, or trust_env=True to read proxy/CA environment configuration.
Pool waits use Timeout.pool and raise PoolTimeout.
See HTTP/2 and
proxies.

File and multipart uploads

Send a file incrementally with
body=req.RequestBody.from_file("report.csv"), or combine multipart
files and ordinary fields:

import req


def main() raises:
    var files = List[req.UploadFile]()
    files.append(req.UploadFile.from_bytes(
        "file", req.encode_utf8("hello\n"),
        filename="hello.txt", content_type="text/plain",
    ))
    var response = req.post(
        "https://httpbin.org/post",
        files=files,
        data=req.QueryParams("tag=mojo&tag=http"),
    )
    response.raise_for_status()
    print(response.status_code)

Files and byte bodies are replayable. Finite RequestBody.from_chunks(...)
sources are one-shot by default; resending one after consumption raises
StreamConsumed. See uploads
for body combinations and redirect behavior.

Stream bytes, text, and lines

import req


def main() raises:
    with req.stream("GET", "https://example.com") as response:
        response.raise_for_status()
        for line in response.iter_lines():
            print(line)
        print(response.elapsed())

Use iter_bytes() for decoded bytes, iter_raw() for original content-encoded
bytes without HTTP transfer framing, and iter_text() for incremental text
decoding. Context exit closes partially consumed responses too.
See streaming.

Hooks, transports, and response metadata

  • EventHooks run request and
    response callbacks in order, including each followed redirect.
  • MockTransport and custom transports
    let tests supply responses without a network server.
  • response.history retains closed intermediate responses.
    response.next_request exposes the next prepared request for an unfollowed
    redirect. response.cookies is a per-response snapshot.
  • response.elapsed() reports seconds from sending until reading or closing
    completes; accessing it earlier raises StreamNotRead.

Defaults and upgrading from 0.1.0

Existing basic request calls keep their defaults: verified TLS, HTTP/1.1,
no followed redirects, and five seconds per timeout phase.
Timeout(seconds) and Timeout.disabled() now include the pool phase.
Environment routing remains off unless trust_env=True.
HTTP 4xx/5xx requires raise_for_status() to become an error.

Use a precompiled download

Release assets are provided for Linux x86-64, Linux ARM64, and
macOS ARM64, all built with Mojo 1.1.0. Download the archive matching
your machine and verify it against SHA256SUMS. Each archive includes
req.mojoc, the native transport, CPU JSON modules, licenses, and pinned
Pixi environment files.

Use an existing Mojo 1.1.0 environment with libcurl 7.85+ and zlib. Point Mojo's
-I option at the extracted directory and set REQ_NATIVE_LIB to the absolute
path of its libreq_curl.so (Linux) or libreq_curl.dylib (macOS).
See the archive instructions
for complete run and build commands.

Build from source

Source builds require Pixi, a C compiler, libcurl 7.85+ development headers
with TLS support, and zlib development headers. Install Command Line Tools
on macOS, or build-essential libcurl4-openssl-dev zlib1g-dev openssl on
Debian/Ubuntu, then:

git clone --branch v0.2.0 --depth 1 https://github.com/mojoto/req.mojo.git
cd req.mojo
pixi install
make build

Save the first example as main.mojo in the repository root and run
pixi run mojo -I . main.mojo. Req finds the native transport in build/.

Learn more

Clients remain single-threaded. There is no Async API, overall request deadline,
or configurable application retry policy. Keep one Client per worker and
consume or close responses before releasing its context.