Git Product home page Git Product logo

flask-pbj's Introduction

Flask Peanut Butter & Jelly

Flask-Pbj provides support for Google Protocol Buffers and json formatted request and response data. The api decorator serializes and deserializes json or protobuf formatted messages to and from a python dictionary.

Why Flask-Pbj

Flask Peanut Butter and Jelly to simplifies the creation of REST APIs for C++ clients. Flask-pbj decorated app.routes accept and return protobuf messages or JSON. The JSON is useful for debugging and public API's while Google Protobuf is a well-documented compact and efficient format, particularly useful for C++/Python communication.

Examples

example_messages.proto

message Person {
    required int32 id = 1;
    required string name = 2;
    optional string email = 3;
}

message Team {
    required int32 id = 1;
    required string name = 2;
    required Person leader = 3
    repeated Person members = 4;
}

app.py

# The route function can access the added request.received_message data member
# for input and return a dictionary for output. The client's accept and
# content-type headers determine the format of the messages. Similar to flask,
# routes can avoid pbjs response serialization by directly returning a
# flask.Response object.
@app.route('/teams', methods=['POST'])
@api(json, protobuf(receives=Person, sends=Team, errors=Error))
def create_team():
    leader = request.received_message

    if len(leader['name']) < 3:
        # Optionally, return a tuple of the form dict, status_code, headers
        # A 4xx HTTP error will use the 'errors' protobuf message type
        return {"errorMessage": "Name too short"}, 400

    # For a 200 response, just return a dict
    return {
        'id': get_url(2),
        'name': "{0}'s Team".format(leader['name']),
        'leader': get_url(person[id]),
        'members': [],
    }

Create a team with JSON:

curl -X POST -H "Accept: application/json" \
    -H "Content-type: application/json" \
    http://127.0.0.1:5000/teams --data {'id': 1, 'name': 'Red Leader'}
{
    "id": 2,
    "name": "Red Leader's Team",
    "leader": "/people/1"
    "members": []
}

Create a new team with google protobuf:

# Create and save a Person structure in python
from example_messages_pb2 import Person
leader = Person()
leader.id = 1
leader.name = 'Red Leader'
with open('person.pb', 'wb') as f:
    f.write(leader.SerializeToString())
curl -X POST -H "Accept: application/x-protobuf" \
    -H "Content-type: application/x-protobuf" \
    http://127.0.0.1:5000/teams --data-binary @person.pb > team.pb

Adding new mimetypes

Codecs are classes see JsonCodec and ProtobufCodec for examples

The Protobuf Message escape hatch

If you want your decorated function to get the raw Protobuf Message class instance instead of the converted dict, set the keyword arg to_dict to False in the protobuf constructor.

This is sometimes handy since this library doesn't support all the functionality in the Protobuf spec. For example, oneof fields; the generated Protobuf Classes ensure that only one of the oneof fields are set but the data dictionaries this library normally exposes do not.

Warning: If to_dict is set to False and a JSON message is received it will not be converted to an instance of the corresponding Protobuf Message class (it'll still be passed to your function as a dictionary). Also please note that receiving and sending JSONs aren't checked/type-safe operations. JSON inputs can have extra fields/be missing fields and dictionary to JSON outputs aren't checked to ensure they've got all the right fields (Protobuf Message -> JSON is verified since in order to be a Protobuf Message instance, the message must be valid).

You can also return a raw Protobuf Message instead of a data dictionary; if you do so, it will be converted to JSON if required or simply passed through. The output type is entirely independent from the to_dict attribute on the protobuf constructor; you can receive incoming messages as Protobuf Messages and return outgoing messages as data dicts or vice versa (or Protobuf in and out, or, as you'd expect, data dictionary in and out). Just about the only thing you can't do is receive JSON inputs as Protobuf Message class instances.

flask-pbj's People

Contributors

rrbutani avatar

Stargazers

 avatar

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.