{ "info": { "author": "Alex Stapleton", "author_email": "alexs@prol.etari.at", "bugtrack_url": null, "classifiers": [ "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy" ], "description": "\n[![CircleCI](https://circleci.com/gh/public/grpcWSGI.svg?style=svg)](https://circleci.com/gh/public/grpcWSGI)\n\n# gRPC-WSGI\n\nA gRPC-Web implementation based on Python's WSGI standard.\n\n## Why?\n\ngRPC has a lot going for it but is awkward to use in some environments. gRPC-WSGI makes it easy to integrate gRPC when you need to use HTTP/1.1 load balancers or proxies, or want to integrate gRPC into existing services such as Django or Flask apps that speak a different protocol most of the time.\n\nThere are two main capabilities this implementation has over Google's.\n\n 1. HTTP/1.1 compatability via gRPC-Web, even for unary_stream RPCs using protobuf. Without the need for a sidecar proxy process like Envoy.\n 2. Run gRPC and other HTTP stuff on the same socket.\n\n## How?\n\ngRPC-WSGI is designed to require minimal changes to an existing WSGI or gRPC code base.\n\n### Server\n\nNormally a WSGI application (such as your favourite Django app) will call something such as \n\n```python\nfrom django.core.wsgi import get_wsgi_application\napplication = get_wsgi_application()\n```\n\nin it somewhere so that your application server (uWSGI, Gunicorn etc) knows where your code is.\n\nTo add gRPC-WSGI to an application like the above all you need to do to enable it is this.\n\n```python\nfrom django.core.wsgi import get_wsgi_application\nfrom grpcWSGI.server import grpcWSGI\n\napplication = get_wsgi_application()\napplication = grpcWSGI(application)\n```\n\nThe grpcWSGI application object also happens to be compatible with the normal grpc.Server interface.\nSo all you need to do actually attach your RPCs and start making calls to your new service is the usual gRPC setup of e.g.\n\n```python\nhelloworld_pb2_grpc.add_GreeterServicer_to_server(Greeter(), application)\n```\n\nAnd now you have a combined HTTP/1.1 Django + gRPC application all under a single port.\n\n### Client\n\nSetting up a client is similarly very simple and similar to standard gRPC calls.\n\nInstead of using gRPCs native `insecure_channel` API we have `grpcWSGI.client.insecure_web_channel` instead which provides a https://github.com/kennethreitz/requests powered client channel to a gRPC-Web server. e.g.\n\n```python\n import gRPCWSGI.client\n\n with grpcWSGI.client.insecure_web_channel(\n f\"http://localhost:8080\"\n ) as channel:\n stub = helloworld_pb2_grpc.GreeterStub(channel)\n print(stub.SayHello(\"world\"))\n```\n\n# TODO\n\n * Error handling\n * Compression?\n * Benchmarks?\n * Clean up the CORS stuff.\n * StreamStream/StreamUnary RPCs?\n * Retries, caching and other client options.\n * Quality of life integrations for Django, Flask etc.\n * application/grpc-web-text support? Do I care about IE10? JSON is potentially faster than Protobuf sometimes...\n * aiohttp / grpc-aiohttp / ASGI integration?\n * MyPy annotations? https://github.com/dropbox/mypy-protobuf Already makes this pretty OK.\n * Use more of the ABCs and other standard stuff from the grpc package\n * Make support for chunked encoding vaguely reliable\n * Some kind of metaclass magic to make it easier to ensure you've actually implemented a servers interface\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/public/grpcWSGI", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "grpcWSGI", "package_url": "https://pypi.org/project/grpcWSGI/", "platform": "", "project_url": "https://pypi.org/project/grpcWSGI/", "project_urls": { "Homepage": "https://github.com/public/grpcWSGI" }, "release_url": "https://pypi.org/project/grpcWSGI/0.0.4/", "requires_dist": [ "grpcio", "requests" ], "requires_python": ">=3.6.0", "summary": "gRPC-Web + WSGI", "version": "0.0.4" }, "last_serial": 5349727, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "6e2aa6d64aabd46568ac4a51a3e59f73", "sha256": "1e0b01f1cebcfbe72a204ae7be3a7ed8df2db8461bf7e355c1f5165ecfc921cd" }, "downloads": -1, "filename": "grpcWSGI-0.0.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "6e2aa6d64aabd46568ac4a51a3e59f73", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 9995, "upload_time": "2019-04-22T19:17:41", "url": "https://files.pythonhosted.org/packages/41/5d/1664cf9b7040fecdbac67dbeed2bc4a348ca7daee14227243ad381603a0a/grpcWSGI-0.0.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f8377b968f5dc0c5fc1d5dc89854d87c", "sha256": "12c83ec07e9f7670d1fc9deaf0f731a5440e32bfd5383579539fdd31f70bb28a" }, "downloads": -1, "filename": "grpcWSGI-0.0.1.tar.gz", "has_sig": false, "md5_digest": "f8377b968f5dc0c5fc1d5dc89854d87c", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 6356, "upload_time": "2019-04-22T19:17:43", "url": "https://files.pythonhosted.org/packages/bb/ec/1fad45e758b30ce80901e29ed1a05cff73301140a61db52e9000eb943cc4/grpcWSGI-0.0.1.tar.gz" } ], "0.0.2": [ { "comment_text": "", "digests": { "md5": "480262382a362ae67fc1ed35293deb40", "sha256": "829c053fc8ef033414494b0b01f5accb7c88dac8e99d0482752b86c9797d9ed5" }, "downloads": -1, "filename": "grpcWSGI-0.0.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "480262382a362ae67fc1ed35293deb40", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 10346, "upload_time": "2019-04-25T16:47:23", "url": "https://files.pythonhosted.org/packages/7e/0d/46144e0d2dcf25ca2a0a6c0d01b0d82a8d2a0992c5994a3f7c4e81b78b1d/grpcWSGI-0.0.2-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "52af63ed04a6a1493d6dcec16d637ae0", "sha256": "20b539112f813b65f281c190c1a15c08d844f035a9e6c93d5848d5f33e7c1549" }, "downloads": -1, "filename": "grpcWSGI-0.0.2.tar.gz", "has_sig": false, "md5_digest": "52af63ed04a6a1493d6dcec16d637ae0", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 6712, "upload_time": "2019-04-25T16:47:26", "url": "https://files.pythonhosted.org/packages/de/4e/8e933f19a9a0de09acad33e97cb15bf2bcc163c1486b23c38624f966f8ff/grpcWSGI-0.0.2.tar.gz" } ], "0.0.3": [ { "comment_text": "", "digests": { "md5": "fbbed1fa3fdff57f6a80625e10390c09", "sha256": "fc47167b732e693e39668f3475b15189aba28e937733f8c6becc75d3fd7a60ec" }, "downloads": -1, "filename": "grpcWSGI-0.0.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "fbbed1fa3fdff57f6a80625e10390c09", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 11076, "upload_time": "2019-05-07T09:10:04", "url": "https://files.pythonhosted.org/packages/d7/1d/46555c5613a54a32bc12cc5ab8ab1fec2a15fb6e977a7606bff2ca8a57cd/grpcWSGI-0.0.3-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "38fb10f15d4ea280f01f8a51131c24d3", "sha256": "686deaf6155f6014bcb305627d3a15e5e30af27ba9e0983e51d7bd7e112a4a3e" }, "downloads": -1, "filename": "grpcWSGI-0.0.3.tar.gz", "has_sig": false, "md5_digest": "38fb10f15d4ea280f01f8a51131c24d3", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 7420, "upload_time": "2019-05-07T09:10:05", "url": "https://files.pythonhosted.org/packages/b7/32/c41401b584ece1a4b5526d8404e7c0f97b2cf245d7f40c4f8e9e586f4785/grpcWSGI-0.0.3.tar.gz" } ], "0.0.4": [ { "comment_text": "", "digests": { "md5": "424b2b3bf196256ea0fecda5336dfb50", "sha256": "0f59db87573f3954496450fd85464f9f3f54caf7b6b9a2824ad521ea957c9d32" }, "downloads": -1, "filename": "grpcWSGI-0.0.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "424b2b3bf196256ea0fecda5336dfb50", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 11931, "upload_time": "2019-06-02T19:44:57", "url": "https://files.pythonhosted.org/packages/70/96/03810df4f733113e7e790b2a6f07074db2e247dde52d8c9de56d723b9eb6/grpcWSGI-0.0.4-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "326df83201b401fc1571e5ad5428c805", "sha256": "5dd70c83b6b3ba44f711733c099d7a323fe5815d5d032747a594348d16ab894a" }, "downloads": -1, "filename": "grpcWSGI-0.0.4.tar.gz", "has_sig": false, "md5_digest": "326df83201b401fc1571e5ad5428c805", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 7917, "upload_time": "2019-06-02T19:44:59", "url": "https://files.pythonhosted.org/packages/a3/97/3cfe9023257aee9b09d5cdb3bafe9cdba28ff141dd13d1fee94c318a0191/grpcWSGI-0.0.4.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "424b2b3bf196256ea0fecda5336dfb50", "sha256": "0f59db87573f3954496450fd85464f9f3f54caf7b6b9a2824ad521ea957c9d32" }, "downloads": -1, "filename": "grpcWSGI-0.0.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "424b2b3bf196256ea0fecda5336dfb50", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6.0", "size": 11931, "upload_time": "2019-06-02T19:44:57", "url": "https://files.pythonhosted.org/packages/70/96/03810df4f733113e7e790b2a6f07074db2e247dde52d8c9de56d723b9eb6/grpcWSGI-0.0.4-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "326df83201b401fc1571e5ad5428c805", "sha256": "5dd70c83b6b3ba44f711733c099d7a323fe5815d5d032747a594348d16ab894a" }, "downloads": -1, "filename": "grpcWSGI-0.0.4.tar.gz", "has_sig": false, "md5_digest": "326df83201b401fc1571e5ad5428c805", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 7917, "upload_time": "2019-06-02T19:44:59", "url": "https://files.pythonhosted.org/packages/a3/97/3cfe9023257aee9b09d5cdb3bafe9cdba28ff141dd13d1fee94c318a0191/grpcWSGI-0.0.4.tar.gz" } ] }