internal/v4: implement archive uploading

We don't yet verify bundles against charms in the store.

This required some refactoring of the testing code;
the most important change is AssertJSONCall actually
makes a real HTTP call through a socket, as that
allows us to correctly test the ContentLength logic.
It also gives us greater assurance that the logic
will work over a real HTTP connection. The overhead
seems to be negligible.
If we can't remove the blob, we're unlikely to be able to tag it.
My view is that we'll eventually need some kind of garbage collector
in the blob store to clean up blobs that are unreferenced because
of server crashes.