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.
Yes, it's fine (this code hasn't changed in this PR, just moved from api.go).

A charm.Reference is just like a charm.URL except that it is not guaranteed
to have a Series. My point of view on this is that it's not really worth representing
that distinction in the type system and so we're using charm.Reference throughout,
which makes other things more straightforward.