Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
14 changes: 11 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ assets-dev:

## clean: remove build artifacts and test coverage
clean:
rm -rf bin/ release/ coverage.txt internal/templates/static/dist/
rm -rf bin/ release/ coverage.txt internal/templates/static/dist/ internal/gen/
find internal/templates -name "*_templ.go" -delete
rm -f internal/templates/asset_paths.go

Expand All @@ -101,14 +101,22 @@ rebuild: clean build
.PHONY: build_all_linux_amd64 build_all_linux_arm64 generate watch air dev mocks
.PHONY: install-tools mod-download mod-tidy mod-verify check-tools version
.PHONY: docker-build docker-run swagger swagger-init swagger-fmt swagger-validate
.PHONY: assets assets-dev
.PHONY: assets assets-dev proto proto-lint

## install-tools: download tool dependencies
install-tools:
$(GO) mod download $(TOOLS_MOD)

## proto: generate protobuf and connect-go code
proto:
buf generate

## proto-lint: lint protobuf definitions
proto-lint:
buf lint

## generate: run go generate (templ compilation + mocks via go:generate directives)
generate: install-tools assets swagger
generate: install-tools assets swagger proto
$(GO) generate ./...
Comment on lines +110 to 120

## mocks: generate mock files only (all directives in internal/mocks/)
Expand Down
8 changes: 8 additions & 0 deletions buf.gen.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version: v2
plugins:
- remote: buf.build/protocolbuffers/go
out: internal/gen
opt: paths=source_relative
- remote: buf.build/connectrpc/go
out: internal/gen
opt: paths=source_relative
9 changes: 9 additions & 0 deletions buf.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version: v2
modules:
- path: proto
lint:
use:
- STANDARD
breaking:
use:
- FILE
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/go-authgate/authgate
go 1.25.0

require (
connectrpc.com/connect v1.19.1
github.com/a-h/templ v0.3.1001
github.com/appleboy/com v1.2.0
github.com/appleboy/go-httpclient v0.10.0
Expand All @@ -29,6 +30,7 @@ require (
go.uber.org/mock v0.6.0
golang.org/x/crypto v0.49.0
golang.org/x/oauth2 v0.36.0
google.golang.org/protobuf v1.36.11
gorm.io/driver/postgres v1.6.0
gorm.io/driver/sqlite v1.6.0
gorm.io/gorm v1.31.1
Expand Down Expand Up @@ -147,6 +149,5 @@ require (
golang.org/x/text v0.35.0 // indirect
golang.org/x/tools v0.42.0 // indirect
google.golang.org/grpc v1.79.1 // indirect
google.golang.org/protobuf v1.36.11 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
connectrpc.com/connect v1.19.1 h1:R5M57z05+90EfEvCY1b7hBxDVOUl45PrtXtAV2fOC14=
connectrpc.com/connect v1.19.1/go.mod h1:tN20fjdGlewnSFeZxLKb0xwIZ6ozc3OQs2hTXy4du9w=
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
github.com/AdaLogics/go-fuzz-headers v0.0.0-20240806141605-e8a1dd7889d6 h1:He8afgbRMd7mFxO99hRNu+6tazq8nFF9lIwo9JFroBk=
Expand Down
5 changes: 3 additions & 2 deletions internal/bootstrap/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,9 @@ func (app *Application) initializeHTTPLayer() {
oauthProviders,
)

// HTTP Server
app.Server = createHTTPServer(app.Config, app.Router)
// HTTP Server (composite handler routes connect-go services + Gin)
compositeHandler := createCompositeHandler(app.DB, app.Router)
app.Server = createHTTPServer(app.Config, compositeHandler)
}

// startWithGracefulShutdown starts the server and handles graceful shutdown
Expand Down
18 changes: 18 additions & 0 deletions internal/bootstrap/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ import (
"time"

"github.com/go-authgate/authgate/internal/config"
authconnect "github.com/go-authgate/authgate/internal/connectrpc"
"github.com/go-authgate/authgate/internal/core"
"github.com/go-authgate/authgate/internal/gen/health/v1/healthv1connect"
"github.com/go-authgate/authgate/internal/metrics"
"github.com/go-authgate/authgate/internal/models"
"github.com/go-authgate/authgate/internal/services"
Expand All @@ -29,6 +31,22 @@ func createHTTPServer(cfg *config.Config, handler http.Handler) *http.Server {
}
}

// createCompositeHandler creates an http.Handler that routes connect-go services
// by path prefix, falling back to the Gin router for everything else.
func createCompositeHandler(db *store.Store, ginRouter http.Handler) http.Handler {
mux := http.NewServeMux()

// Register connect-go HealthService
healthServer := authconnect.NewHealthServer(db)
path, handler := healthv1connect.NewHealthServiceHandler(healthServer)
mux.Handle(path, handler)

// Fall back to Gin for all other routes
mux.Handle("/", ginRouter)

return mux
}

// addServerRunningJob adds the HTTP server running job
func addServerRunningJob(m *graceful.Manager, srv *http.Server) {
m.AddRunningJob(func(ctx context.Context) error {
Expand Down
40 changes: 40 additions & 0 deletions internal/connectrpc/health.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package connectrpc

import (
"context"

"connectrpc.com/connect"

healthv1 "github.com/go-authgate/authgate/internal/gen/health/v1"
"github.com/go-authgate/authgate/internal/gen/health/v1/healthv1connect"
"github.com/go-authgate/authgate/internal/store"
)

// HealthServer implements the connect-go HealthService.
type HealthServer struct {
healthv1connect.UnimplementedHealthServiceHandler
db *store.Store
}

// NewHealthServer creates a new HealthServer.
func NewHealthServer(db *store.Store) *HealthServer {
return &HealthServer{db: db}
}

// Check returns the health status of the service.
func (s *HealthServer) Check(
_ context.Context,
_ *connect.Request[healthv1.HealthCheckRequest],
) (*connect.Response[healthv1.HealthCheckResponse], error) {
resp := &healthv1.HealthCheckResponse{}

if err := s.db.Health(); err != nil {
resp.Status = healthv1.HealthCheckResponse_SERVING_STATUS_NOT_SERVING
resp.Database = "disconnected"
} else {
resp.Status = healthv1.HealthCheckResponse_SERVING_STATUS_SERVING
resp.Database = "connected"
}

return connect.NewResponse(resp), nil
}
38 changes: 38 additions & 0 deletions internal/connectrpc/health_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package connectrpc

import (
"context"
"net/http"
"net/http/httptest"
"testing"

"connectrpc.com/connect"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/go-authgate/authgate/internal/config"
healthv1 "github.com/go-authgate/authgate/internal/gen/health/v1"
"github.com/go-authgate/authgate/internal/gen/health/v1/healthv1connect"
"github.com/go-authgate/authgate/internal/store"
)

func TestHealthServer_Check_Serving(t *testing.T) {
db, err := store.New(context.Background(), "sqlite", ":memory:", &config.Config{})
require.NoError(t, err)

mux := http.NewServeMux()
path, handler := healthv1connect.NewHealthServiceHandler(NewHealthServer(db))
mux.Handle(path, handler)

srv := httptest.NewServer(mux)
defer srv.Close()

client := healthv1connect.NewHealthServiceClient(srv.Client(), srv.URL)
resp, err := client.Check(
context.Background(),
connect.NewRequest(&healthv1.HealthCheckRequest{}),
)
require.NoError(t, err)
assert.Equal(t, healthv1.HealthCheckResponse_SERVING_STATUS_SERVING, resp.Msg.Status)
assert.Equal(t, "connected", resp.Msg.Database)
}
Loading
Loading