isaacs/npm — Issue #1591: 409 Conflict, corrupt package document through bad proxy
Author: jhs
Created: 2011-10-23 04:54:46+00:00
State: open

My ISP has a "transparent" proxy that caches GETs pretty aggressively. `npm publish` is not quite robust in this situation. I manually fixed my package logging in to your couch Futon with my account (which, by the way, that's bad-ass that we can do that).

Based on the wreckage I saw (not, say, reading the source or examining the HTTP traffic), this is my guess about the bug.

1. npm GETs the current package doc
1. The proxy returns stale data
1. npm splits the update into two requests, **red flag**
1. POST new metadata to an `_update` function which works as it doesn't need the client to supply the `_rev` **red flag**
1. PUT the attachment via the direct attachment API, with the *original* rev got from step 1.

Some ideas on fixing the bug.

* Just base64 encode the attachment and do it in one big update. Keep it atomic. Base64 adds 33% to the attachment size on the wire. That's not so bad. Also Couch parses the JSON in batch, so large attachments might exceed its memory. Maybe you could use the inline method for attachments up to size N, and fall back to the old way for larger ones.
* Try to attach first, then update metadata, that way at least `dist-tags.latest` won't be wrong.
* Get the rev from the `_update` request (it's in one of the response headers), and use that for the attachment PUT. Since the `_update` was a POST, it is pretty likely to reflect the current data.

A workaround is to use the HTTPS repo. I did that and this bug is no longer a problem for me.

Another workaround is the timestamp in the queystring hack, which is effective and universal but makes the baby Jesus cry.