Golang中启用GraphQL订阅时遇到问题:Playground未检测到订阅并提示'schema不支持订阅'
Golang中启用GraphQL订阅时遇到问题:Playground未检测到订阅并提示’schema不支持订阅’
在Go的GraphQL API中,我使用gqlgen实现了订阅功能。我定义了Subscription类型,使其返回布尔值或当前服务器时间。我运行了generate命令来应用更改并获取自动生成的代码。在schemaresolvers.go中,我使用goroutine实现了逻辑。在main.go中,我配置了带有传输层和WebSocket的服务器。然而,Playground无法检测到订阅,并且当我在Playground中尝试使用subscription时,会收到以下错误:“Schema does not support operation type ‘subscription’。”
“github.com/99designs/gqlgen/graphql/handler/transport”
main.go
func NewGraphQLHandler(dbInstance *gorm.DB) (http.Handler, error) {
c := generated.Config{
Resolvers: &graph.Resolver{
DB: dbInstance,
},
}
c.Directives.Auth = directives.Auth
srv := handler.NewDefaultServer(generated.NewExecutableSchema(c))
//agregar websocket, no detecta la subscription en el playground
srv.AddTransport(&transport.Websocket)
return srv, nil
}
Configuration main.go
func registerHandlers(lifecycle fx.Lifecycle, router *mux.Router, graphqlHandler http.Handler) {
router.Handle("/", playground.Handler("GraphQL playground", "/query"))
router.Handle("/query", graphqlHandler)
router.Handle("/subscriptions", graphqlHandler)
schemaresolvers.go
func (r *subscriptionResolver) ServerEvents(ctx context.Context) (<-chan bool, error) {
//creamos el channel
result := make(chan bool)
//go routine
go func() {
//el ping cada 5 segundos que se enviara al canal
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
result <- true //se envia true al canal
case <-ctx.Done():
//cuando el cliente se desconecta se cierra
close(result)
fmt.Println("Subscripcion cerrada")
return
}
}
}()
return result, nil
}
Schema
type Subscription {
serverEvents: Boolean!
}
更多关于Golang中启用GraphQL订阅时遇到问题:Playground未检测到订阅并提示'schema不支持订阅'的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于Golang中启用GraphQL订阅时遇到问题:Playground未检测到订阅并提示'schema不支持订阅'的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go中启用GraphQL订阅时,Playground提示"schema不支持订阅"通常是由于WebSocket传输层配置不完整导致的。您需要正确配置WebSocket传输层并启用订阅功能。以下是修改后的main.go配置:
func NewGraphQLHandler(dbInstance *gorm.DB) (http.Handler, error) {
c := generated.Config{
Resolvers: &graph.Resolver{
DB: dbInstance,
},
}
c.Directives.Auth = directives.Auth
// 创建可执行schema
executableSchema := generated.NewExecutableSchema(c)
// 创建GraphQL处理器
srv := handler.NewDefaultServer(executableSchema)
// 配置WebSocket传输层,启用KeepAlive和订阅
srv.AddTransport(&transport.Websocket{
KeepAlivePingInterval: 10 * time.Second,
InitFunc: func(ctx context.Context, initPayload transport.InitPayload) (context.Context, error) {
return ctx, nil
},
})
// 添加必要的传输层
srv.AddTransport(transport.Options{})
srv.AddTransport(transport.GET{})
srv.AddTransport(transport.POST{})
srv.AddTransport(transport.MultipartForm{})
// 启用订阅
srv.Use(extension.Introspection{})
return srv, nil
}
同时确保路由配置正确:
func registerHandlers(lifecycle fx.Lifecycle, router *mux.Router, graphqlHandler http.Handler) {
// GraphQL Playground配置
router.Handle("/", playground.Handler("GraphQL playground", "/query"))
// GraphQL端点
router.Handle("/query", graphqlHandler)
// 如果需要单独的订阅端点
router.Handle("/subscriptions", graphqlHandler)
// 或者使用WebSocket端点
router.Handle("/ws", graphqlHandler)
}
对于schemaresolvers.go,确保返回类型与schema匹配:
func (r *subscriptionResolver) ServerEvents(ctx context.Context) (<-chan bool, error) {
result := make(chan bool)
go func() {
defer close(result)
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
for {
select {
case <-ticker.C:
select {
case result <- true:
// 成功发送数据
case <-ctx.Done():
return
}
case <-ctx.Done():
return
}
}
}()
return result, nil
}
检查生成的schema文件,确保订阅类型正确生成:
// 在generated.go中应该有以下内容
type SubscriptionResolver interface {
ServerEvents(ctx context.Context) (<-chan bool, error)
}
最后,在Playground中测试订阅时,使用正确的WebSocket连接:
subscription {
serverEvents
}
如果问题仍然存在,检查gqlgen版本并确保在gqlgen.yml中启用了订阅:
# gqlgen.yml
subscription:
filename: graph/subscription.resolvers.go
type: Subscription
运行生成命令:
go run github.com/99designs/gqlgen generate

