def server(module, host, port): sys.path.append(os.getcwd()) reloader = hupper.start_reloader("strawberry.cli.run", verbose=False) schema_module = importlib.import_module(module) reloader.watch_files([schema_module.__file__]) app = Starlette(debug=True) app.add_middleware(CORSMiddleware, allow_headers=["*"], allow_origins=["*"], allow_methods=["*"]) graphql_app = GraphQL(schema_module.schema, debug=True) paths = ["/", "/graphql"] for path in paths: app.add_route(path, graphql_app) app.add_websocket_route(path, graphql_app) print(f"Running strawberry on http://{host}:{port}/ 🍓") uvicorn.run(app, host=host, port=port, log_level="error")
def create_app(): app = Starlette() app.add_route("/auth", with_auth, methods=["GET"]) app.add_route("/no-auth", without_auth, methods=["GET"]) app.add_websocket_route("/ws-auth", ws_with_auth) app.add_websocket_route("/ws-no-auth", ws_without_auth) return app
def server(schema, host, port, app_dir): sys.path.insert(0, app_dir) try: schema_symbol = import_module_symbol(schema, default_symbol_name="schema") except (ImportError, AttributeError) as exc: message = str(exc) raise click.BadArgumentUsage(message) if not isinstance(schema_symbol, Schema): message = "The `schema` must be an instance of strawberry.Schema" raise click.BadArgumentUsage(message) reloader = hupper.start_reloader("strawberry.cli.run", verbose=False) schema_module = importlib.import_module(schema_symbol.__module__) reloader.watch_files([schema_module.__file__]) app = Starlette(debug=True) app.add_middleware(CORSMiddleware, allow_headers=["*"], allow_origins=["*"], allow_methods=["*"]) graphql_app = GraphQL(schema_symbol, debug=True) paths = ["/", "/graphql"] for path in paths: app.add_route(path, graphql_app) app.add_websocket_route(path, graphql_app) print(f"Running strawberry on http://{host}:{port}/ 🍓") uvicorn.run(app, host=host, port=port, log_level="error")
class Server: """ `Server` is a thin wrapper around a Starlette application. Rather than have the Server inherit the Starlette application class we choose to forward specific methods. This gives us greater control over the sufrace area of the application when used with the jab harness as well as leaves open the option to break away from using the Starlette application itself and instead begin to use the starlette toolkit. """ def __init__(self, host: Optional[str] = None, port: Optional[int] = None, debug: bool = False) -> None: self._app = Starlette(debug) self._host = host self._port = port def add_route(self, fn: Handler, rule: str, **options: Any) -> None: self._app.add_route(rule, fn, **options) def add_websocket_route(self, fn: WebSocketHandler, rule: str, **options: Any) -> None: self._app.add_websocket_route(rule, fn, **options) async def asgi(self, scope: dict, receive: Receive, send: Send) -> None: """ Exposes the ASGI interface of the Starlette application to be used with your favorite ASGI server. """ await self._app(scope, receive, send) # pragma: no cover async def run(self) -> None: """ Runs the app inside of uvicorn inside of the jab harness. NOTE ---- Despite the async definition this function immediately blocks. It's an ugly vestige of when jab did not support an ASGI interface itself and the jab ASGI interface should always be used instead of it. """ uvicorn.run(self._app, host=self._host or "0.0.0.0", port=self._port or 8000, lifespan="on") @property def starlette(self) -> Starlette: """ Provides access to the underlying Starlette application. Useful in conjunction with `starlette.TestClient`. """ return self._app @property def jab(self) -> Callable: """ Provides a jab constructor to incorporate an already instantiated Server object. """ def constructor() -> Server: return self return constructor
def main() -> None: ip = get_local_ip() app = Starlette() graphql_app = GraphQL(schema) app.add_route("/graphql", graphql_app) app.add_websocket_route("/graphql", graphql_app) typer.echo(f"App running on http://{ip}:8000/graphql") uvicorn.run(app, host="0.0.0.0", port=8000, log_level="error")
def test_app_add_websocket_route(): app = Starlette() async def websocket_endpoint(session): await session.accept() await session.send_text("Hello, world!") await session.close() app.add_websocket_route("/ws", websocket_endpoint) client = TestClient(app) with client.websocket_connect("/ws") as session: text = session.receive_text() assert text == "Hello, world!"
def make_app(BASE): class CatchAll(BaseHTTPMiddleware): async def dispatch(self, request: Request, handler): request.scope["path"] = BASE # TODO subscriptions path return await handler(request) app = Starlette(debug=True) app.add_middleware(CORSMiddleware, allow_headers=["*"], allow_origins=["*"], allow_methods=["*"]) graphql_app = GraphQL(schema, debug=True) app.add_route(BASE, graphql_app) app.add_websocket_route(BASE, graphql_app) app = CatchAll(app) return app
class NeolithServer: def __init__(self): self.loop = None self.server = None self.irc = None self.sessions = {} self.channels = Channels() self.secret_key = os.urandom(32) self.name = settings.SERVER_NAME if settings.PUBLIC_CHANNEL: self.channels.add(Channel(name=settings.PUBLIC_CHANNEL, topic='', protected=True, encrypted=False)) self.web = Starlette(debug=True) self.web.add_event_handler('startup', self.startup) self.web.add_event_handler('shutdown', self.shutdown) self.web.add_route('/api', self.web_handler, methods=['GET', 'POST']) self.web.add_websocket_route('/ws', self.websocket_handler) # Server static files static_dir = os.path.join(os.path.dirname(__file__), 'static') self.web.mount('/static', StaticFiles(directory=static_dir)) if settings.ENABLE_WEB_CLIENT: self.web.add_route('/', client, methods=['GET']) if settings.ENABLE_DOCS: self.web.add_route('/docs', docs, methods=['GET']) if settings.ENABLE_SIGNUP: self.web.add_route('/signup', signup, methods=['GET', 'POST']) async def startup(self): dorm.setup(settings.DATABASE, models=[Account]) print('Starting binary protocol server on {}:{}'.format(settings.SOCKET_BIND, settings.SOCKET_PORT)) # Careful not to use the event loop until after uvicorn starts it, since it may swap in uvloop. self.loop = asyncio.get_event_loop() self.server = await self.loop.create_server(lambda: SocketSession(self), settings.SOCKET_BIND, settings.SOCKET_PORT) if settings.ENABLE_IRC: print('Starting IRC server on {}:{}'.format(settings.IRC_BIND, settings.IRC_PORT)) self.irc = await self.loop.create_server(lambda: IRCSession(self), settings.IRC_BIND, settings.IRC_PORT) async def shutdown(self): print('Stopping binary protocol server') self.server.close() if self.irc: self.irc.close() async def web_handler(self, request): session_token = request.headers.get('x-neolith-session') session = self.get(token=session_token, default=WebSession()) if request.method == 'GET': return JSONResponse([tx.to_dict() for tx in await session.events()]) elif request.method == 'POST': session.hostname = request.client.host if not session.ident: await self.connected(session) tx = Transaction(await request.json()) response = await self.handle(session, tx, send=False) return JSONResponse(response.to_dict()) else: return JSONResponse({'error': 'Invalid HTTP method.'}, status_code=405) async def websocket_handler(self, websocket, **kwargs): await websocket.accept() session = WebSocketSession(websocket) session.hostname = websocket.client.host await self.connected(session) try: while True: tx = Transaction(await websocket.receive_json()) await self.handle(session, tx) except WebSocketDisconnect: print('websocket disconnected') finally: await self.disconnected(session) async def handle(self, session, transaction, send=True): print(session, '-->', transaction.to_dict()) response = transaction.response() for packet in transaction.packets: assert isinstance(packet, ClientPacket) try: if packet.requires_auth and not session.authenticated: raise ProtocolError('This request requires authentication.') response.add(await packet.handle(self, session)) except ProtocolError as e: response.error = str(e) if send and not response.empty: await session.send(response) return response async def connected(self, session): print('New connection - {}'.format(session)) session.ident = binascii.hexlify(os.urandom(16)).decode('ascii') session.token = binascii.hexlify(os.urandom(16)).decode('ascii') self.sessions[session.ident] = session async def disconnected(self, session): if session.authenticated: session.authenticated = False for channel in self.channels: if session in channel.sessions: channel.remove(session) await channel.send(ChannelLeave(channel=channel.name, user=session)) await self.broadcast(UserLeft(user=session)) if session.ident in self.sessions: del self.sessions[session.ident] def start(self): uvicorn.run(self.web, host=settings.WEB_BIND, port=settings.WEB_PORT) async def broadcast(self, message): for session in self.sessions.values(): if session.authenticated: await session.send(message) async def authenticate(self, session): if session.authenticated: raise ProtocolError('Session is already authenticated.') if self.get(nickname=session.nickname, authenticated=True): raise ProtocolError('This nickname is already in use.') # XXX: where should this go? maybe a new task to be executed next time through the loop? await self.broadcast(UserJoined(user=session)) if settings.PUBLIC_CHANNEL and settings.AUTO_JOIN: channel = self.channels[settings.PUBLIC_CHANNEL] channel.add(session) await channel.send(ChannelJoin(channel=settings.PUBLIC_CHANNEL, user=session)) # Authenticate the session after sending the joins, so we don't send joins before the login response. print('Authenticated {}'.format(session)) session.authenticated = True return session.ident def find(self, **kwargs): for session in self.sessions.values(): match = True for field, value in kwargs.items(): if getattr(session, field) != value: match = False if match: yield session def get(self, **kwargs): default = kwargs.pop('default', None) for session in self.find(**kwargs): return session return default
import os from starlette.applications import Starlette from starlette.middleware.cors import CORSMiddleware from strawberry import Schema from strawberry.asgi import GraphQL from strawberry.cli.constants import DEBUG_SERVER_SCHEMA_ENV_VAR_KEY from strawberry.utils.importer import import_module_symbol app = Starlette(debug=True) app.add_middleware( CORSMiddleware, allow_headers=["*"], allow_origins=["*"], allow_methods=["*"] ) schema_import_string = os.environ[DEBUG_SERVER_SCHEMA_ENV_VAR_KEY] schema_symbol = import_module_symbol(schema_import_string, default_symbol_name="schema") assert isinstance(schema_symbol, Schema) graphql_app = GraphQL(schema_symbol, debug=True) paths = ["/", "/graphql"] for path in paths: app.add_route(path, graphql_app) app.add_websocket_route(path, graphql_app)
@SUBSCRIPTION.field("count") def count(number, _info, **_kwargs): """returns current count number, starting at 1""" return number + 1 @APP.on_event("startup") async def startup(): """initialization steps""" await init_db() @APP.on_event("shutdown") async def shutdown(): """clean up on shutdown""" await close_connections() SCHEMA = make_executable_schema(SCHEMA, [MUTATION, QUERY, SUBSCRIPTION, POST]) GRAPHQL_SERVER = GraphQL( SCHEMA, debug=True, extensions=[ApolloTracingExtension], ) APP.add_route("/graphql/", GRAPHQL_SERVER) APP.add_websocket_route("/graphql/", GRAPHQL_SERVER) APP.debug = True
from src.resolvers.HeroSkill import hero_skill from src.resolvers.MoveType import move_type from src.resolvers.Rarity import rarity from src.resolvers.WeaponType import weapon_type from src.resolvers.Query import query # SCHEMA DEFINITION type_defs = load_schema_from_path("src/schema.graphql") class LoaderGraphQL(GraphQL): async def context_for_request(self, request: Any, data: Any) -> Any: return { "loaders": { "base_stats_loader": BaseStatsLoader(), "heroes_loader": HeroesLoader(), "skills_loader": SkillsLoader(), }, "request": request, } schema = make_executable_schema( type_defs, [query, hero, hero_skill, weapon_type, move_type, date_scalar, rarity]) graphql_server = LoaderGraphQL(schema) app = Starlette() app.add_route("/", graphql_server) app.add_websocket_route("/", graphql_server)