Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,18 @@ jobs:
go-version: 1.26.x
- name: Run Slow Tests
run: make slowtest
migrate:
name: migrate
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v7
with:
fetch-depth: 1
- name: Install Go
uses: actions/setup-go@v6
with:
# only the latest
go-version: 1.26.x
Comment thread
emcfarlane marked this conversation as resolved.
Outdated
- name: Test Migration Tool
run: make testmigrate
2 changes: 1 addition & 1 deletion .github/workflows/windows.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ jobs:
shell: bash
run: |
go build ./...
go test -vet=off -race ./...
go test -vet=off -timeout 30m ./...
69 changes: 56 additions & 13 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,15 @@ linters:
# We need our duplex HTTP call to have access to the context.
- linters:
- containedctx
path: duplex_http_call.go
path: connecthttp/duplex_http_call.go
# The in-process stream needs to capture the call context for cancellation.
- linters:
- containedctx
path: connectinprocess/stream.go
# The test conn wraps a stream and holds the call context to inspect headers.
- linters:
- containedctx
path: connecthttp/interceptor_ext_test.go
# blockUntilResponseReady returns the shared response, whose body is
# closed once by CloseRead rather than at each call site.
- linters:
Expand All @@ -82,7 +90,7 @@ linters:
- linters:
- gochecknoglobals
- gochecknoinits
path: example_init_test.go
path: connecthttp/example_init_test.go
# We purposefully do an ineffectual assignment for an example.
- linters:
- ineffassign
Expand All @@ -96,57 +104,84 @@ linters:
- linters:
- errcheck
- gosec
path: error_writer_example_test.go
path: connecthttp/error_writer_example_test.go
# It should be crystal clear that Connect uses plain *http.Clients.
- linters:
- revive
- staticcheck
path: client_example_test.go
path: connecthttp/client_example_test.go
# Don't complain about timeout management or lack of output assertions in examples.
- linters:
- gosec
- testableexamples
path: handler_example_test.go
path: connecthttp/handler_example_test.go
# No output assertions needed for these examples.
- linters:
- testableexamples
path: error_writer_example_test.go
path: connecthttp/error_writer_example_test.go
- linters:
- testableexamples
path: error_not_modified_example_test.go
path: connecthttp/error_not_modified_example_test.go
- linters:
- testableexamples
path: error_example_test.go
path: connecthttp/error_example_test.go
# In examples, it's okay to use http.ListenAndServe.
- linters:
- gosec
path: error_not_modified_example_test.go
path: connecthttp/error_not_modified_example_test.go
# There are many instances where we want to keep unused parameters
# as a matter of style or convention, for example when a context.Context
# is the first parameter, we choose to just globally ignore this.
- linters:
- revive
text: '^unused-parameter: '
# The interface is an unexported v1 internal interface.
- linters:
- interfacebloat
path: connecthttp/protocol.go
# We want to return explicit nils in protocol_grpc.go
- linters:
- revive
path: protocol_grpc.go
path: connecthttp/protocol_grpc.go
text: '^if-return: '
# The gRPC error marshaling keeps its nested structure for clarity.
- linters:
- nestif
path: connecthttp/protocol_grpc.go
# connectWireDetail embeds *anypb.Any, keep the explicit selector.
- linters:
- staticcheck
path: connecthttp/protocol_connect.*\.go
text: 'QF1008: '
# We want to return explicit nils in protocol_connect.go
- linters:
- revive
path: protocol_connect.go
path: connecthttp/protocol_connect.go
text: '^if-return: '
# We want to return explicit nils in error_writer.go
- linters:
- revive
path: error_writer.go
path: connecthttp/error_writer.go
text: '^if-return: '
# We want to set http.Server's logger
- linters:
- forbidigo
path: internal/memhttp
text: use of `log.(New|Logger|Lshortfile)` forbidden by pattern .*
# The migration CLI writes its report to stdout.
- linters:
- forbidigo
path: cmd/connect-go-v2-migrate
text: use of `fmt.Print.*` forbidden by pattern .*
# The migration CLI keeps its rewrite rules in static lookup tables.
- linters:
- gochecknoglobals
path: cmd/connect-go-v2-migrate
# The interceptor example sets a *log.Logger on its stream wrapper.
- linters:
- forbidigo
path: connecthttp/interceptor_example_test.go
text: use of `log.Logger` forbidden by pattern .*
# We want to show examples with http.Get
- linters:
- noctx
Expand All @@ -159,10 +194,18 @@ linters:
- linters:
- canonicalheader
path: .*_test.go
# TestServer is a large table-driven test.
- linters:
- gocyclo
path: connecthttp/connect_ext_test.go
# The benchmark builds a fresh option slice per client.
- linters:
- gocritic
path: connecthttp/bench_test.go
# Allow Code pointer receiver for UnmarshalText method
- linters:
- recvcheck
path: code.go
path: connect.go
# Avoid false positives for int overflow in tests
- linters:
- gosec
Expand Down
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ slowtest: build
runconformance: build ## Run conformance test suite
cd internal/conformance && ./runconformance.sh

.PHONY: testmigrate
testmigrate: ## Run connect-go-v2-migrate test suite
cd cmd/connect-go-v2-migrate && go test ./...

.PHONY: bench
bench: BENCH ?= .*
bench: build ## Run benchmarks for root package
Expand Down Expand Up @@ -82,6 +86,7 @@ generate: $(BIN)/buf $(BIN)/protoc-gen-go $(BIN)/protoc-gen-connect-go $(BIN)/li
go mod tidy
cd ./internal/conformance && go mod tidy
buf generate
cd internal/conformance && buf generate --template buf.gen.yaml buf.build/connectrpc/conformance
cd ./cmd/protoc-gen-connect-go/internal && \
find ./testdata -maxdepth 1 -type d \( ! -name testdata \) | xargs -n 1 -I % bash -c "cd '%' && buf generate"
license-header \
Expand Down
63 changes: 39 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ on [connectrpc.com][docs] (especially the [Getting Started] guide for Go), the

Curious what all this looks like in practice? From a [Protobuf
schema](internal/proto/connect/ping/v1/ping.proto), we generate [a small RPC
package](internal/gen/simple/connect/ping/v1/pingv1connect/ping.connect.go). Using that
package](internal/gen/connect/ping/v1/pingv1connect/ping.connect.go). Using that
package, we can build a server. This example is available at [internal/example](internal/example):

```go
Expand All @@ -63,10 +63,11 @@ import (
"log"
"net/http"

"connectrpc.com/connect"
pingv1 "connectrpc.com/connect/internal/gen/connect/ping/v1"
"connectrpc.com/connect/internal/gen/simple/connect/ping/v1/pingv1connect"
"connectrpc.com/validate"
"connectrpc.com/connect/v2"
"connectrpc.com/connect/v2/connecthttp"
pingv1 "connectrpc.com/connect/v2/internal/gen/connect/ping/v1"
"connectrpc.com/connect/v2/internal/gen/connect/ping/v1/pingv1connect"
"connectrpc.com/validate/v2"
)

type PingServer struct {
Expand All @@ -80,16 +81,13 @@ func (ps *PingServer) Ping(ctx context.Context, req *pingv1.PingRequest) (*pingv
}

func main() {
// Register services on a *connect.Server, then mount it with connecthttp.
// Interceptors are arguments to NewServer. Validation via Protovalidate is
// almost always recommended.
server := connect.NewServer(validate.NewServerInterceptor())
pingv1connect.RegisterPingServiceHandler(server, &PingServer{})
mux := http.NewServeMux()
// The generated constructors return a path and a plain net/http
// handler.
mux.Handle(
pingv1connect.NewPingServiceHandler(
&PingServer{},
// Validation via Protovalidate is almost always recommended
connect.WithInterceptors(validate.NewInterceptor()),
),
)
connecthttp.Mount(mux, server)
p := new(http.Protocols)
p.SetHTTP1(true)
// For gRPC clients, it's convenient to support HTTP/2 without TLS.
Expand All @@ -116,17 +114,19 @@ import (
"log"
"net/http"

pingv1 "connectrpc.com/connect/internal/gen/connect/ping/v1"
"connectrpc.com/connect/internal/gen/simple/connect/ping/v1/pingv1connect"
"connectrpc.com/connect/v2"
"connectrpc.com/connect/v2/connecthttp"
pingv1 "connectrpc.com/connect/v2/internal/gen/connect/ping/v1"
"connectrpc.com/connect/v2/internal/gen/connect/ping/v1/pingv1connect"
)

func main() {
client := pingv1connect.NewPingServiceClient(
http.DefaultClient,
"http://localhost:8080/",
client := connect.NewClient(
connecthttp.NewTransport(http.DefaultClient, "http://localhost:8080"),
)
pingClient := pingv1connect.NewPingServiceClient(client)
req := &pingv1.PingRequest{Number: 42}
res, err := client.Ping(context.Background(), req)
res, err := pingClient.Ping(context.Background(), req)
if err != nil {
log.Fatalln(err)
}
Expand All @@ -138,6 +138,13 @@ Of course, `http.ListenAndServe` and `http.DefaultClient` aren't fit for
production use! See Connect's [deployment docs][docs-deployment] for a guide to
configuring timeouts, connection pools, observability, and h2c.

## Migrating from v1

If you are migrating from v1 to v2, check out our [migration guide](./docs/v2-migration.md).

This project follows semantic versioning. The module `/v2` suffix is part of
the module `connectrpc.com/connect/v2`.

## Ecosystem

* [grpchealth]: gRPC-compatible health checks for connect-go
Expand All @@ -148,16 +155,24 @@ configuring timeouts, connection pools, observability, and h2c.
* [Buf Studio]: web UI for ad-hoc RPCs
* [conformance]: Connect, gRPC, and gRPC-Web interoperability tests

## Status: Stable
## Status

This module is stable. It supports:
This module, `connectrpc.com/connect/v2`, is in beta.
The `v2` module will be published on the `main` branch of the repository when released.
Comment on lines +160 to +161

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit unclear to me what that means. Is the plan to merge this branch to main and maintain v1 in a v1 branch, or to keep the v2 branch going until a stable release? I believe that merging to main is more user-friendly because the docs and migration guide are easier to discover.

RELEASE.md still references v1.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intent is to merge v2 to main and create a v1 branch to maintain v1. The first release will be v2.0.0-alpha.1. It can be off this v2 branch, which would help users test this proposal, but the intent is to merge to main first and do the alpha release off main. The RELEASE.md needs updating.


## Support and versioning

`connect-go` supports:

* The two most recent major releases of Go (the same versions of Go that continue
to [receive security patches][go-support-policy]).
* [APIv2] of Protocol Buffers in Go (`google.golang.org/protobuf`).

Within those parameters, `connect` follows semantic versioning. We will
_not_ make breaking changes in the 1.x series of releases.
Within those parameters, `connect-go` follows semantic versioning.

Module `connectrpc.com/connect` is the `v1` module. It remains stable and
supported indefinitely. The `v1` module lives on the `v1` branch.
See the [v2 guide](docs/v2-guide.md) for an overview of what changed and why.

## Legal

Expand Down
9 changes: 2 additions & 7 deletions buf.gen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,12 @@ managed:
enabled: true
override:
- file_option: go_package_prefix
value: connectrpc.com/connect/internal/gen
value: connectrpc.com/connect/v2/internal/gen
plugins:
- local: protoc-gen-go
out: internal/gen
opt: paths=source_relative
- local: protoc-gen-connect-go
out: internal/gen/generics
out: internal/gen
opt: paths=source_relative
- local: protoc-gen-connect-go
out: internal/gen/simple
opt:
- paths=source_relative
- simple
clean: true
54 changes: 0 additions & 54 deletions buffer_pool.go

This file was deleted.

Loading
Loading