Giter Club home page Giter Club logo

twirpy's Introduction

Twirpy

Python implementation of Twirp RPC framework (supports Twirp Wire Protocol v7).

This repo contains a protoc plugin that generates sever and client code and a pypi package with common implementation details.

For details about the twirp project, check https://github.com/twitchtv/twirp

Installation

Grab the protoc plugin to generate files with

go get -u github.com/verloop/twirpy/protoc-gen-twirpy

Add the twirp package to your project

pip install twirp

You'll also need uvicorn to run the server.

Generate and run

Use the protoc plugin to generate twirp server and client code.

We'll assume familiarity with the example from the docs. https://twitchtv.github.io/twirp/docs/example.html

protoc --python_out=./ --twirpy_out=./ ./haberdasher.proto

Server code

# server.py
import random

from twirp.asgi import TwirpASGIApp
from twirp.exceptions import InvalidArgument

from . import haberdasher_twirp, haberdasher_pb2

class HaberdasherService(object):
    def MakeHat(self, context, size):
        if size.inches <= 0:
            raise InvalidArgument(argument="inches", error="I can't make a hat that small!")
        return haberdasher_pb2.Hat(
            size=size.inches,
            color= random.choice(["white", "black", "brown", "red", "blue"]),
            name=random.choice(["bowler", "baseball cap", "top hat", "derby"])
        )


# if you are using a custom prefix, then pass it as `server_path_prefix`
# param to `HaberdasherServer` class.
service = haberdasher_twirp.HaberdasherServer(service=HaberdasherService())
app = TwirpASGIApp()
app.add_service(service)

Run the server with

uvicorn twirp_server:app --port=3000

Client code

# client.py
from twirp.context import Context
from twirp.exceptions import TwirpServerException

from . import haberdasher_twirp, haberdasher_pb2

client = haberdasher_twirp.HaberdasherClient("http://localhost:3000")

# if you are using a custom prefix, then pass it as `server_path_prefix`
# param to `MakeHat` class.
try:
    response = client.MakeHat(ctx=Context(), request=haberdasher_pb2.Size(inches=12))
    print(response)
except TwirpServerException as e:
    print(e.code, e.message, e.meta, e.to_dict())

Twirp Wire Protocol (v7)

Twirpy generates the code based on the protocol v7. This is a breaking change from the previous v5 and you can see the changes here.

This new version comes with flexibility to use any prefix for the server URLs and defaults to /twirp. To use an empty prefix or any custom prefix like /my/custom/prefix, pass it as a server_path_prefix param to server and clients. Check the example directory, which uses /twirpy as a custom prefix.

If you want to use the server and clients of v5, then use the 0.0.1 release.

Message Body Length

Currently, message body length limit is set to 100kb, you can override this by passing max_receive_message_length to TwirpASGIApp constructor.

# this sets max message length to be 10 bytes
app = TwirpASGIApp(max_receive_message_length=10)

Support and community

Python: #twirp. Join PySlackers here

Go: #twirp. Join Gophers community slack here

Standing on the shoulders of giants

twirpy's People

Contributors

avinassh avatar batchar2 avatar chadawagner avatar dependabot[bot] avatar gauthamsuresh09 avatar ghnuberath avatar ofpiyush avatar sarahegler avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

twirpy's Issues

Consider dropping Twirpy middlewares

One can use middlewares from https://www.starlette.io/middleware/

Our middlewares act more like a decorator on the actual method than a real middleware. I believe we had added them internally when we didn't have hooks, but I can't remember for sure.

To avoid confusion with Starlette's middlewares, we can drop them from a future version.

As for immediate next step, maybe we can deprecate them in the next version and wait for users to tell us if they're using it?

If no one shows up for the next 2 versions, we can drop support?

Twirp on Flask

Hello,

Would it be possible to run this twirp implementation on a flask server? Any advice on how to do so if possible?

Support for Middlewares

Hi, does Twirpy support Middlewares like Starlette? I'm trying to implement an auth layer and would like to do it in a Middleware.

I did not see in the documentation or code where to specify them.

Thanks

Wrapping ConnectionErrors in python3 results in an AttributeError

In TwirpClient's _make_request, ConnectionErrors are wrapped as TwirpServerExceptions:

raise exceptions.TwirpServerException(
    code=errors.Errors.Unavailable,
    message=e.message,
    meta={"original_exception": e},
)

Which, in python3, causes an AttributError because ConnectionError does not have message anymore.

I believe a simple fix would be to change this (and the Timeout error as well) to:

raise exceptions.TwirpServerException(
    code=errors.Errors.Unavailable,
    message=str(e),
    meta={"original_exception": e},
)

Async Client support

Hi! I've been using this package for a bit, and for performance reasons I've had to create a modified TwirpClient that makes http requests using aiohttp instead of requests, so that ASGI apps can use the clients to make calls in a non-blocking way. Would you be open to adding such a class if a PR was raised?

Missing Content-Type returns "got non-twirp exception while processing request"

If Content-Type is missing from the request, Twirpy returns a 500 response code instead of gracefully handling the error.

Make any request without a Content-Type. This error will be raised.
Error: got non-twirp exception while processing request
Trace:

Traceback (most recent call last):
  File "/usr/local/lib/python3.10/site-packages/twirp/asgi.py", line 62, in __call__
    encoder, decoder = self._get_encoder_decoder(endpoint, headers)
  File "/usr/local/lib/python3.10/site-packages/twirp/base.py", line 104, in _get_encoder_decoder
    message="unexpected Content-Type: " + ctype
TypeError: can only concatenate str (not "NoneType") to str

See the code below. ctype = headers.get('content-type', None) sets ctype to None then attempts to concatenate the None type to a string in message="unexpected Content-Type: " + ctype while building the BadRoute error.

twirpy/twirp/base.py

Lines 93 to 106 in 6940030

def _get_encoder_decoder(self, endpoint, headers):
ctype = headers.get('content-type', None)
if "application/json" == ctype:
decoder = functools.partial(self.json_decoder, data_obj=endpoint.input)
encoder = functools.partial(self.json_encoder, data_obj=endpoint.output)
elif "application/protobuf" == ctype:
decoder = functools.partial(self.proto_decoder, data_obj=endpoint.input)
encoder = functools.partial(self.proto_encoder, data_obj=endpoint.output)
else:
raise exceptions.TwirpServerException(
code=errors.Errors.BadRoute,
message="unexpected Content-Type: " + ctype
)
return encoder, decoder

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.