Skip to content

Instantly share code, notes, and snippets.

@ericmoritz
Last active December 23, 2015 18:19
Show Gist options
  • Save ericmoritz/6675109 to your computer and use it in GitHub Desktop.
Save ericmoritz/6675109 to your computer and use it in GitHub Desktop.
A simple protobuf based web service
*.pyc
*~
.env/
static/
data/
*_pb2.py

An example of a protobuf based web service.

function Right(v) {
return {
'bind': function(f) { return f(v); },
'is_right': true,
'is_left': false,
'either': function(_, rf) { return rf(v) },
}
}
function Left(v) {
return {
'bind': function(f) { return Left(v); },
'is_right': false,
'is_left': true,
'either': function(lf, _) { return lf(v) },
}
}
function catchEither(f) {
try {
return Right(f());
} catch(err) {
return Left(err);
}
}
from things_pb2 import Person, Animal
people = {
"em": {"name": "Eric", "age": 33},
"jh": {"name": "Jonathan"},
"sl": {"name": "Steven"},
"fc": {"name": "Frankln Clinton"},
}
animals = {
"dog": {"type": "dog"},
"chop": {"type": "dog", "name": "Chop", "owner_key": 'fc'},
}
def _person_msg(p, key, data):
p.key = key
for key, value in data.items():
setattr(p, key, value)
return p
def _animal_msg(a, key, data):
a = Animal()
a.key = key
for key, value in data.items():
setattr(a, key, value)
# denormalize the owner
if key == 'owner_key':
_person_msg(a.owner, value, people[value])
return a
def write_msg(bucket, key, msg):
with open('data/{bucket}/{key}'.format(**locals()), 'wb') as fh:
fh.write(msg.SerializeToString())
for key, value in people.items():
write_msg(
"people",
key,
_person_msg(Person(), key, value))
for key, value in animals.items():
write_msg(
"animals",
key,
_animal_msg(Animal(), key, value))
<!doctype html>
<html>
<head>
<script src="/static/Long.min.js"></script>
<script src="/static/ByteBuffer.min.js"></script>
<script src="/static/ProtoBuf.min.js"></script>
<script src="/static/jquery.min.js"></script>
<script src="either.js"></script>
<script src="main.js"></script>
</head>
</html>
var ProtoBuf = dcodeIO.ProtoBuf;
var builder = ProtoBuf.protoFromFile("things.proto")
var Person = builder.build("things.Person");
var Animal = builder.build("things.Animal");
function display(obj) {
document.write(JSON.stringify(obj) + "<br/>");
}
function logError(err) {
console.error(err.toString());
}
function handlePerson(bin) {
catchEither(
function() { return Person.decode(bin) }
)
.either(logError, display);
}
function handleAnimal(bin) {
catchEither(
function() { return Animal.decode(bin) }
)
.either(logError, display);
}
function main() {
jQuery.get("data/people/em", handlePerson);
jQuery.get("data/people/fc", handlePerson);
jQuery.get("data/people/jh", handlePerson);
jQuery.get("data/people/sl", handlePerson);
jQuery.get("data/animals/chop", handlePerson); // oops not a person
jQuery.get("data/animals/chop", handleAnimal);
}
jQuery(document).ready(main);
.PHONY: clean build
build: static data things_pb2.py
clean:
rm -f *~ *.pyc *_pb2.py
rm -rf data/
rm -rf static/
server: build
python -m SimpleHTTPServer
static:
mkdir -p static
curl -o static/Long.min.js https://raw.github.com/dcodeIO/Long.js/master/Long.min.js
curl -o static/ByteBuffer.min.js https://raw.github.com/dcodeIO/ByteBuffer.js/master/ByteBuffer.min.js
curl -o static/ProtoBuf.min.js https://raw.github.com/dcodeIO/ProtoBuf.js/master/ProtoBuf.min.js
curl -o static/jquery.min.js http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js
data: things_pb2.py
mkdir -p data/people
mkdir -p data/animals
python generate_data.py
things_pb2.py:
protoc --python_out=. things.proto
package things;
message Person {
required string key = 1;
required string name = 2;
optional uint32 age = 3;
}
message Animal {
required string key = 1;
required string type = 2;
optional string name = 3;
optional string owner_key = 4;
optional Person owner = 5;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment