Connect
Connect is a slim library for building browser and gRPC-compatible HTTP APIs.
You write a short Protocol Buffer schema and implement your
application logic, and Connect generates code to handle marshaling, routing,
compression, and content type negotiation. It also generates an idiomatic,
type-safe client. Handlers and clients support three protocols: gRPC, gRPC-Web,
and Connect's own protocol.
The Connect protocol is a simple protocol that works over HTTP/1.1
or HTTP/2. It takes the best portions of gRPC and gRPC-Web, including
streaming, and packages them into a protocol that works equally well in
browsers, monoliths, and microservices. Calling a Connect API is as easy as
using curl
. Try it with our live demo:
curl \
--header "Content-Type: application/json" \
--data '{"sentence": "I feel happy."}' \
https://demo.connect.build/buf.connect.demo.eliza.v1.ElizaService/Say
Handlers and clients also support the gRPC and gRPC-Web protocols, including
streaming, headers, trailers, and error details. gRPC-compatible server
reflection and health checks are available as standalone packages.
Instead of cURL, we could call our API with buf curl
:
go install github.com/bufbuild/buf/cmd/buf@latest
buf curl --protocol grpc \
--data '{"sentence": "I feel happy."}' \
https://demo.connect.build/buf.connect.demo.eliza.v1.ElizaService/Say
Under the hood, Connect is just Protocol Buffers and the standard
library: no custom HTTP implementation, no new name resolution or load
balancing APIs, and no surprises. Everything you already know about net/http
still applies, and any package that works with an http.Server
, http.Client
,
or http.Handler
also works with Connect.
For more on Connect, see the announcement blog post, the documentation
on connect.build (especially the Getting Started guide for Go), the
demo service, or the protocol specification.
A small example
Curious what all this looks like in practice? From a Protobuf
schema, we generate a small RPC
package. Using that
package, we can build a server:
package main
import (
"context"
"log"
"net/http"
"github.com/bufbuild/connect-go"
pingv1 "github.com/bufbuild/connect-go/internal/gen/connect/ping/v1"
"github.com/bufbuild/connect-go/internal/gen/connect/ping/v1/pingv1connect"
"golang.org/x/net/http2"
"golang.org/x/net/http2/h2c"
)
type PingServer struct {
pingv1connect.UnimplementedPingServiceHandler
}
func (ps *PingServer) Ping(
ctx context.Context,
req *connect.Request[pingv1.PingRequest],
) (*connect.Response[pingv1.PingResponse], error) {
log.Println(req.Header().Get("Some-Header"))
res := connect.NewResponse(&pingv1.PingResponse{
Number: req.Msg.Number,
})
res.Header().Set("Some-Other-Header", "hello!")
return res, nil
}
func main() {
mux := http.NewServeMux()
mux.Handle(pingv1connect.NewPingServiceHandler(&PingServer{}))
err := http.ListenAndServe(
"localhost:8080",
h2c.NewHandler(mux, &http2.Server{}),
)
log.Fatalf("listen failed: %v", err)
}
With that server running, you can make requests with any gRPC or Connect
client. To write a client using connect-go
,
package main
import (
"context"
"log"
"net/http"
"github.com/bufbuild/connect-go"
pingv1 "github.com/bufbuild/connect-go/internal/gen/connect/ping/v1"
"github.com/bufbuild/connect-go/internal/gen/connect/ping/v1/pingv1connect"
)
func main() {
client := pingv1connect.NewPingServiceClient(
http.DefaultClient,
"http://localhost:8080/",
)
req := connect.NewRequest(&pingv1.PingRequest{
Number: 42,
})
req.Header().Set("Some-Header", "hello from connect")
res, err := client.Ping(context.Background(), req)
if err != nil {
log.Fatalln(err)
}
log.Println(res.Msg)
log.Println(res.Header().Get("Some-Other-Header"))
}
Of course, http.ListenAndServe
and http.DefaultClient
aren't fit for
production use! See Connect's deployment docs for a guide to
configuring timeouts, connection pools, observability, and h2c.
Ecosystem
Status: Stable
This module is stable. It supports:
Within those parameters, connect-go
follows semantic versioning. We will
not make breaking changes in the 1.x series of releases.
Legal
Offered under the Apache 2 license.