api/transport.go
Snider da1839f730 feat(api): webhooks + sunset headers + WithWebSocket + cmd/api migration
- webhook.go: HMAC-SHA256 WebhookSigner matching PHP WebhookSignature —
  sign/verify, X-Webhook-Signature / X-Webhook-Timestamp headers,
  VerifyRequest middleware helper, 5-minute default tolerance,
  secret generator (RFC §6)
- sunset.go: ApiSunsetWith(date, replacement, opts...) + WithSunsetNoticeURL;
  ApiSunset now emits API-Suggested-Replacement when replacement set;
  RouteDescription.NoticeURL surfaces API-Deprecation-Notice-URL (RFC §8)
- options.go + api.go + transport.go: WithWebSocket(gin.HandlerFunc)
  alongside existing WithWSHandler(http.Handler); gin form wins when
  both supplied (RFC §2.2)
- openapi.go: apiSuggestedReplacement + apiDeprecationNoticeURL as
  reusable header components; NoticeURL on a RouteDescription flips
  operation deprecated flag and emits response header doc
- cmd/api/*.go: migrated from Cobra (cli.NewCommand, StringFlag) to
  new path-based CLI API (c.Command + core.Options.String/Int/Bool);
  replaces the 1,422-line Cobra test suite with _Good/_Bad/_Ugly
  triads on the new surface
- webhook_test.go + sunset_test.go + websocket_test.go: full coverage

Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-14 14:51:04 +01:00

69 lines
1.9 KiB
Go

// SPDX-License-Identifier: EUPL-1.2
package api
import core "dappco.re/go/core"
// TransportConfig captures the configured transport endpoints and flags for an Engine.
//
// It is intentionally small and serialisable so callers can inspect the active HTTP
// surface without rebuilding an OpenAPI document.
//
// Example:
//
// cfg := api.TransportConfig{SwaggerPath: "/swagger", WSPath: "/ws"}
type TransportConfig struct {
SwaggerEnabled bool
SwaggerPath string
GraphQLPath string
GraphQLEnabled bool
GraphQLPlayground bool
GraphQLPlaygroundPath string
WSEnabled bool
WSPath string
SSEEnabled bool
SSEPath string
PprofEnabled bool
ExpvarEnabled bool
}
// TransportConfig returns the currently configured transport metadata for the engine.
//
// The result snapshots the Engine state at call time and normalises any configured
// URL paths using the same rules as the runtime handlers.
//
// Example:
//
// cfg := engine.TransportConfig()
func (e *Engine) TransportConfig() TransportConfig {
if e == nil {
return TransportConfig{}
}
cfg := TransportConfig{
SwaggerEnabled: e.swaggerEnabled,
WSEnabled: e.wsHandler != nil || e.wsGinHandler != nil,
SSEEnabled: e.sseBroker != nil,
PprofEnabled: e.pprofEnabled,
ExpvarEnabled: e.expvarEnabled,
}
gql := e.GraphQLConfig()
cfg.GraphQLEnabled = gql.Enabled
cfg.GraphQLPlayground = gql.Playground
cfg.GraphQLPlaygroundPath = gql.PlaygroundPath
if e.swaggerEnabled || core.Trim(e.swaggerPath) != "" {
cfg.SwaggerPath = resolveSwaggerPath(e.swaggerPath)
}
if gql.Path != "" {
cfg.GraphQLPath = gql.Path
}
if e.wsHandler != nil || e.wsGinHandler != nil || core.Trim(e.wsPath) != "" {
cfg.WSPath = resolveWSPath(e.wsPath)
}
if e.sseBroker != nil || core.Trim(e.ssePath) != "" {
cfg.SSEPath = resolveSSEPath(e.ssePath)
}
return cfg
}