Fix file upload error when remote attachment has no stored hash

This commit is contained in:
Dan Stillman 2017-01-22 15:30:18 -05:00
parent 90a3013802
commit c9694e93b0
2 changed files with 112 additions and 29 deletions

View file

@ -374,33 +374,49 @@ Zotero.Sync.Storage.Mode.ZFS.prototype = {
}
body = body.join('&');
try {
var req = yield this.apiClient.makeRequest(
"POST",
uri,
{
body,
headers,
// This should include all errors in _handleUploadAuthorizationFailure()
successCodes: [200, 201, 204, 403, 404, 412, 413],
debug: true
}
);
}
catch (e) {
if (e instanceof Zotero.HTTP.UnexpectedStatusException) {
let msg = "Unexpected status code " + e.status + " in " + funcName
+ " (" + item.libraryKey + ")";
Zotero.logError(msg);
Zotero.debug(e.xmlhttp.getAllResponseHeaders());
throw new Error(Zotero.Sync.Storage.defaultError);
var req;
while (true) {
try {
req = yield this.apiClient.makeRequest(
"POST",
uri,
{
body,
headers,
// This should include all errors in _handleUploadAuthorizationFailure()
successCodes: [200, 201, 204, 403, 404, 412, 413],
debug: true
}
);
}
catch (e) {
if (e instanceof Zotero.HTTP.UnexpectedStatusException) {
let msg = "Unexpected status code " + e.status + " in " + funcName
+ " (" + item.libraryKey + ")";
Zotero.logError(msg);
Zotero.debug(e.xmlhttp.getAllResponseHeaders());
throw new Error(Zotero.Sync.Storage.defaultError);
}
throw e;
}
let result = yield this._handleUploadAuthorizationFailure(req, item);
if (result instanceof Zotero.Sync.Storage.Result) {
return result;
}
// If remote attachment exists but has no hash (which can happen for an old (pre-4.0?)
// attachment with just an mtime, or after a storage purge), send again with If-None-Match
else if (result == "ERROR_412_WITHOUT_VERSION") {
if (headers["If-None-Match"]) {
throw new Error("412 returned for request with If-None-Match");
}
delete headers["If-Match"];
headers["If-None-Match"] = "*";
Zotero.debug("Retrying with If-None-Match");
}
else {
break;
}
throw e;
}
var result = yield this._handleUploadAuthorizationFailure(req, item);
if (result instanceof Zotero.Sync.Storage.Result) {
return result;
}
try {
@ -468,10 +484,9 @@ Zotero.Sync.Storage.Mode.ZFS.prototype = {
throw new Error(Zotero.Sync.Storage.defaultError);
}
else if (req.status == 412) {
Zotero.debug("412 BUT WE'RE COOL");
let version = req.getResponseHeader('Last-Modified-Version');
if (!version) {
throw new Error("Last-Modified-Version header not provided");
return "ERROR_412_WITHOUT_VERSION";
}
if (version > item.version) {
return new Zotero.Sync.Storage.Result({

View file

@ -817,7 +817,75 @@ describe("Zotero.Sync.Storage.Mode.ZFS", function () {
assert.isFalse(result.localChanges);
assert.isFalse(result.remoteChanges);
assert.isTrue(result.syncRequired);
})
});
it("should retry with If-None-Match on 412 with missing remote hash", function* () {
var { engine, client, caller } = yield setup();
var zfs = new Zotero.Sync.Storage.Mode.ZFS({
apiClient: client
})
var file = getTestDataDirectory();
file.append('test.png');
var item = yield Zotero.Attachments.importFromFile({ file });
item.version = 5;
item.synced = true;
item.attachmentSyncedModificationTime = Date.now();
item.attachmentSyncedHash = 'bd4c33e03798a7e8bc0b46f8bda74fac'
yield item.saveTx();
var contentType = 'image/png';
var prefix = Zotero.Utilities.randomString();
var suffix = Zotero.Utilities.randomString();
var uploadKey = Zotero.Utilities.randomString(32, 'abcdef0123456789');
var called = 0;
server.respond(function (req) {
if (req.method == "POST"
&& req.url == `${baseURL}users/1/items/${item.key}/file`
&& !req.requestBody.includes('upload=')
&& req.requestHeaders["If-Match"] == item.attachmentSyncedHash) {
called++;
req.respond(
412,
{
"Content-Type": "application/json"
},
"If-Match set but file does not exist"
);
}
else if (req.method == "POST"
&& req.url == `${baseURL}users/1/items/${item.key}/file`
&& !req.requestBody.includes('upload=')
&& req.requestHeaders["If-None-Match"] == "*") {
assert.equal(called++, 1)
req.respond(
200,
{
"Content-Type": "application/json"
},
JSON.stringify({
url: baseURL + "pretend-s3/1",
contentType: contentType,
prefix: prefix,
suffix: suffix,
uploadKey: uploadKey
})
);
}
})
var stub = sinon.stub(zfs, "_uploadFile");
yield zfs._processUploadFile({
name: item.libraryKey
});
assert.equal(called, 2);
assert.ok(stub.called);
stub.restore();
});
it("should handle 413 on quota limit", function* () {
var { engine, client, caller } = yield setup();