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

1 回复

更多关于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
回到顶部