grpc
A gRPC server and client over HTTP/2: unary and streaming calls, metadata and status codes.
import grpc
gRPC is a way of calling a remote procedure that runs over HTTP/2, and it is common in microservices. On the server side you register each method under its path, like /demo.Greeter/SayHello; the method routine reads the client's message with Recv, answers with Send and ends it with SetStatus or Fail.
On the client side, UnaryCall is a plain request, and for streams you use StartCall, SendMessage, RecvMessage and FinishCall. Messages are bytes; you usually build them with protobuf.
Types
Status
struct Status| Name | Type | Description |
|---|---|---|
code | int = 0 | The code. |
message | str = "" | The message. |
import grpc
import compress
import sync
mut server := grpc.NewServer(0)
mut ready := sync.NewWaitGroup()
func hello(c: i64):
mut ok := false
name := grpc.RecvStr(c, ok)
_ := grpc.SendStr(c, "hello " + name)
grpc.SetStatus(c, grpc.GRPC_OK, "")
end
func countdown(c: i64):
mut ok := false
_ := grpc.Recv(c, ok)
repeat 3 in i:
_ := grpc.Send(c, compress.BufFromStr("" + (3 - i)))
end
grpc.SetStatus(c, grpc.GRPC_OK, "")
end
func trace(c: i64):
mut ok := false
_ := grpc.RecvStr(c, ok)
_ := grpc.SendStr(c, grpc.MDGet(grpc.CallMetadata(c), "x-trace") + " " + grpc.CallPath(c))
grpc.SetStatus(c, grpc.GRPC_OK, "")
end
func forbidden(c: i64):
grpc.Fail(c, grpc.GRPC_PERMISSION_DENIED, "the token expired")
end
func run_server():
_ := grpc.Listen(server)
sync.Done(ready)
_ := grpc.ServeCount(server, 1)
end
func main:
hello_path := grpc.MethodPath("demo.Greeter", "SayHello")
println hello_path
grpc.RegisterMethod(hello_path, hello)
grpc.RegisterStreamMethod("/demo.Greeter/Countdown", countdown, false, true)
grpc.RegisterMethod("/demo.Greeter/Trace", trace)
grpc.RegisterMethod("/demo.Greeter/Admin", forbidden)
println grpc.MethodCount(), grpc.HasMethod(hello_path)
sync.Add(ready, 1)
t := spawn(run_server)
sync.Wait(ready)
mut ch := grpc.Dial("127.0.0.1", grpc.Port(server))
grpc.SetTimeout(ch, 5000)
println grpc.ChannelOk(ch)
mut result := grpc.Status {}
println grpc.UnaryCallStr(ch, hello_path, "Maryam", result), grpc.StatusOk(result)
call := grpc.StartCall(ch, "/demo.Greeter/Countdown", grpc.NewMetadata())
_ := grpc.SendMessage(ch, call, compress.BufFromStr("go"), true)
mut more := true
until more:
mut ok := false
msg := grpc.RecvMessage(ch, call, ok)
if not ok:
more = false
else:
println "message:", compress.BufToStrUnsafe(msg)
end
end
println grpc.MDCount(grpc.CallHeaders(ch, call))
println grpc.StatusString(grpc.FinishCall(ch, call))
mut md := grpc.NewMetadata()
_ := grpc.MDAdd(md, "x-trace", "t-42")
mut result2 := grpc.Status {}
answer := grpc.UnaryCall(ch, "/demo.Greeter/Trace", compress.BufFromStr("x"), md, result2)
println compress.BufToStrUnsafe(answer)
call2 := grpc.StartCall(ch, "/demo.Greeter/Trace", md)
_ := grpc.SendMessage(ch, call2, compress.BufFromStr("y"), false)
_ := grpc.CloseSend(ch, call2)
mut ok2 := false
_ := grpc.RecvMessage(ch, call2, ok2)
_ := grpc.FinishCall(ch, call2)
println ok2, grpc.CallTrailers(ch, call2).items.len() >= 0
mut result3 := grpc.Status {}
_ := grpc.UnaryCallStr(ch, "/demo.Greeter/Admin", "", result3)
println result3.code, result3.message, grpc.StatusName(result3.code)
mut result4 := grpc.Status {}
_ := grpc.UnaryCallStr(ch, "/demo.Greeter/Nope", "", result4)
println grpc.StatusString(result4)
grpc.CloseChannel(ch)
join(t)
grpc.StopServer(server)
grpc.ResetMethods()
println grpc.MethodCount()
endMDEntry
struct MDEntry| Name | Type | Description |
|---|---|---|
key | str = "" | The key. |
value | str = "" | The value. |
binary | bool = false | It is binary. |
import grpc
import compress
import net.http2
func main:
one := grpc.FrameMessageStr("hello")
println one.len, compress.BufGet(one, 0), compress.BufGet(one, 4)
mut all := compress.NewByteBuf()
compress.BufPushBuf(all, one)
compress.BufPushBuf(all, grpc.FrameMessage(compress.BufFromStr("two"), false))
compress.BufPushBuf(all, grpc.FrameMessageGzip(compress.BufFromStr("three three three"), true))
println grpc.MessageCount(all), grpc.HasMessage(all, 0)
mut pos := 0
mut ok := false
until grpc.HasMessage(all, pos):
msg := grpc.NextMessage(all, pos, ok)
println ok, compress.BufToStrUnsafe(msg)
end
mut md := grpc.NewMetadata()
_ := grpc.MDAdd(md, "authorization", "Bearer abc")
_ := grpc.MDAdd(md, "x-tag", "a")
_ := grpc.MDAdd(md, "x-tag", "b")
_ := grpc.MDAddBinary(md, "trace-bin", "\x01\x02")
println grpc.MDCount(md), grpc.MDHas(md, "x-tag"), grpc.MDGet(md, "authorization")
println grpc.MDGetAll(md, "x-tag").len()
println grpc.MDKeyAt(md, 3), grpc.MDValueAt(md, 3).len()
mut headers := http2.HeaderList {}
grpc.MDToHeaders(md, headers)
println http2.HeadersCount(headers), http2.HeadersGet(headers, "trace-bin")
println grpc.MDCount(grpc.MDFromHeaders(headers))
bad := grpc.NewStatus(grpc.GRPC_NOT_FOUND, "there is no user 42")
println grpc.StatusOk(bad), grpc.StatusString(bad)
message := grpc.EncodeStatusMessage("100% done")
println message, grpc.DecodeStatusMessage(message)
println grpc.FormatStatusCode(14), grpc.ParseStatusCode("14"), grpc.ParseStatusCode("x")
println grpc.StatusName(grpc.GRPC_DEADLINE_EXCEEDED), grpc.StatusName(grpc.GRPC_UNAUTHENTICATED)
println grpc.GRPC_CANCELLED, grpc.GRPC_UNKNOWN, grpc.GRPC_INVALID_ARGUMENT, grpc.GRPC_ALREADY_EXISTS
println grpc.GRPC_RESOURCE_EXHAUSTED, grpc.GRPC_FAILED_PRECONDITION, grpc.GRPC_ABORTED, grpc.GRPC_OUT_OF_RANGE
println grpc.GRPC_UNIMPLEMENTED, grpc.GRPC_INTERNAL, grpc.GRPC_UNAVAILABLE, grpc.GRPC_DATA_LOSS
println grpc.GRPC_CONTENT_TYPE, grpc.GRPC_CONTENT_TYPE_PROTO, grpc.GRPC_CONTENT_TYPE_JSON
println grpc.GRPC_COMP_NONE, grpc.GRPC_COMP_GZIP, grpc.GRPC_MAX_FRAMES, grpc.GRPC_MAX_MESSAGE
endMetadata
struct Metadata| Name | Type | Description |
|---|---|---|
items | Vector | The entries. |
The example for this item is shown with the ones above: grpc-Calls.salam
CallCtx
struct CallCtx| Name | Type | Description |
|---|---|---|
stream_id | int = 0 | The stream id. |
method | str = "" | The method path. |
headers | http2.HeaderList | The headers. |
recv | compress.ByteBuf | The received data. |
recv_pos | int = 0 | The read position. |
client_done | bool = false | The client closed its sending side. |
sent_headers | bool = false | The response headers were sent. |
status | Status | The status. |
busy | bool = false | It is in use. |
failed | bool = false | It failed. |
The example for this item is shown with the ones above: grpc-Calls.salam
CallTable
struct CallTable| Name | Type | Description |
|---|---|---|
items | Vector | The calls. |
The example for this item is shown with the ones above: grpc-Calls.salam
MethodDesc
struct MethodDesc| Name | Type | Description |
|---|---|---|
path | str = "" | The path. |
fn | i64 = 0 | The routine. |
client_stream | bool = false | The client sends a stream. |
server_stream | bool = false | The server sends a stream. |
The example for this item is shown with the ones above: grpc-Calls.salam
MethodTable
struct MethodTable| Name | Type | Description |
|---|---|---|
items | Vector | The methods. |
The example for this item is shown with the ones above: grpc-Calls.salam
Cursor
struct Cursor| Name | Type | Description |
|---|---|---|
stream_id | int = 0 | The stream id. |
pos | int = 0 | The read position. |
The example for this item is shown with the ones above: grpc-Calls.salam
CursorTable
struct CursorTable| Name | Type | Description |
|---|---|---|
items | Vector | The cursors. |
The example for this item is shown with the ones above: grpc-Calls.salam
Channel
struct Channel| Name | Type | Description |
|---|---|---|
conn | http2.Conn | The HTTP/2 connection. |
authority | str = "" | The host and port. |
scheme | str = "http" | The scheme: http or https. |
user_agent | str = "salam-grpc/1.0" | The client identifier. |
timeout_ms | int = 0 | The timeout of each call. |
use_gzip | bool = false | Send the messages compressed. |
cursors | CursorTable | The read position of each stream. |
ok | bool = false | It is healthy. |
last_error | str = "" | The last error. |
The example for this item is shown with the ones above: grpc-Calls.salam
Server
struct Server| Name | Type | Description |
|---|---|---|
port | int = 0 | The port. |
listen_fd | i64 = -1 | The listening socket. |
running | bool = false | It is running. |
served | int = 0 | The number of connections answered. |
The example for this item is shown with the ones above: grpc-Calls.salam
Constants and variables
GRPC_OK
const GRPC_OK: i32 = 0The example for this item is shown with the ones above: grpc-Calls.salam
GRPC_CANCELLED
const GRPC_CANCELLED: i32 = 1The example for this item is shown with the ones above: grpc-Wire.salam
GRPC_UNKNOWN
const GRPC_UNKNOWN: i32 = 2The example for this item is shown with the ones above: grpc-Wire.salam
GRPC_INVALID_ARGUMENT
const GRPC_INVALID_ARGUMENT: i32 = 3The example for this item is shown with the ones above: grpc-Wire.salam
GRPC_DEADLINE_EXCEEDED
const GRPC_DEADLINE_EXCEEDED: i32 = 4The example for this item is shown with the ones above: grpc-Wire.salam
GRPC_NOT_FOUND
const GRPC_NOT_FOUND: i32 = 5The example for this item is shown with the ones above: grpc-Wire.salam
GRPC_ALREADY_EXISTS
const GRPC_ALREADY_EXISTS: i32 = 6The example for this item is shown with the ones above: grpc-Wire.salam
GRPC_PERMISSION_DENIED
const GRPC_PERMISSION_DENIED: i32 = 7The example for this item is shown with the ones above: grpc-Calls.salam
GRPC_RESOURCE_EXHAUSTED
const GRPC_RESOURCE_EXHAUSTED: i32 = 8The example for this item is shown with the ones above: grpc-Wire.salam
GRPC_FAILED_PRECONDITION
const GRPC_FAILED_PRECONDITION: i32 = 9The example for this item is shown with the ones above: grpc-Wire.salam
GRPC_ABORTED
const GRPC_ABORTED: i32 = 10The example for this item is shown with the ones above: grpc-Wire.salam
GRPC_OUT_OF_RANGE
const GRPC_OUT_OF_RANGE: i32 = 11The example for this item is shown with the ones above: grpc-Wire.salam
GRPC_UNIMPLEMENTED
const GRPC_UNIMPLEMENTED: i32 = 12The example for this item is shown with the ones above: grpc-Wire.salam
GRPC_INTERNAL
const GRPC_INTERNAL: i32 = 13The example for this item is shown with the ones above: grpc-Wire.salam
GRPC_UNAVAILABLE
const GRPC_UNAVAILABLE: i32 = 14The example for this item is shown with the ones above: grpc-Wire.salam
GRPC_DATA_LOSS
const GRPC_DATA_LOSS: i32 = 15The example for this item is shown with the ones above: grpc-Wire.salam
GRPC_UNAUTHENTICATED
const GRPC_UNAUTHENTICATED: i32 = 16The example for this item is shown with the ones above: grpc-Wire.salam
GRPC_CONTENT_TYPE
const GRPC_CONTENT_TYPE: str = "application/grpc"The example for this item is shown with the ones above: grpc-Wire.salam
GRPC_CONTENT_TYPE_PROTO
const GRPC_CONTENT_TYPE_PROTO: str = "application/grpc+proto"The example for this item is shown with the ones above: grpc-Wire.salam
GRPC_CONTENT_TYPE_JSON
const GRPC_CONTENT_TYPE_JSON: str = "application/grpc+json"The example for this item is shown with the ones above: grpc-Wire.salam
GRPC_COMP_NONE
const GRPC_COMP_NONE: i32 = 0The example for this item is shown with the ones above: grpc-Wire.salam
GRPC_COMP_GZIP
const GRPC_COMP_GZIP: i32 = 1The example for this item is shown with the ones above: grpc-Wire.salam
GRPC_MAX_FRAMES
const GRPC_MAX_FRAMES: i32 = 100000The example for this item is shown with the ones above: grpc-Wire.salam
GRPC_MAX_MESSAGE
const GRPC_MAX_MESSAGE: i32 = 4194304The example for this item is shown with the ones above: grpc-Wire.salam
Functions
NewMetadata
func NewMetadata(): MetadataThe example for this item is shown with the ones above: grpc-Calls.salam
MDAdd
func MDAdd(md &: Metadata, key: str, value: str): boolcontent-type, are rejected.The example for this item is shown with the ones above: grpc-Calls.salam
MDAddBinary
func MDAddBinary(md &: Metadata, key: str, value: str): bool-bin and the value is sent in base64.The example for this item is shown with the ones above: grpc-Wire.salam
MDGet
func MDGet(md: Metadata, key: str): strThe example for this item is shown with the ones above: grpc-Calls.salam
MDHas
func MDHas(md: Metadata, key: str): boolThe example for this item is shown with the ones above: grpc-Wire.salam
MDGetAll
func MDGetAll(md: Metadata, key: str): Vector<str>The example for this item is shown with the ones above: grpc-Wire.salam
MDCount
func MDCount(md: Metadata): intThe example for this item is shown with the ones above: grpc-Calls.salam
MDKeyAt
func MDKeyAt(md: Metadata, i: int): strThe example for this item is shown with the ones above: grpc-Wire.salam
MDValueAt
func MDValueAt(md: Metadata, i: int): strThe example for this item is shown with the ones above: grpc-Wire.salam
MDToHeaders
func MDToHeaders(md: Metadata, hl &: http2.HeaderList)The example for this item is shown with the ones above: grpc-Wire.salam
MDFromHeaders
func MDFromHeaders(hl: http2.HeaderList): MetadataThe example for this item is shown with the ones above: grpc-Wire.salam
NewStatus
func NewStatus(code: int, message: str): StatusThe example for this item is shown with the ones above: grpc-Wire.salam
StatusOk
func StatusOk(s: Status): boolThe example for this item is shown with the ones above: grpc-Calls.salam
MethodPath
func MethodPath(service: str, method: str): str/demo.Greeter/SayHello.The example for this item is shown with the ones above: grpc-Calls.salam
FrameMessage
func FrameMessage(msg: compress.ByteBuf, compressed: bool): compress.ByteBufThe example for this item is shown with the ones above: grpc-Wire.salam
FrameMessageGzip
func FrameMessageGzip(msg: compress.ByteBuf, use_gzip: bool): compress.ByteBufThe example for this item is shown with the ones above: grpc-Wire.salam
FrameMessageStr
func FrameMessageStr(msg: str): compress.ByteBufThe example for this item is shown with the ones above: grpc-Wire.salam
HasMessage
func HasMessage(data: compress.ByteBuf, pos: int): boolThe example for this item is shown with the ones above: grpc-Wire.salam
NextMessage
func NextMessage(data: compress.ByteBuf, pos &: int, ok &: bool): compress.ByteBufThe example for this item is shown with the ones above: grpc-Wire.salam
MessageCount
func MessageCount(data: compress.ByteBuf): intThe example for this item is shown with the ones above: grpc-Wire.salam
Dial
func Dial(host: str, port: int): ChannelThe example for this item is shown with the ones above: grpc-Calls.salam
DialTLS
func DialTLS(host: str, port: int): Channelimport grpc
import net.tcp
func echo(c: i64):
mut ok := false
_ := grpc.SendStr(c, grpc.RecvStr(c, ok))
end
func main:
mut ch := grpc.DialTLS("api.example.com", 443)
if not grpc.ChannelOk(ch):
println grpc.ChannelError(ch)
ret
end
grpc.SetGzip(ch, true)
mut result := grpc.Status {}
println grpc.UnaryCallStr(ch, "/demo.Echo/Say", "hello", result)
grpc.CloseChannel(ch)
grpc.RegisterMethod("/demo.Echo/Say", echo)
mut s := grpc.NewServer(50051)
if grpc.Listen(s):
grpc.Serve(s)
end
conn := tcp.Dial("127.0.0.1", 50052)
_ := grpc.ServeConn(conn.fd)
endChannelOk
func ChannelOk(ch: Channel): boolThe example for this item is shown with the ones above: grpc-Calls.salam
ChannelError
func ChannelError(ch: Channel): strThe example for this item is shown with the ones above: grpc-TLS.salam
SetTimeout
func SetTimeout(ch &: Channel, ms: int)grpc-timeout header.The example for this item is shown with the ones above: grpc-Calls.salam
SetGzip
func SetGzip(ch &: Channel, enable: bool)The example for this item is shown with the ones above: grpc-TLS.salam
CloseChannel
func CloseChannel(ch &: Channel)The example for this item is shown with the ones above: grpc-Calls.salam
StartCall
func StartCall(ch &: Channel, path: str, md: Metadata): intThe example for this item is shown with the ones above: grpc-Calls.salam
SendMessage
func SendMessage(ch &: Channel, sid: int, msg: compress.ByteBuf, last: bool): booltrue on the last message, the sending side is closed.The example for this item is shown with the ones above: grpc-Calls.salam
CloseSend
func CloseSend(ch &: Channel, sid: int): boolThe example for this item is shown with the ones above: grpc-Calls.salam
RecvMessage
func RecvMessage(ch &: Channel, sid: int, ok &: bool): compress.ByteBufThe example for this item is shown with the ones above: grpc-Calls.salam
FinishCall
func FinishCall(ch &: Channel, sid: int): StatusThe example for this item is shown with the ones above: grpc-Calls.salam
CallHeaders
func CallHeaders(ch: Channel, sid: int): MetadataThe example for this item is shown with the ones above: grpc-Calls.salam
CallTrailers
func CallTrailers(ch: Channel, sid: int): MetadataThe example for this item is shown with the ones above: grpc-Calls.salam
UnaryCall
func UnaryCall(ch &: Channel, path: str, req: compress.ByteBuf, md: Metadata, st &: Status): compress.ByteBufThe example for this item is shown with the ones above: grpc-Calls.salam
UnaryCallStr
func UnaryCallStr(ch &: Channel, path: str, req: str, st &: Status): strThe example for this item is shown with the ones above: grpc-Calls.salam
NewServer
func NewServer(port: int): ServerThe example for this item is shown with the ones above: grpc-Calls.salam
RegisterMethod
func RegisterMethod(path: str, fn: i64)The example for this item is shown with the ones above: grpc-Calls.salam
RegisterStreamMethod
func RegisterStreamMethod(path: str, fn: i64, client_stream: bool, server_stream: bool)The example for this item is shown with the ones above: grpc-Calls.salam
MethodCount
func MethodCount(): intThe example for this item is shown with the ones above: grpc-Calls.salam
HasMethod
func HasMethod(path: str): boolThe example for this item is shown with the ones above: grpc-Calls.salam
ResetMethods
func ResetMethods()The example for this item is shown with the ones above: grpc-Calls.salam
CallPath
func CallPath(slot: i64): strThe example for this item is shown with the ones above: grpc-Calls.salam
CallMetadata
func CallMetadata(slot: i64): MetadataThe example for this item is shown with the ones above: grpc-Calls.salam
Recv
func Recv(slot: i64, ok &: bool): compress.ByteBufThe example for this item is shown with the ones above: grpc-Calls.salam
RecvStr
func RecvStr(slot: i64, ok &: bool): strThe example for this item is shown with the ones above: grpc-Calls.salam
Send
func Send(slot: i64, msg: compress.ByteBuf): boolThe example for this item is shown with the ones above: grpc-Calls.salam
SendStr
func SendStr(slot: i64, msg: str): boolThe example for this item is shown with the ones above: grpc-Calls.salam
SetStatus
func SetStatus(slot: i64, code: int, message: str)The example for this item is shown with the ones above: grpc-Calls.salam
Fail
func Fail(slot: i64, code: int, message: str)The example for this item is shown with the ones above: grpc-Calls.salam
Listen
func Listen(s &: Server): boolThe example for this item is shown with the ones above: grpc-Calls.salam
Port
func Port(s: Server): intThe example for this item is shown with the ones above: grpc-Calls.salam
ServeConn
func ServeConn(fd: i64): intThe example for this item is shown with the ones above: grpc-TLS.salam
ServeCount
func ServeCount(s &: Server, n: int): intThe example for this item is shown with the ones above: grpc-Calls.salam
Serve
func Serve(s &: Server)The example for this item is shown with the ones above: grpc-Calls.salam
StopServer
func StopServer(s &: Server)The example for this item is shown with the ones above: grpc-Calls.salam
StatusName
func StatusName(code: int): strNOT_FOUND.The example for this item is shown with the ones above: grpc-Calls.salam
EncodeStatusMessage
func EncodeStatusMessage(msg: str): strgrpc-message header.The example for this item is shown with the ones above: grpc-Wire.salam
DecodeStatusMessage
func DecodeStatusMessage(msg: str): strThe example for this item is shown with the ones above: grpc-Wire.salam
FormatStatusCode
func FormatStatusCode(code: int): strThe example for this item is shown with the ones above: grpc-Wire.salam
ParseStatusCode
func ParseStatusCode(text: str): intThe example for this item is shown with the ones above: grpc-Wire.salam
StatusString
func StatusString(s: Status): strNAME: message.The example for this item is shown with the ones above: grpc-Calls.salam