> [*] While at Pycon I converted Mailman 3 from lazr.restful to restish. There
> are a lot of nice things about restish, not the least of which that it's much
> more agile to add new APIs.
I noticed you were experimenting with restish in Mailman. Glad to hear
you've had some success and find it easy to work with.
> I also think it leads to more readable, more
> discoverable code because there are no ZCML files :).
Yeah, in general I'm not keen on lots of external configuration but
that's sometimes a matter of personal preference.
> restish also allows you
> to more cleanly separate API from internal model interfaces.
Agreed. restish is about resources and representations. I like to
think the model part of the application is left to the developer to
make the best choice.
> The things it
> doesn't have that lazr.restful gives you are support for collections
> (including batching), etags, and a few other niceties. I have some thoughts
> on adding a few things to restish, but haven't had time to put together some
> code. Feel free to hijack this thread if you want to discuss in more
> detail. :)
I would love to hear your thoughts and maybe sketch some stuff out
together. Like you I'm limited for time, but perhaps a group effort
will produce something useful.
The need for some sort of collection resource has been raised before.
I already have something embedded in an application but it's only JSON
and there's no point in adding something like that to restish as-is;
it needs to support multiple representations. My gut feeling says this
is a combination of two things:
1. A collection resource that works at a Python object level.
2. A mechanism for automatically serializing lists of objects and
single objects to various formats. (Not some hard-coded, inflexible
registry approach though!)
Caching helpers is another subject that I've been intending to tackle
for some time now. I'm fairly sure a couple of cache header building
functions for dynamic caching and some decorators for more static
caching would cover most common requirements.
Something like the following:
@caching.never_cache()
def resource(request):
return ...
@caching.expires(3600)
def resource(request):
return ...
@caching.expires(timedelta(days=10))
def resource(request):
return ...
@GET()
def html(request):
obj = find_obj()
return http.ok([caching.etag(hash(obj)), json.dumps(obj))
However, that last example isn't quite right because you wouldn't want
to build the "200 OK" if the etag is still correct. So something to
check the validity of an etag and hopefully create the "304" response
for you would be good. Would a context manager help here?
@GET()
def html(request):
obj = find_obj()
with caching.etag_mismatch(request, hash(obj)):
return http.ok([caching.etag(hash(obj)), json.dumps(obj))
Of course, an ETag header is really a list of tags and then there's
setting the Vary header correctly too, but I'll just gloss over that
for now ;-).
- Matt