我尝试使用ApolloClient从我的响应前端订阅我根据https://github.com/graphql-python/graphql-ws/blob/master/examples/flask_gevent/app.py实现的Python GraphQL服务器。
我的前端订阅看起来像这样
client.subscribe({
query: gql`
subscription{
count_seconds
}
`
}).subscribe({
next(data) {
console.log("New data received from subscription");
}
});
但是我的服务器抱怨
Traceback (most recent call last):
File "C:\Users\Adrian\Miniconda3\lib\site-packages\gevent\pywsgi.py", line 976, in handle_one_response
self.run_application()
File "C:\Users\Adrian\Miniconda3\lib\site-packages\geventwebsocket\handler.py", line 75, in run_application
self.run_websocket()
File "C:\Users\Adrian\Miniconda3\lib\site-packages\geventwebsocket\handler.py", line 52, in run_websocket
list(self.application(self.environ, lambda s, h, e=None: []))
File "C:\Users\Adrian\Miniconda3\lib\site-packages\flask\app.py", line 2463, in __call__
return self.wsgi_app(environ, start_response)
File "C:\Users\Adrian\Miniconda3\lib\site-packages\flask_sockets.py", line 45, in __call__
handler(environment, **values)
File "C:\Users\Adrian\Miniconda3\lib\site-packages\flask_cors\decorator.py", line 128, in wrapped_function
resp = make_response(f(*args, **kwargs))
File "C:\Users\Adrian\Miniconda3\lib\site-packages\flask\helpers.py", line 223, in make_response
return current_app.make_response(args)
File "C:\Users\Adrian\Miniconda3\lib\site-packages\flask\app.py", line 2130, in make_response
" {rv.__class__.__name__}.".format(rv=rv)
TypeError: The view function did not return a valid response. The return type must be a string, dict, tuple, Response instance, or WSGI callable, but it was a list.
2020-03-27T21:16:07Z {'REMOTE_ADDR': '::1', 'REMOTE_PORT': '55650', 'HTTP_HOST': 'localhost:5000', (hidden keys: 32)} failed with TypeError
我的服务器实现
from flask import Flask, make_response, request
from flask_sockets import Sockets
from flask_cors import CORS, cross_origin
from flask_graphql import GraphQLView
from graphql_ws.gevent import GeventSubscriptionServer
from schema import schema
from gevent import pywsgi
from geventwebsocket.handler import WebSocketHandler
from graphql.backend import GraphQLCoreBackend
app = Flask(__name__)
app.debug = False
cors = CORS(app, resources={r"/graphql/*": {"origins": "*"}})
app.config['CORS_HEADERS'] = 'Content-Type'
sub_server = GeventSubscriptionServer(schema)
sockets = Sockets(app)
class Server:
def __init__(self):
self.server = pywsgi.WSGIServer(('', 5000), app, handler_class=WebSocketHandler)
app.add_url_rule('/graphql', view_func=GraphQLView.as_view('graphql', schema=schema, graphiql=False))
app.app_protocol = lambda environ_path_info: 'graphql-ws'
self.server.serve_forever()
@sockets.route('/subscriptions')
@cross_origin()
def echo_socket(ws):
sub_server.handle(ws)
return []
我不知道这是什么根本原因,...返回的列表到底在哪里,我还应该有其他东西?
也许schema
也很重要
import graphene
from rx import Observable
import random
class Query(graphene.ObjectType):
hello = graphene.String(name=graphene.String(default_value="World"))
def resolve_hello(self, info, name):
print("answer query")
return 'Hello ' + name
class RandomType(graphene.ObjectType):
seconds = graphene.Int()
random_int = graphene.Int()
class Subscription(graphene.ObjectType):
count_seconds = graphene.Int(up_to=graphene.Int())
random_int = graphene.Field(RandomType)
def resolve_count_seconds(self, info, up_to=5):
print("new subscription")
return Observable.interval(1000) \
.map(lambda i: "{0}".format(i)) \
.take_while(lambda i: int(i) <= up_to)
def resolve_random_int(self, info):
return Observable.interval(1000).map(lambda i: RandomType(seconds=i, random_int=random.randint(0, 500)))
schema = graphene.Schema(query=Query, subscription=Subscription)