NURLNURL registrynurl-lang.org →

← all packages

grpc

owner @Hindurable

repository https://github.com/nurl-lang/nurl/tree/main/packages/gRPC

Install

[dependencies]
grpc = "^0.3.0"

Versions

Dependencies (latest)

None.

gRPC

Native gRPC over HTTP/2 for NURL. The library transports protobuf bytes and supports unary, client streaming, server streaming and bidirectional calls. TCP, TLS, HTTP/2, HPACK, gzip and protobuf use NURL's standard library. Requires NURL 0.72.0 or newer.

[dependencies]
grpc = "^0"

Import deps/grpc/src/grpc.nu, or client.nu / server.nu separately. The repository directory is packages/gRPC; the registry name is grpc. Run nurlpkg install from the consumer's directory after adding the dependency.

Client

$ `deps/grpc/src/client.nu`

@ echo GrpcClient client ( Vec u ) request → !v GrpcError {
    : ( Vec Header ) metadata ( grpc_metadata_new )
    : ~ GrpcCallOptions options ( grpc_call_options )
    = . options timeout_ns 5000000000
    : GrpcUnaryResponse reply \ ( grpc_unary client
        `/example.Echo/Unary` request metadata options )
    // Decode reply.data with stdlib/ext/protobuf.nu and the service schema.
    ^ @ !v GrpcError { T 0 }
}

Nothing is released by hand: metadata, replies, messages, statuses, errors and events are values their owner drops, a GrpcClient is a handle whose last owner (the client binding and every call opened on it) disconnects the transport it opened, a dropped GrpcCall cancels an unfinished call, and a dropped GrpcServer flushes and releases its HTTP/2 state. The *_free functions and grpc_client_close remain as optional early releases.

grpc_client_connect_tls(host, port, verify) verifies certificates when verify is true and requires ALPN h2. SSL_CERT_FILE selects a private CA bundle. grpc_client_connect_h2c(host, port) explicitly selects cleartext HTTP/2 prior knowledge. Each call holds a share of its client, so the transport stays up until the client and its last call are gone.

For streaming, open a GrpcCall with grpc_call_open(client, path, metadata, options), send borrowed payloads with grpc_call_send, and finish the request side with grpc_call_half_close. grpc_call_receive returns an owned GrpcMessage: present = true includes an actual message, even when its payload is empty. present = false means successful completion. A non-OK status returns GrpcError after any preceding response messages.

Requests and responses may overlap: bidirectional calls can receive before half-closing. A client and its calls have one owner and one driver; concurrent calls share HTTP/2 streams, and the application drives their progress. Sending into a full bounded queue reports RESOURCE_EXHAUSTED; receive/pump existing traffic before retrying. Calls are never retried automatically.

Call options specify the deadline duration in nanoseconds (0 means no deadline), send/receive message limits, metadata limit, and GRPC_IDENTITY or GRPC_GZIP request compression. Default message size is 4 MiB; default metadata size is 8 KiB. Limits apply to both compressed and decompressed message bytes. grpc_call_cancel cancels one call; dropping an unfinished call cancels it too.

Server

Use grpc_server_new(tcp, limits) on an accepted HTTP/2 connection, then drive grpc_server_next with a mutable GrpcServer. grpc_server_limits() provides bounded defaults. Events carry a stream ID and one of:

contains any request trailers.

Send initial metadata with grpc_server_send_metadata, messages with grpc_server_send, and finish with grpc_server_finish(server, stream_id, status, trailing_metadata). Finishing queues mandatory status trailers after pending messages; errors may finish without messages. grpc_server_flush advances queued writes without reading. Application handlers decide method routing, cardinality, authorization and protobuf schema rules. Stop application work on cancellation, and keep slow work out of the connection's driver. The server never owns its TCP connection: let the server go (its drop flushes the HTTP/2 connection), then close the socket.

For scheduled messages or application work, grpc_server_next_until(server, deadline_ns) uses an absolute monotonic polling deadline and returns a control event when it expires. This does not cancel RPCs. grpc_server_deadline(server, stream_id) returns the RPC's absolute deadline (0 means none), and grpc_server_is_cancelled lets work check cancellation or expiry before continuing. The driver must keep polling to observe peer cancellations.

For TLS listeners use tcp_listen_tls_with_alpn(..., "h2") (NURL source uses backticks around string literals). The test server shows all four call patterns with cleanup; it deliberately accepts one connection so sanitizer tests can check the whole lifecycle.

Metadata and errors

Metadata is a Vec[Header]. Add printable ASCII with grpc_metadata_add, and binary values with grpc_metadata_add_binary; binary names end in -bin. Application binary values are raw, binary-safe Strings. The library handles padded/unpadded Base64 and comma-joined binary values on the wire. Duplicate metadata is preserved. Reserved transport keys cannot be injected through application metadata.

GrpcError owns its message (dropped with it). All 17 status codes are available as GRPC_* constants. GrpcStatus also carries optional serialized google.rpc.Status details. The library checks that a details code agrees with grpc-status. Status messages use UTF-8 percent encoding; malformed percent escapes remain readable. Missing status never counts as success.

The library follows the gRPC HTTP/2 protocol and HTTP-to-gRPC fallback status mapping. It does not generate code from .proto files. Use the standard protobuf codec for service-specific message readers and writers; the transport accepts any payload serializer.

Validation

Run nurlpkg test from this package's directory to exercise its standalone wire, metadata and compression tests. The peer programs in tests/fixtures/ are driven by the repository's interoperability suite:

python -m pip install -r packages/gRPC/tests/requirements.txt
python tools/tests/test_grpc.py
NURL_SAN=1 python tools/tests/test_grpc.py

The integration tests use the official gRPC C-core Python runtime in both directions and an independent HTTP/2 peer for malformed/fractured messages. The same suite runs under ASan, UBSan and leak detection. Standard-library regressions additionally exercise HTTP/2 state, Base64 and compression against independent reference implementations.

See DEVELOPMENT.md for release acceptance steps and coverage.