Fix a regression with ETags in the API and improve overall support.

Review Request #9768 — Created March 12, 2018 and submitted — Latest diff uploaded

Information

Djblets
release-2.0.x
6fc2dce...

Reviewers

A recent change to WebAPIResource attempted to create a standard JSON
payload from which to build an encoded ETag for the resource, replacing
an old repr() call that returned different results on different
versions of Python, for use when autogenerate_etags was set. This
ended up regressing unit tests in Review Board, since by default, json
didn't know all data types we put in the payload.

This could have been fixed by using our own encoders, but it still
wasn't ideal. In the standard case, it meant we were serializing a
payload to JSON twice, and that's not great. Several fixes were
attempted to clean this up, but in the end the method implemented by
this change is to add a more general stage of ETag handling after a
response to the page was generated.

In this case, if autogenerate_etags is on and an explicit ETag was not
provided in the response, one is generated automatically based on the
serialized payload already in the response. This happens after the
HTTP method handlers finish up, in the response processing stage,
meaning that get_list() and HEAD requests benefit.

The old repr() logic was brought back in generate_etag(), for any
older apps that might manually call it. It's no longer used internally,
and is marked for deprecation.

Performance should now actually improve, since automatic ETag generation
has always happened after the database queries and payload building had
completed anyway, and we've now gotten rid of an extra serialization,
reducing the overall work that was needed.

All unit tests in Djblets and Review Board passed.