Merge pull request #1899 from fletcherhaz/snapshot
Fix server not handling empty body in multi-part request. Fixes #1897
This commit is contained in:
commit
1307fdfae7
2 changed files with 54 additions and 5 deletions
|
@ -466,6 +466,7 @@ Zotero.Server.DataListener.prototype._processEndpoint = Zotero.Promise.coroutine
|
||||||
} else if(this.contentType === "multipart/form-data") {
|
} else if(this.contentType === "multipart/form-data") {
|
||||||
let boundary = /boundary=([^\s]*)/i.exec(this.header);
|
let boundary = /boundary=([^\s]*)/i.exec(this.header);
|
||||||
if (!boundary) {
|
if (!boundary) {
|
||||||
|
Zotero.debug('Invalid boundary: ' + this.header, 1);
|
||||||
return this._requestFinished(this._generateResponse(400, "text/plain", "Invalid multipart/form-data provided\n"));
|
return this._requestFinished(this._generateResponse(400, "text/plain", "Invalid multipart/form-data provided\n"));
|
||||||
}
|
}
|
||||||
boundary = '--' + boundary[1];
|
boundary = '--' + boundary[1];
|
||||||
|
@ -603,17 +604,18 @@ Zotero.Server.DataListener.prototype._decodeMultipartData = function(data, bound
|
||||||
data = data.slice(1, data.length-1);
|
data = data.slice(1, data.length-1);
|
||||||
for (let field of data) {
|
for (let field of data) {
|
||||||
let fieldData = {};
|
let fieldData = {};
|
||||||
field = field.trim();
|
|
||||||
// Split header and body
|
// Split header and body
|
||||||
let unixHeaderBoundary = field.indexOf("\n\n");
|
let unixHeaderBoundary = field.indexOf("\n\n");
|
||||||
let windowsHeaderBoundary = field.indexOf("\r\n\r\n");
|
let windowsHeaderBoundary = field.indexOf("\r\n\r\n");
|
||||||
if (unixHeaderBoundary < windowsHeaderBoundary && unixHeaderBoundary != -1) {
|
if (unixHeaderBoundary < windowsHeaderBoundary && unixHeaderBoundary != -1) {
|
||||||
fieldData.header = field.slice(0, unixHeaderBoundary);
|
fieldData.header = field.slice(0, unixHeaderBoundary).trim();
|
||||||
fieldData.body = field.slice(unixHeaderBoundary+2);
|
fieldData.body = field.slice(unixHeaderBoundary+2).trim();
|
||||||
} else if (windowsHeaderBoundary != -1) {
|
} else if (windowsHeaderBoundary != -1) {
|
||||||
fieldData.header = field.slice(0, windowsHeaderBoundary);
|
fieldData.header = field.slice(0, windowsHeaderBoundary).trim();
|
||||||
fieldData.body = field.slice(windowsHeaderBoundary+4);
|
fieldData.body = field.slice(windowsHeaderBoundary+4).trim();
|
||||||
} else {
|
} else {
|
||||||
|
// Only log first 200 characters in case the part is large
|
||||||
|
Zotero.debug('Malformed multipart/form-data body: ' + field.substr(0, 200), 1);
|
||||||
throw new Error('Malformed multipart/form-data body');
|
throw new Error('Malformed multipart/form-data body');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -240,6 +240,53 @@ describe("Zotero.Server", function () {
|
||||||
assert.ok(called);
|
assert.ok(called);
|
||||||
assert.equal(req.status, 204);
|
assert.equal(req.status, 204);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should support an empty body", async function () {
|
||||||
|
var called = false;
|
||||||
|
var endpoint = "/test/" + Zotero.Utilities.randomString();
|
||||||
|
|
||||||
|
Zotero.Server.Endpoints[endpoint] = function () {};
|
||||||
|
Zotero.Server.Endpoints[endpoint].prototype = {
|
||||||
|
supportedMethods: ["POST"],
|
||||||
|
supportedDataTypes: ["multipart/form-data"],
|
||||||
|
|
||||||
|
init: function (options) {
|
||||||
|
called = true;
|
||||||
|
assert.isObject(options);
|
||||||
|
assert.property(options.headers, "Content-Type");
|
||||||
|
assert(options.headers["Content-Type"].startsWith("multipart/form-data; boundary="));
|
||||||
|
assert.isArray(options.data);
|
||||||
|
assert.equal(options.data.length, 1);
|
||||||
|
|
||||||
|
let expected = {
|
||||||
|
header: "Content-Disposition: form-data; name=\"foo\"",
|
||||||
|
body: "",
|
||||||
|
params: {
|
||||||
|
name: "foo"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
assert.deepEqual(options.data[0], expected);
|
||||||
|
return 204;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let formData = new FormData();
|
||||||
|
formData.append("foo", "");
|
||||||
|
|
||||||
|
let req = await Zotero.HTTP.request(
|
||||||
|
"POST",
|
||||||
|
serverPath + endpoint,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "multipart/form-data"
|
||||||
|
},
|
||||||
|
body: formData
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.ok(called);
|
||||||
|
assert.equal(req.status, 204);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue