API Reference
Module
gRPCServer — Module
gRPCServerA native Julia implementation of a gRPC server library.
gRPCServer enables Julia developers to expose services over the gRPC protocol with support for all four RPC patterns (unary, server streaming, client streaming, bidirectional), interceptors, health checking, reflection, TLS/mTLS, and compression.
Quick Start
using gRPCServer# Create serverserver = GRPCServer("127.0.0.1", 50051)# Register your serviceregister!(server, MyService())# Start serverrun(server)See the documentation for more examples and API reference.
Server Types
gRPCServer.GRPCServer — Type
GRPCServerThe main gRPC server managing connections, services, and lifecycle.
Fields
host::String: Server bind addressport::Int: Server portconfig::ServerConfig: Server configurationstatus::ServerStatus.T: Current lifecycle statedispatcher::RequestDispatcher: Request dispatcherhealth_status::Dict{String, HealthStatus.T}: Per-service health statusinflight::Base.Threads.Atomic{Int}: Requests currently admitted into dispatch (load shedding)shed_total::Base.Threads.Atomic{Int}: Total requests rejected at the concurrency capcontext::Any: Server-level payload threaded into each request'sServerContext.payload
Configuration keywords
The HTTP/2 backend is selected with http2_backend::AbstractHTTP2Backend (default HTTPjlBackend); context::Any carries a server-level payload. The remaining configuration keywords mirror the ServerConfig fields: max_message_size, max_receive_message_length, max_send_message_length, max_concurrent_streams, max_connections, max_concurrent_requests, max_queued_requests, keepalive_interval, keepalive_timeout, idle_timeout, drain_timeout, read_header_timeout, read_timeout, write_timeout, max_header_bytes, reuseaddr, backlog, tls::Union{TLSConfig, Nothing}, enable_health_check, enable_reflection, debug_mode, log_requests, compression_enabled, compression_threshold, supported_codecs, h2_initial_window_size, h2_connection_window_size.
Backends do not support every feature. Explicitly specifying a keyword the chosen backend cannot honor raises UnsupportedFeatureError at construction instead of silently ignoring it (omitted keywords never raise). Per-backend defaults and the supported keyword set are declared by backend_defaults and backend_capabilities; for convenience, see the backend-specific constructors GRPCServerHTTPJl, GRPCServerPureHTTP2, and GRPCServerNghttp2, whose docstrings list each backend's raising keywords.
Example
server = GRPCServer("0.0.0.0", 50051)register!(server, GreeterService())run(server)gRPCServer.ServerConfig — Type
ServerConfigConfiguration container for gRPC server options.
Fields
Connection Limits
max_connections::Union{Int, Nothing}: Maximum concurrent connections (nothing = unlimited)max_concurrent_streams::Int: Maximum streams per connection (default: 100)max_concurrent_requests::Union{Int, Nothing}: Maximum concurrent requests (default: 1024;nothingor 0 = unlimited, matching the legacy csvance semantics). The admission gate sheds a call arriving past the cap immediately with a trailers-onlyRESOURCE_EXHAUSTEDstatus — no queue, no waiting (seemax_queued_requests). Ships enabled because HTTP.jl allows 100 concurrent streams per connection, so with the cap unset N connections yield 100·N concurrent handler tasks; 1024 bounds that by default while staying well above typical concurrency.max_queued_requests::Int: NOT IMPLEMENTED — accepted for API compatibility only. No request queue exists: a call arriving pastmax_concurrent_requestsis shed immediately with a trailers-onlyRESOURCE_EXHAUSTEDstatus (no queueing, no waiting). The value has no effect, and explicitly setting it atGRPCServerconstruction raisesUnsupportedFeatureError(default: 1000)
Message Limits
max_message_size::Int: Maximum message size in bytes (default: 4MB). Seeds both the receive and send caps; override one side withmax_receive_message_length/max_send_message_length(each defaults tomax_message_size). The receive cap is enforced by the framing layer on incoming request messages (HTTPjl backend); the send cap is enforced when encoding response messages. TheServerConfig.max_message_sizefield always reports the larger of the two.
Timeouts (in seconds)
keepalive_interval::Union{Float64, Nothing}: Interval for keepalive pings (nothing = disabled)keepalive_timeout::Float64: Timeout for keepalive response (default: 20.0)idle_timeout::Union{Float64, Nothing}: Close idle connections after this time (default: 300;nothing= never). Aligns with the legacyserve!default. A connection that stops sending bytes — including one holding a partial request body — is closed after this window, bounding slow-body memory accrual.drain_timeout::Float64: Maximum time to wait for graceful shutdown (default: 30.0)read_header_timeout::Union{Float64, Nothing}: Max seconds to read request headers before the connection is closed (default: 30.0; nothing disables). Passed through to the HTTP.jl listener.read_timeout::Union{Float64, Nothing}: Max seconds to read request data (nothing = disabled, the default). Enabling it defends against a peer that trickles or never finishes a request body, but it also terminates legitimately idle long-lived streaming connections, so set it only for unary or short-lived workloads —idle_timeout(on by default) already bounds stalled bodies at coarser granularity. Passed through to the HTTP.jl listener.write_timeout::Union{Float64, Nothing}: Max seconds to write response data (nothing = disabled, the default). Passed through to the HTTP.jl listener.
Deadline semantics
grpc-timeout is parsed strictly into ctx.deadline (INVALID_ARGUMENT if malformed). The deadline is enforced at two points, never mid-execution: a fail-fast pre-check before the handler runs (an already-expired deadline fails with trailers-only DEADLINE_EXCEEDED and the handler is not invoked), and a post-return mapping once the handler has finished. A handler that runs past its deadline is not interrupted — it runs to completion and its result is then mapped to DEADLINE_EXCEEDED. Handlers that must bound their own runtime should check remaining_time/is_cancelled cooperatively or install TimeoutInterceptor (also pre-check-only). Watchdog-based cancellation and a server-side default deadline are future work. Unbounded handler runtime is the main amplification vector for resource exhaustion: pair cooperative deadline checks with a max_concurrent_requests cap sized to memory (see the DoS posture note below).
DoS posture
The server trusts a peer only up to the configured limits. The shipped defaults are conservative for a reason: HTTP.jl allows 100 concurrent streams per connection, so without a cap N connections imply 100·N concurrent handler tasks, and a stalled request body holds memory until the peer finishes it or the connection is reaped. The defaults bound both — max_concurrent_requests = 1024 caps concurrent handler tasks (further requests are shed with RESOURCE_EXHAUSTED), and idle_timeout = 300 closes connections that stop sending bytes. Still size max_concurrent_requests explicitly to the host's memory and the configured max_message_size in production, and treat any handler that can run for a long time as a DoS vector (see Deadline semantics and SECURITY.md).
HTTP.jl listener knobs (legacy serve! pass-throughs)
max_header_bytes::Int: Maximum request-header size in bytes (default: 1MiB)reuseaddr::Bool: Allow reusing the address on restart (default: true)backlog::Int: Connection backlog for the listener (default: 128)
TLS
tls::Union{TLSConfig, Nothing}: TLS configuration (nothing = insecure)
Feature Toggles
enable_health_check::Bool: Enable built-in health checking service (default: false)enable_reflection::Bool: Enable gRPC reflection service (default: false)debug_mode::Bool: Include exception details in error responses (default: false)log_requests::Bool: Log all incoming requests (default: false)
Compression
compression_enabled::Bool: Enable message compression (default: true)compression_threshold::Int: Minimum bytes before compression (default: 1024)supported_codecs::Vector{CompressionCodec.T}: Supported compression codecs
Backend gating
ServerConfig itself is backend-agnostic and always constructible. At GRPCServer construction, however, a configuration keyword that is explicitly set but unsupported by the selected HTTP/2 backend raises UnsupportedFeatureError instead of being silently ignored (omitted keywords never raise). This applies to: max_connections, max_queued_requests, keepalive_interval, keepalive_timeout, the HTTP.jl listener timeouts and knobs, the h2-window keywords, drain_timeout (some backends), send-side compression, mTLS / TLS sub-features (on Nghttp2Backend), enable_reflection (on Nghttp2Backend), and max_concurrent_streams (on PureHTTP2Backend and Nghttp2Backend — the HTTPjlBackend supports it). See HTTP/2 Backends for the per-backend matrix.
Example
config = ServerConfig( max_message_size = 8 * 1024 * 1024, # 8MB enable_health_check = true, enable_reflection = true, debug_mode = false)gRPCServer.TLSConfig — Type
TLSConfigTLS/mTLS configuration for secure connections.
Fields
cert_chain::String: Path to server certificate chain (PEM)private_key::String: Path to server private key (PEM)client_ca::Union{String, Nothing}: Path to client CA certificate for mTLSrequire_client_cert::Bool: Whether to require client certificatesmin_version::Symbol: Minimum TLS version (:TLSv1_2or:TLSv1_3)alpn_protocols::Vector{String}: Ordered ALPN protocol preference list (default["h2"])handshake_timeout_ns::Int64: Optional per-handshake timeout in nanoseconds;0leaves it unset
Example
tls = TLSConfig( cert_chain = "/path/to/server.crt", private_key = "/path/to/server.key", client_ca = "/path/to/ca.crt", # For mTLS require_client_cert = true, min_version = :TLSv1_2, alpn_protocols = ["h2"],)gRPCServer.ServerStatus — Module
ServerStatusRepresents the lifecycle state of a gRPC server.
States
STOPPED: Server is not runningSTARTING: Server is binding to addressRUNNING: Server is accepting connectionsDRAINING: Server is completing in-flight requestsSTOPPING: Server is releasing resources
Context Types
gRPCServer.ServerContext — Type
ServerContextRequest-scoped context provided to handler functions.
Fields
request_id::UUID: Unique identifier for this requestmethod::String: Full method path (e.g., "/helloworld.Greeter/SayHello")authority::String: Authority from :authority pseudo-headermetadata::Dict{String, Union{String, Vector{UInt8}}}: Request metadataresponse_headers::Dict{String, Union{String, Vector{UInt8}}}: Response headers to sendtrailers::Dict{String, Union{String, Vector{UInt8}}}: Trailing metadata to senddeadline::Union{DateTime, Nothing}: Request deadline (nothing = no deadline). The server does not interrupt a handler when the deadline passes — it is enforced only before dispatch (fail-fast) and after the handler returns (seeServerConfigdeadline semantics); handlers should checkremaining_time/is_cancelledcooperatively to bound their own runtime.cancelled::Bool: Whether the request has been cancelledpeer::PeerInfo: Client connection informationtrace_context::Union{Vector{UInt8}, Nothing}: Distributed tracing contextpayload::Any: Arbitrary server-side payload (unused by the transport)
Example
function say_hello(ctx::ServerContext, request::HelloRequest)::HelloReply @info "Request" id=ctx.request_id method=ctx.method # Check cancellation if is_cancelled(ctx) throw(GRPCError(StatusCode.CANCELLED, "Request cancelled")) end # Set response header set_header!(ctx, "x-request-id", string(ctx.request_id)) # Check deadline remaining = remaining_time(ctx) if remaining !== nothing && remaining < 0 throw(GRPCError(StatusCode.DEADLINE_EXCEEDED, "Deadline exceeded")) end HelloReply(message = "Hello, $(request.name)!")endgRPCServer.PeerInfo — Type
PeerInfoClient connection information.
Fields
address::Union{IPv4, IPv6}: Client IP addressport::Int: Client portcertificate::Union{Vector{UInt8}, Nothing}: Client certificate for mTLS (DER-encoded)
Example
peer = ctx.peer@info "Client connected from $(peer.address):$(peer.port)"Service Registration
gRPCServer.ServiceDescriptor — Type
ServiceDescriptorDescribes a gRPC service and its methods.
Fields
name::String: Fully-qualified service name (e.g., "helloworld.Greeter")methods::Dict{String, MethodDescriptor}: Methods keyed by namefile_descriptor::Union{Vector{UInt8}, Nothing}: File descriptor for reflection (optional)
Example
service = ServiceDescriptor( "helloworld.Greeter", Dict( "SayHello" => MethodDescriptor( "SayHello", MethodType.UNARY, "helloworld.HelloRequest", "helloworld.HelloReply", say_hello ) ), nothing)gRPCServer.MethodDescriptor — Type
MethodDescriptorDescribes a single RPC method.
Fields
name::String: Method name (e.g., "SayHello")method_type::MethodType.T: RPC pattern typeinput_type::String: Fully-qualified request message type nameoutput_type::String: Fully-qualified response message type namehandler::Function: Handler function referenceraw_request::Bool: Treat the request payload as raw protobuf bytes (skip the type registry / ProtoBuf decode; the handler receives a fresh copy of the raw bytes). Defaultfalse.raw_response::Bool: Treat the handler'sAbstractVector{UInt8}return value as raw protobuf bytes and pass them through verbatim (no ProtoBuf encode). Defaultfalse.
Handler Signatures by MethodType
UNARY:(ctx::ServerContext, request::T) -> RSERVER_STREAMING:(ctx::ServerContext, request::T, stream::ServerStream{R}) -> NothingCLIENT_STREAMING:(ctx::ServerContext, stream::ClientStream{T}) -> RBIDI_STREAMING:(ctx::ServerContext, stream::BidiStream{T,R}) -> Nothing
Example
method = MethodDescriptor( "SayHello", MethodType.UNARY, "helloworld.HelloRequest", "helloworld.HelloReply", say_hello)gRPCServer.MethodType — Module
MethodTypeClassifies RPC method patterns.
Values
UNARY: Single request, single responseSERVER_STREAMING: Single request, multiple responsesCLIENT_STREAMING: Multiple requests, single responseBIDI_STREAMING: Multiple requests, multiple responses
gRPCServer.register! — Function
register!(registry::ServiceRegistry, descriptor::ServiceDescriptor)Register a service in the registry. Also auto-registers protobuf types if Julia types were provided in MethodDescriptor.
register!(server::GRPCServer, service)Register a service with the server.
The service must implement service_descriptor(service) to provide its ServiceDescriptor.
Arguments
server::GRPCServer: The server to register withservice: A service implementation
Throws
InvalidServerStateError: If server is not in STOPPED stateServiceAlreadyRegisteredError: If service is already registered
Example
server = GRPCServer("0.0.0.0", 50051)register!(server, GreeterService())gRPCServer.register_method! — Function
register_method!(registry::ServiceRegistry, service_name::String, method::MethodDescriptor)Register a single method under service_name, creating the service entry (and its ServiceDescriptor) on first use. Unlike register! (which throws ServiceAlreadyRegisteredError if the service exists), repeated calls accumulate methods onto the same service — this is the primitive the generated per-RPC registration functions build on. The handler shape is validated at registration time (see _validate_method_handler!) and the method's Julia types are auto-registered in the type registry.
register_method!(dispatcher::RequestDispatcher, service_name::String, method::MethodDescriptor)Register a single method with the dispatcher (see register_method!(::ServiceRegistry, ...)).
gRPCServer.services — Function
services(server::GRPCServer) -> Vector{String}Get a list of registered service names.
Example
for service_name in services(server) println(service_name)endgRPCServer.service_descriptor — Function
service_descriptor(service) -> ServiceDescriptorGet the service descriptor for a service implementation.
This function should be overloaded for custom service types.
Example
struct GreeterService endfunction gRPCServer.service_descriptor(::GreeterService) ServiceDescriptor( "helloworld.Greeter", Dict( "SayHello" => MethodDescriptor( "SayHello", MethodType.UNARY, "helloworld.HelloRequest", "helloworld.HelloReply", say_hello ) ), nothing )endThe generated register_<Service>_<Rpc>! functions build a MethodDescriptor for each RPC and call register_method! on the server's dispatcher; use the generated functions for normal services. The types and functions below are the underlying runtime interface the codegen sits on.
Registration-time validation is performed by internal helpers:
gRPCServer._validate_method_handler! — Function
_validate_method_handler!(method::MethodDescriptor)Check at registration time that method.handler is callable with the signature its MethodType requires (see _expected_handler_tuple), so mismatched handler shapes fail with a clear ArgumentError at register_! rather than a MethodError on the first call. Untyped/vararg handlers pass; wrong arity, wrong argument types, and raw/typed mismatches are rejected. Return types cannot be checked generically and are not validated.
gRPCServer._expected_handler_tuple — Function
_expected_handler_tuple(method::MethodDescriptor) -> Union{Tuple, Nothing}The call tuple a handler for method must accept, derived from its MethodType and its Julia input/output types. Raw sides substitute Vector{UInt8} (the raw payload). Returns nothing when the descriptor carries no Julia types (string-typed descriptors) and cannot be shape-checked.
| MethodType | Expected handler tuple |
|---|---|
| UNARY | Tuple{ServerContext, ReqT} |
| SERVER_STREAMING | Tuple{ServerContext, ReqT, ServerStream{RespT}} |
| CLIENT_STREAMING | Tuple{ServerContext, ClientStream{ReqT}} |
| BIDI_STREAMING | Tuple{ServerContext, BidiStream{ReqT, RespT}} |
Stream Types
gRPCServer.ServerStream — Type
ServerStream{T}Outgoing stream for server streaming and bidirectional RPCs.
Type parameter T is the response message type.
Methods
send!(stream, message): Send a messageclose!(stream): End the stream
Example
function list_features(ctx::ServerContext, request::Rectangle, stream::ServerStream{Feature}) for feature in find_features(request) send!(stream, feature) endendgRPCServer.ClientStream — Type
ClientStream{T}Incoming stream for client streaming and bidirectional RPCs.
Type parameter T is the request message type.
Implements the Julia iterator interface for use in for loops.
Example
function record_route(ctx::ServerContext, stream::ClientStream{Point})::RouteSummary point_count = 0 for point in stream point_count += 1 # Process each point end return RouteSummary(point_count=point_count)endgRPCServer.BidiStream — Type
BidiStream{T, R}Bidirectional stream combining input (T) and output (R) streams.
Type parameters:
T: Request message type (incoming)R: Response message type (outgoing)
Implements the iterator interface for incoming messages and provides send! for outgoing messages.
Example
function route_chat(ctx::ServerContext, stream::BidiStream{RouteNote, RouteNote}) for note in stream # Iterate incoming messages # Echo back each note send!(stream, note) endendgRPCServer.send! — Function
send!(stream::ServerStream{T}, message::T) where T
send!(stream::ServerStream{T}, message::T; compress::Bool=true) where TSend a message on the server stream.
Arguments
stream::ServerStream{T}: The stream to send onmessage::T: The message to sendcompress::Bool=true: Whether to compress the message (if compression is negotiated)
Throws
StreamCancelledError: If the stream has been cancelledArgumentError: If the stream is closed
Example
send!(stream, Feature(name="Feature 1", location=Point(latitude=1, longitude=2)))send!(stream::BidiStream{T, R}, message::R) where {T, R}
send!(stream::BidiStream{T, R}, message::R; compress::Bool=true) where {T, R}Send a message on the bidirectional stream.
Example
send!(stream, RouteNote(message="Hello", location=point))gRPCServer.close! — Function
close!(stream::BidiStream)Close the output side of the bidirectional stream.
Error Handling
gRPCServer.StatusCode — Module
StatusCodeStandard gRPC status codes per specification.
Status Codes
OK(0): Not an error; returned on successCANCELLED(1): Operation was cancelledUNKNOWN(2): Unknown errorINVALID_ARGUMENT(3): Invalid argument providedDEADLINE_EXCEEDED(4): Deadline expired before completionNOT_FOUND(5): Requested entity not foundALREADY_EXISTS(6): Entity already existsPERMISSION_DENIED(7): Permission deniedRESOURCE_EXHAUSTED(8): Resource exhaustedFAILED_PRECONDITION(9): Precondition check failedABORTED(10): Operation abortedOUT_OF_RANGE(11): Value out of rangeUNIMPLEMENTED(12): Operation not implementedINTERNAL(13): Internal errorUNAVAILABLE(14): Service unavailableDATA_LOSS(15): Data loss or corruptionUNAUTHENTICATED(16): Request not authenticated
gRPCServer.GRPCError — Type
GRPCError <: ExceptionException type for gRPC errors with status code, message, and optional details.
Fields
code::StatusCode.T: The gRPC status codemessage::String: Human-readable error messagedetails::Vector{Any}: Additional error details (rich error model)
Example
throw(GRPCError(StatusCode.NOT_FOUND, "User not found", []))throw(GRPCError(StatusCode.INVALID_ARGUMENT, "Name cannot be empty"))gRPCServer.BindError — Type
BindError <: ExceptionException thrown when the server fails to bind to the configured address.
Fields
message::String: Description of the bind failurecause::Union{Exception, Nothing}: Underlying exception if available
gRPCServer.ServiceAlreadyRegisteredError — Type
ServiceAlreadyRegisteredError <: ExceptionException thrown when attempting to register a service with a name that already exists.
Fields
service_name::String: The duplicate service name
gRPCServer.InvalidServerStateError — Type
InvalidServerStateError <: ExceptionException thrown when an operation is attempted in an invalid server state.
Fields
expected::ServerStatus.T: The expected server stateactual::ServerStatus.T: The actual server state
gRPCServer.MethodSignatureError — Type
MethodSignatureError <: ExceptionException thrown when a handler method has an invalid signature.
Fields
method_name::String: The method with invalid signatureexpected::String: Description of expected signatureactual::String: Description of actual signature
gRPCServer.StreamCancelledError — Type
StreamCancelledError <: ExceptionException thrown when a stream operation is attempted on a cancelled stream.
Fields
reason::String: The reason for cancellation
gRPCServer.UnsupportedFeatureError — Type
UnsupportedFeatureError <: ExceptionException thrown when a feature is explicitly requested that the selected HTTP/2 backend does not support.
Fields
feature::Symbol: The feature (configuration keyword) that is unsupportedbackend::Type: The backend type that does not support the featuremessage::String: Human-readable explanation, including the way out
gRPCServer.status_code_to_http — Function
status_code_to_http(code::StatusCode.T) -> IntMap a gRPC status code to the appropriate HTTP status code.
gRPCServer.exception_to_status_code — Function
exception_to_status_code(e::Exception) -> StatusCode.TMap a Julia exception to a gRPC status code.
gRPCServer.http2_to_grpc_status — Function
http2_to_grpc_status(http2_error_code::UInt32) -> StatusCode.TMap an HTTP/2 error code to a gRPC status code.
This mapping is per the gRPC HTTP/2 protocol specification: https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md
HTTP/2 Error Code Mappings
- NOERROR (0x0) → INTERNAL (unexpected for RSTSTREAM)
- PROTOCOL_ERROR (0x1) → INTERNAL
- INTERNAL_ERROR (0x2) → INTERNAL
- FLOWCONTROLERROR (0x3) → INTERNAL
- SETTINGS_TIMEOUT (0x4) → INTERNAL
- STREAM_CLOSED (0x5) → INTERNAL
- FRAMESIZEERROR (0x6) → INTERNAL
- REFUSED_STREAM (0x7) → UNAVAILABLE
- CANCEL (0x8) → CANCELLED
- COMPRESSION_ERROR (0x9) → INTERNAL
- CONNECT_ERROR (0xa) → INTERNAL
- ENHANCEYOURCALM (0xb) → RESOURCE_EXHAUSTED
- INADEQUATESECURITY (0xc) → PERMISSIONDENIED
- HTTP11_REQUIRED (0xd) → INTERNAL
Example
grpc_status = http2_to_grpc_status(0x08) # CANCEL → CANCELLEDhttp2_to_grpc_status(http2_error_code::Integer) -> StatusCode.TConvenience method accepting any integer type.
Interceptors
gRPCServer.Interceptor — Type
InterceptorAbstract type for gRPC interceptors.
Interceptors are callables that wrap handler execution, allowing for cross-cutting concerns like logging, authentication, metrics, and error handling.
Required Interface
Subtypes must be callable with signature:
(interceptor)(ctx::ServerContext, request_or_stream, info::MethodInfo, next::Function) -> responseArguments
ctx::ServerContext: Request contextrequest_or_stream: Request message (unary/server streaming) or stream (client/bidi streaming)info::MethodInfo: Method informationnext::Function: Next handler in the chain (call to continue processing)
Example
struct AuthInterceptor <: Interceptor required_scope::Stringendfunction (i::AuthInterceptor)(ctx, request, info, next) token = get_metadata_string(ctx, "authorization") if token === nothing throw(GRPCError(StatusCode.UNAUTHENTICATED, "Missing authorization")) end # Validate token and check scope if !validate_token(token, i.required_scope) throw(GRPCError(StatusCode.PERMISSION_DENIED, "Insufficient scope")) end return next(ctx, request)endgRPCServer.MethodInfo — Type
MethodInfoInformation about the method being called, provided to interceptors.
Fields
service_name::String: Fully-qualified service name (e.g., "helloworld.Greeter")method_name::String: Method name (e.g., "SayHello")method_type::MethodType.T: RPC pattern type
Example
struct LoggingInterceptor <: Interceptor endfunction (::LoggingInterceptor)(ctx, request, info::MethodInfo, next) @info "Calling" service=info.service_name method=info.method_name return next(ctx, request)endgRPCServer.LoggingInterceptor — Type
LoggingInterceptor <: InterceptorBuilt-in interceptor that logs request/response information.
Fields
log_requests::Bool: Log incoming requests (default: true)log_responses::Bool: Log responses (default: true)log_errors::Bool: Log errors (default: true)
Example
add_interceptor!(server, LoggingInterceptor())gRPCServer.MetricsInterceptor — Type
MetricsInterceptor <: InterceptorBuilt-in interceptor that collects request metrics.
Fields
on_request::Function: Called with (method, request_size) on each requeston_response::Function: Called with (method, status, durationms, responsesize) on each response
Example
metrics = MetricsInterceptor( on_request = (method, size) -> increment_counter("grpc_requests", method), on_response = (method, status, ms, size) -> record_histogram("grpc_duration", ms, method, status))add_interceptor!(server, metrics)gRPCServer.TimeoutInterceptor — Type
TimeoutInterceptor <: InterceptorBuilt-in interceptor that enforces request deadlines.
Fields
default_timeout_ms::Union{Int, Nothing}: Default timeout in milliseconds if none specified
Example
add_interceptor!(server, TimeoutInterceptor(default_timeout_ms=30000)) # 30 second defaultgRPCServer.RecoveryInterceptor — Type
RecoveryInterceptor <: InterceptorBuilt-in interceptor that catches panics and converts them to gRPC errors.
Fields
include_stack_trace::Bool: Include stack trace in error message (debug mode only)
Example
add_interceptor!(server, RecoveryInterceptor(include_stack_trace=true))gRPCServer.add_interceptor! — Function
add_interceptor!(dispatcher::RequestDispatcher, interceptor::Interceptor)Add a global interceptor.
add_interceptor!(dispatcher::RequestDispatcher, service_name::String, interceptor::Interceptor)Add a service-specific interceptor.
add_interceptor!(server::GRPCServer, interceptor::Interceptor)Add a global interceptor that applies to all services.
Example
add_interceptor!(server, LoggingInterceptor())add_interceptor!(server, MetricsInterceptor())add_interceptor!(server::GRPCServer, service_name::String, interceptor::Interceptor)Add an interceptor for a specific service.
Example
add_interceptor!(server, "helloworld.Greeter", AuthInterceptor())Health Checking
gRPCServer.HealthStatus — Module
HealthStatusService health state for the health checking service.
Values
UNKNOWN: Health status is unknownSERVING: Service is healthy and accepting requestsNOT_SERVING: Service is not healthySERVICE_UNKNOWN: Service is not registered
gRPCServer.set_health! — Function
set_health!(server::GRPCServer, status::HealthStatus.T)Set the health status for the overall server.
Example
set_health!(server, HealthStatus.NOT_SERVING) # Server entering maintenanceset_health!(server::GRPCServer, service_name::String, status::HealthStatus.T)Set the health status for a specific service.
Example
set_health!(server, "helloworld.Greeter", HealthStatus.NOT_SERVING)gRPCServer.get_health — Function
get_health(server::GRPCServer, service_name::String="") -> HealthStatus.TGet the health status for a service (or overall server if empty string).
Reflection Support
gRPCServer.HEALTH_DESCRIPTOR — Constant
HEALTH_DESCRIPTOR::Vector{Vector{UInt8}}Extracted FileDescriptorProto messages for the gRPC Health service (grpc.health.v1). Each element is a serialized FileDescriptorProto that can be returned by the reflection service.
Generated from: specs/001-grpc-server/contracts/health.proto
gRPCServer.REFLECTION_DESCRIPTOR — Constant
REFLECTION_DESCRIPTOR::Vector{Vector{UInt8}}Extracted FileDescriptorProto messages for the gRPC Server Reflection service (grpc.reflection.v1alpha). Each element is a serialized FileDescriptorProto that can be returned by the reflection service.
Generated from: specs/001-grpc-server/contracts/reflection.proto
gRPCServer.has_health_descriptor — Function
has_health_descriptor() -> BoolCheck if the Health service descriptor is available.
gRPCServer.has_reflection_descriptor — Function
has_reflection_descriptor() -> BoolCheck if the Reflection service descriptor is available.
Server Lifecycle
gRPCServer.start! — Function
start!(server::GRPCServer)Start the server and begin accepting connections.
This is a non-blocking call. Use run(server) for blocking operation.
Throws
InvalidServerStateError: If server is not in STOPPED stateBindError: If the server cannot bind to the address
Example
start!(server)# Server is now running in backgroundgRPCServer.stop! — Function
stop!(server::GRPCServer; force::Bool=false, timeout::Float64=0.0)Stop the server.
Arguments
server::GRPCServer: The server to stopforce::Bool=false: If true, immediately close all connectionstimeout::Float64=0.0: Override drain timeout (0 = use config)
Throws
InvalidServerStateError: If server is not running
Example
stop!(server) # Graceful shutdownstop!(server; force=true) # Immediate shutdownTLS
gRPCServer.reload_tls! — Function
reload_tls!(server::GRPCServer)Reload TLS certificates from disk.
This allows certificate rotation without server restart.
Throws
InvalidServerStateError: If server is not runningArgumentError: If TLS is not configured
Example
reload_tls!(server) # Reload certificatesContext Operations
gRPCServer.set_header! — Function
set_header!(ctx::ServerContext, key::String, value::String)
set_header!(ctx::ServerContext, key::String, value::Vector{UInt8})Set a response header to be sent before the response body.
Headers must be set before the first response message is sent. Binary headers should have a "-bin" suffix in the key name.
Example
set_header!(ctx, "x-custom-header", "custom-value")set_header!(ctx, "x-binary-data-bin", UInt8[0x01, 0x02, 0x03])gRPCServer.set_trailer! — Function
set_trailer!(ctx::ServerContext, key::String, value::String)
set_trailer!(ctx::ServerContext, key::String, value::Vector{UInt8})Set trailing metadata to be sent after the response body.
Trailers are sent at the end of the response stream and can be used to communicate status information determined during processing.
Example
set_trailer!(ctx, "x-processing-time", "150ms")gRPCServer.get_metadata — Function
get_metadata(ctx::ServerContext, key::String) -> Union{String, Vector{UInt8}, Nothing}Get request metadata by key (case-insensitive).
Example
auth = get_metadata(ctx, "authorization")if auth === nothing throw(GRPCError(StatusCode.UNAUTHENTICATED, "Missing authorization"))endgRPCServer.get_metadata_string — Function
get_metadata_string(ctx::ServerContext, key::String) -> Union{String, Nothing}Get request metadata as a string (returns nothing for binary metadata).
gRPCServer.get_metadata_binary — Function
get_metadata_binary(ctx::ServerContext, key::String) -> Union{Vector{UInt8}, Nothing}Get request metadata as binary (converts strings to bytes if needed).
gRPCServer.remaining_time — Function
remaining_time(ctx::ServerContext) -> Union{Float64, Nothing}Get the remaining time until the deadline in seconds.
Returns nothing if no deadline is set. Returns negative value if deadline has passed.
Example
remaining = remaining_time(ctx)if remaining !== nothing && remaining < 0 throw(GRPCError(StatusCode.DEADLINE_EXCEEDED, "Deadline exceeded"))endgRPCServer.is_cancelled — Function
is_cancelled(ctx::ServerContext) -> BoolCheck if the request has been cancelled by the client.
Example
if is_cancelled(ctx) throw(GRPCError(StatusCode.CANCELLED, "Request cancelled by client"))endis_cancelled(stream::ClientStream) -> BoolCheck if the stream has been cancelled.
is_cancelled(stream::BidiStream) -> BoolCheck if the stream has been cancelled.
gRPCServer.cancel! — Function
cancel!(ctx::ServerContext)Mark the request as cancelled.
cancel! is not exported — call it as gRPCServer.cancel!(ctx).
Compression
gRPCServer.CompressionCodec — Module
CompressionCodecSupported compression algorithms for gRPC messages.
Values
IDENTITY: No compressionGZIP: Gzip compressionDEFLATE: Deflate compression
gRPCServer.compress — Function
compress(data::Vector{UInt8}, codec::CompressionCodec.T) -> Vector{UInt8}Compress data using the specified codec.
gRPCServer.decompress — Function
decompress(data::Vector{UInt8}, codec::CompressionCodec.T) -> Vector{UInt8}Decompress data using the specified codec.
gRPCServer.codec_name — Function
codec_name(codec::CompressionCodec.T) -> StringGet the gRPC encoding name for a compression codec.
gRPCServer.parse_codec — Function
parse_codec(name::AbstractString) -> Union{CompressionCodec.T, Nothing}Parse a gRPC encoding name to a compression codec. Returns nothing if the encoding is not supported.
gRPCServer.negotiate_compression — Function
negotiate_compression(
client_encodings::Vector{CompressionCodec.T},
server_codecs::Vector{CompressionCodec.T}
) -> CompressionCodec.TNegotiate compression codec between client and server. Returns the first codec supported by both, preferring client order. Falls back to IDENTITY if no common codec.
ProtoBuf Code Generation
Loading gRPCServer registers its ProtoBuf.jl code generation handler; one protojl run (with gRPCClient.jl loaded too) emits message types, client stubs, and per-service registration functions in a single generated file. protojl is re-exported from ProtoBuf.jl by gRPCServer. See Code Generation for the full walkthrough.
gRPCServer.grpc_register_service_codegen — Function
grpc_register_service_codegen()Register gRPCServer's external code generation handler with ProtoBuf.jl so that a subsequent protojl run emits server descriptors (<Service>_<Rpc>_Method builders, register_<Service>_<Rpc>! registration functions, and a register_<Service>! aggregate) for each service in the .proto.
This is called automatically from the module's __init__, so it normally does not need to be invoked directly. It can be called explicitly (e.g. gRPCServer.grpc_register_service_codegen()) to re-register the handler after ProtoBuf.jl has been reloaded.
HTTP/2 Backend Abstraction
gRPCServer.jl supports pluggable HTTP/2 backends via an abstract type and a connection-factory method. See HTTP/2 Backends for the full guide.
gRPCServer.AbstractHTTP2Backend — Type
AbstractHTTP2BackendAbstract type representing an HTTP/2 backend for gRPCServer.jl.
Backends drive the server through one of two contracts:
serve_grpc(primary): the backend owns its listener/serve loop and presents each incoming call as anAbstractGRPCStreamtodispatch_grpc_call. Seeserve_grpc,uses_serve_grpc, andstop_serving!. All three built-in backends use this contract.create_connection(legacy): the backend implementscreate_connectionto return an HTTP/2 connection object driven by gRPCServer's own frame loop. Kept for custom backends written against the old interface; the connection object must be compatible with PureHTTP2.jl'sHTTP2Connectioninterface (connection lifecycle:process_preface,process_frame,is_open; stream management:get_stream,remove_stream,can_send_on_stream; sending:send_headers,send_data,send_trailers,send_rst_stream,send_goaway; frame I/O:Frame,encode_frame,decode_frame_header).
See the HTTP/2 Backends documentation page for details on implementing a custom backend.
gRPCServer.PureHTTP2Backend — Type
PureHTTP2Backend <: AbstractHTTP2BackendOpt-in pure-Julia HTTP/2 backend using PureHTTP2.jl (the default backend is HTTPjlBackend; pass http2_backend=PureHTTP2Backend() to the GRPCServer constructor to select it).
PureHTTP2 is an optional dependency. Load it before constructing the backend:
using gRPCServer, PureHTTP2server = GRPCServer("127.0.0.1", 50051; http2_backend = PureHTTP2Backend())This backend delegates all HTTP/2 operations to the PureHTTP2 package, which provides a pure-Julia implementation of the HTTP/2 protocol (RFC 7540) including HPACK header compression (RFC 7541), stream management, and flow control.
gRPCServer.create_connection — Function
create_connection(backend::AbstractHTTP2Backend)Create a new HTTP/2 connection using the specified backend.
Returns an HTTP/2 connection object that will be used to manage a single client connection. The returned object must support the full HTTP/2 connection interface (see AbstractHTTP2Backend for requirements).
This is the legacy custom-backend contract. New backends should implement serve_grpc instead; the built-in backends all do. PureHTTP2Backend implements create_connection inside the PureHTTP2 extension.
Examples
backend = PureHTTP2Backend()conn = create_connection(backend) # Returns a PureHTTP2.HTTP2ConnectiongRPCServer.HTTPjlBackend — Type
HTTPjlBackend <: AbstractHTTP2BackendHTTP/2 backend backed by HTTP.jl (>= 2.0.0).
HTTP.jl owns the TCP listener and the TLS/ALPN handshake; this backend delegates the HTTP/2 protocol (frames, HPACK, flow control, trailers) to HTTP.jl and adapts each HTTP.Stream to the AbstractGRPCStream contract.
Constructing an HTTPjlBackend validates that the loaded HTTP.jl can serve HTTP/2 and raises a clear error otherwise.
Known limitations (current HTTP.jl)
- No live TLS certificate reload (
reload_tls!); HTTP.jl owns the TLS context.
Select PureHTTP2Backend() if you need certificate reload.
gRPCServer.Nghttp2Backend — Type
Nghttp2Backend <: AbstractHTTP2BackendHTTP/2 backend backed by the nghttp2 C library through Nghttp2Wrapper.jl.
Nghttp2Wrapper is an optional dependency. Load it before constructing the backend:
using gRPCServer, Nghttp2Wrapperserver = GRPCServer("127.0.0.1", 50051; http2_backend = Nghttp2Backend())Supported RPC types
Unary and client-streaming calls only. Nghttp2Wrapper's server handler receives a fully buffered request and returns a fully buffered response, so a handler cannot emit messages as it produces them — server-streaming and bidirectional calls are rejected at dispatch rather than silently truncated. Its ROADMAP Milestone 7 tracks the incremental handler that would lift this.
Select HTTPjlBackend for the full set.
gRPCServer.BackendCapabilities — Type
BackendCapabilitiesDeclares which features an HTTP/2 backend supports. Every field defaults to true; a backend declares false for the features it cannot honor. Custom backends get the all-true default unless they define backend_capabilities for their type.
Fields (all Bool)
tls: TLS cert/keytls_mtls: mutual TLS (client_ca,require_client_cert)tls_min_version: minimum TLS version selectiontls_alpn: ALPN protocol listtls_handshake_timeout: per-handshake timeouttls_reload:reload_tls!max_connections:max_connectionsconfigmax_concurrent_streams:max_concurrent_streamsconfigqueued_requests:max_queued_requestsconfigkeepalive:keepalive_interval/keepalive_timeoutconfigconnection_timeouts:idle_timeout/read_header_timeout/read_timeout/write_timeoutlistener_knobs:max_header_bytes/reuseaddr/backloghttp2_settings:h2_initial_window_size/h2_connection_window_sizedrain_timeout_config:drain_timeoutconfig field (vs.stop!(; timeout=))receive_cap:max_receive_message_lengthenforcementdecompression: receive-side decompression (informational)send_compression: send-side compression (compression_enabled/compression_threshold/supported_codecs)server_streaming: server-streaming RPCs (informational)bidi_streaming: bidi-streaming RPCs (informational)reflection: the reflection service (enable_reflection)health: the health service (enable_health_check)
gRPCServer.backend_capabilities — Function
backend_capabilities(backend) -> BackendCapabilitiesReturn the capability declaration for a backend type (or instance). Custom backends default to all-true; built-in backends declare the features they cannot honor. Keyed on the type, so backend_capabilities(Nghttp2Backend) works even when the Nghttp2Wrapper extension is not loaded.
gRPCServer.backend_defaults — Function
backend_defaults(backend) -> NamedTuplePer-backend default values for the GRPCServer configuration keywords. The default implementation derives the values from a fresh ServerConfig() (single source of truth — no duplicated literals), plus the two h2-window keywords that are GRPCServer-level (65535 = the HTTP.jl HTTP2Settings defaults). A backend may override this method to declare genuinely different effective defaults; for the built-in backends the values are identical today, and the per-backend difference (what raises when explicitly set) lives in backend_capabilities.
gRPCServer.GRPCServerHTTPJl — Function
GRPCServerHTTPJl(host, port; kwargs...) -> GRPCServerCreate a gRPC server on the HTTP.jl backend (HTTPjlBackend).
Accepts the same configuration keywords as GRPCServer; the backend is fixed to HTTPjlBackend. Explicitly setting a keyword this backend cannot honor raises UnsupportedFeatureError at construction. On this backend the following keywords raise (explicitly set): max_connections, max_queued_requests, keepalive_interval, keepalive_timeout, drain_timeout (pass timeout= to stop! instead), compression_enabled=true, compression_threshold, supported_codecs; reload_tls! also raises on this backend. max_concurrent_streams is supported (default 100, enforced per connection by HTTP.jl).
Example
server = GRPCServerHTTPJl("0.0.0.0", 50051; max_receive_message_length=8 * 1024 * 1024)gRPCServer.GRPCServerPureHTTP2 — Function
GRPCServerPureHTTP2(host, port; kwargs...) -> GRPCServerCreate a gRPC server on the pure-Julia HTTP/2 backend (PureHTTP2Backend).
PureHTTP2 is an optional dependency: load it before constructing the server (via using PureHTTP2, which also loads the gRPCServerPureHTTP2Ext extension), or constructing this entry point throws an actionable ArgumentError.
Accepts the same configuration keywords as GRPCServer; the backend is fixed to PureHTTP2Backend. Explicitly setting a keyword this backend cannot honor raises UnsupportedFeatureError at construction. On this backend the following keywords raise (explicitly set): max_connections, max_concurrent_streams, max_queued_requests, keepalive_interval, keepalive_timeout, idle_timeout, read_header_timeout, read_timeout, write_timeout, max_header_bytes, reuseaddr, backlog, h2_initial_window_size, h2_connection_window_size, max_receive_message_length, compression_enabled=true, compression_threshold, supported_codecs. drain_timeout is supported.
Example
using PureHTTP2server = GRPCServerPureHTTP2("0.0.0.0", 50051; drain_timeout=60.0)gRPCServer.GRPCServerNghttp2 — Function
GRPCServerNghttp2(host, port; kwargs...) -> GRPCServerCreate a gRPC server on the Nghttp2 backend (Nghttp2Backend).
Accepts the same configuration keywords as GRPCServer; the backend is fixed to Nghttp2Backend. Requires the Nghttp2Wrapper extension to be loaded (otherwise constructing Nghttp2Backend throws). Explicitly setting a keyword this backend cannot honor raises UnsupportedFeatureError at construction: TLS is supported (cert/key only — mTLS, min_version, alpn_protocols, handshake_timeout_ns raise), enable_health_check is supported (Check works; Watch is refused per-request), and everything else configurable raises when explicitly set (enable_reflection, the timeouts, listener knobs, h2 windows, keepalive, connection limits, message-length limits, and send-side compression).
Raised stream-handler contract (all built-in backends)
The preferred contract, higher-level than the connection factory: the backend owns its listener and serve loop, and presents each gRPC call as an AbstractGRPCStream. It was introduced for the HTTP.jl backend; as of 1.0 all three built-in backends (HTTPjl, PureHTTP2, nghttp2) serve through it, with the HTTP.jl request path driving dispatch via serve_grpc.
gRPCServer.AbstractGRPCStream — Type
AbstractGRPCStreamRepresents a single in-flight gRPC call (one HTTP/2 stream) as seen by the gRPC dispatch layer, independent of which HTTP/2 backend produced it.
A backend adapter presents each incoming call as an AbstractGRPCStream and implements the stream operations: grpc_path, grpc_method, request_metadata, read_message!, is_cancelled, send_response_headers!, send_message!, send_trailers!, and reset!.
gRPCServer.serve_grpc — Function
serve_grpc(backend::AbstractHTTP2Backend, server, on_call) -> NothingOwn the accept loop for server and invoke on_call(stream::AbstractGRPCStream) once per incoming gRPC call. Backends must validate the HTTP/2 connection preface (h2c) and/or negotiate ALPN h2 (TLS), surface each request's :path and metadata via the stream, honor graceful shutdown when the server leaves the RUNNING state, and fail fast (before accepting traffic) when the backend cannot serve gRPC HTTP/2.
This is the higher-level extension point that complements create_connection; see the HTTP/2 Backends documentation for details.
HTTP/2 Stream State
These functions are used for advanced stream state management, particularly for handling edge cases with client disconnection. As of 1.0 they come from PureHTTP2.jl directly — gRPCServer no longer re-exports them (PureHTTP2 became an optional weak dependency). Load PureHTTP2 and qualify: PureHTTP2.can_send(stream), PureHTTP2.StreamError.
can_send(stream)— check whether a stream is in a state that accepts outbound dataStreamError— exception type for HTTP/2 stream-level errors