https://github.com/public/sonora Skip to content Sign up * Why GitHub? + Features + Mobile + Actions + Codespaces + Packages + Security + Code review + Issues + Integrations + GitHub Sponsors + Customer stories * Team * Enterprise * Explore + Explore GitHub + Learn and contribute + Topics + Collections + Trending + Learning Lab + Open source guides + Connect with others + The ReadME Project + Events + Community forum + GitHub Education + GitHub Stars program * Marketplace * Pricing + Plans + Compare plans + Contact Sales + Education [ ] * # In this repository All GitHub | Jump to | * No suggested jump to results * # In this repository All GitHub | Jump to | * # In this user All GitHub | Jump to | * # In this repository All GitHub | Jump to | Sign in Sign up {{ message }} public / sonora Public * Notifications * Fork 3 * Star 90 * A gRPC-Web implementation for Python Apache-2.0 License 90 stars 3 forks Star Notifications * Code * Issues 9 * Pull requests 0 * Actions * Projects 0 * Wiki * Security * Insights More * Code * Issues * Pull requests * Actions * Projects * Wiki * Security * Insights master Switch branches/tags [ ] Branches Tags Could not load branches Nothing to show {{ refName }} default View all branches Could not load tags Nothing to show {{ refName }} default View all tags 25 branches 7 tags Code Latest commit @public public Merge pull request #51 from public/fix-trailers ... e7137a8 Dec 30, 2021 Merge pull request #51 from public/fix-trailers Always send grpc-status in trailers e7137a8 Git stats * 207 commits Files Permalink Failed to load latest commit information. Type Name Latest commit message Commit time .circleci s/docker-compose/docker compose/ Dec 30, 2021 sonora Always send grpc-status in trailers Dec 30, 2021 test_server Official interop test servers Apr 26, 2021 tests fix all the existing tests Apr 26, 2021 .gitignore .gitignore Apr 22, 2019 .python-version Update tested Python versions Dec 27, 2021 Dockerfile Use poetry instead of setuptools May 2, 2021 LICENSE Create LICENSE Apr 22, 2019 README.md readme: asgi and quart example Jun 30, 2021 docker-compose.yaml Use grpcweb interop tests in CircleCI Apr 26, 2021 poetry.lock Add black to dev deps Dec 27, 2021 pyproject.toml Merge pull request #50 from public/mypy-pyproject Dec 27, 2021 tox.ini Add tox helpers for running interop tests Dec 30, 2021 View code [ ] Sonora Why? How? Server WSGI ASGI Clients Requests (Sync) Aiohttp (Async) README.md CircleCI Sonora Sonora is a Python-first implementation of gRPC-Web built on top of standard Python APIs like WSGI and ASGI for easy integration. Why? Regular gRPC has a lot going for it but is awkward to use in some environments. gRPC-Web makes it easy to get gRPC working in environments that need HTTP/1.1 but the Google gRPC and gRPC-Web implementations don't like to coexist with your normal Python frameworks like Django or Flask. Sonora doesn't care what ioloop you use, this means you can run it along side any other Python web framework in the same application! This makes it easy to * Add gRPC to an existing code base. * Run gRPC behind AWS and other HTTP/1.1 load balancers. * Integrate with other ASGI frameworks like Channels, Starlette, Quart etc. * Integrate with other WSGI frameworks like Flask, Django etc. Sonora aims to be compatible with and tested against Google's grpc-web implementation in both text mode and binary mode. The name Sonora was inspired by the Sonoran gopher snake. Snek How? Sonora is designed to require minimal changes to an existing Python application. Server WSGI Normally a WSGI application (such as your favourite Django app) will have a file somewhere named wsgi.py that gets your application setup and ready for your web server of choice. It will look something like this. from django.core.wsgi import get_wsgi_application application = get_wsgi_application() To add Sonora's gRPC-Web capabilities to an application like the above all you need to do to enable it is this. from django.core.wsgi import get_wsgi_application from sonora.wsgi import grpcWSGI import helloworld_pb2_grpc # Setup your frameworks default WSGI app. application = get_wsgi_application() # Install the Sonora grpcWSGI middleware so we can handle requests to gRPC's paths. application = grpcWSGI(application) # Attach your gRPC server implementation. helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), application) And now you have a combined HTTP/1.1 Django + gRPC application all under a single port. ASGI For ASGI things are mostly the same, the example shown here integrates with Quart but it's more or less the same for other frameworks. from sonora.asgi import grpcASGI from quart import Quart import helloworld_pb2_grpc # Setup your frameworks default ASGI app. application = Quart(__name__) # Install the Sonora grpcASGI middleware so we can handle requests to gRPC's paths. application.asgi_app = grpcASGI(application.asgi_app) # Attach your gRPC server implementation. helloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), application.asgi_app) And now you have a combined HTTP/1.1 Quart + gRPC application all under a single port. Clients Sonora provides both regular sync and aiohttp based async clients. Requests (Sync) Instead of using gRPCs native grpc.insecure_channel API we have sonora.client.insecure_web_channel instead which provides a requests powered client channel to a gRPC-Web server. e.g. import sonora.client with sonora.client.insecure_web_channel( f"http://localhost:8080" ) as channel: stub = helloworld_pb2_grpc.GreeterStub(channel) print(stub.SayHello("world")) Aiohttp (Async) Instead of grpc.aio.insecure_channel we have sonora.aio.insecure_web_channel which provides an aiohttp based asyncio compatible client for gRPC-Web. e.g. import sonora.aio async with sonora.aio.insecure_web_channel( f"http://localhost:8080" ) as channel: stub = helloworld_pb2_grpc.GreeterStub(channel) print(await stub.SayHello("world")) stub = helloworld_pb2_grpc.GreeterStub(channel) async for response in stub.SayHelloSlowly("world"): print(response) This also supports the new streaming response API introduced by gRFC L58 import sonora.aio async with sonora.aio.insecure_web_channel( f"http://localhost:8080" ) as channel: stub = helloworld_pb2_grpc.GreeterStub(channel) async with stub.SayHelloSlowly("world") as response: print(await response.read()) About A gRPC-Web implementation for Python Resources Readme License Apache-2.0 License Stars 90 stars Watchers 6 watching Forks 3 forks Releases 7 tags Packages 0 No packages published Contributors 4 * @public public Alex Stapleton * @mm0d mm0d Dmitriy Markin * @lidizheng lidizheng Lidi Zheng * @gitpushdashf gitpushdashf T Languages * Python 99.2% * Dockerfile 0.8% * (c) 2022 GitHub, Inc. * Terms * Privacy * Security * Status * Docs * Contact GitHub * Pricing * API * Training * Blog * About You can't perform that action at this time. You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.