1
0
mirror of https://github.com/Jermolene/TiddlyWiki5 synced 2024-11-23 18:17:20 +00:00

putSaver: detect edit conflicts to prevent clobbering, if possible

if the server supplies an ETag, we send it back when saving, allowing
the server to detect edit conflicts and respond with 412 (cf.
https://www.w3.org/1999/04/Editing/)

caveats:
* this only kicks in after the first save, as we don't have access to
  the ETag when first loading the document
* there's no recovery mechanism (e.g. resetting `this.etag` in order to
  force clobbering), other than manually reloading the document
This commit is contained in:
FND 2016-10-15 17:03:50 +02:00
parent d7b6917638
commit 2d75cb83af

View File

@ -27,7 +27,7 @@ var PutSaver = function(wiki) {
req.open("OPTIONS",encodeURI(document.location.protocol + "//" + document.location.hostname + ":" + document.location.port + document.location.pathname)); req.open("OPTIONS",encodeURI(document.location.protocol + "//" + document.location.hostname + ":" + document.location.port + document.location.pathname));
req.onload = function() { req.onload = function() {
// Check DAV header http://www.webdav.org/specs/rfc2518.html#rfc.section.9.1 // Check DAV header http://www.webdav.org/specs/rfc2518.html#rfc.section.9.1
self.serverAcceptsPuts = (this.status === 200 && !!this.getResponseHeader('dav')); self.serverAcceptsPuts = (this.status === 200 && !!this.getResponseHeader("dav"));
}; };
req.send(); req.send();
}; };
@ -37,19 +37,25 @@ PutSaver.prototype.save = function(text,method,callback) {
return false; return false;
} }
var req = new XMLHttpRequest(); var req = new XMLHttpRequest();
// TODO: store/check ETags if supported by server, to protect against overwrites // TODO: in case of edit conflict
// Prompt: Do you want to save over this? Y/N // Prompt: Do you want to save over this? Y/N
// Merging would be ideal, and may be possible using future generic merge flow // Merging would be ideal, and may be possible using future generic merge flow
req.onload = function() { req.onload = function() {
if (this.status === 200 || this.status === 201) { if (this.status === 200 || this.status === 201) {
this.etag = this.getResponseHeader("ETag");
callback(null); // success callback(null); // success
} }
else if (this.status === 412) { // edit conflict
callback("File changed on server");
else { else {
callback(this.responseText); // fail callback(this.responseText); // fail
} }
}; };
req.open("PUT", encodeURI(window.location.href)); req.open("PUT", encodeURI(window.location.href));
req.setRequestHeader("Content-Type", "text/html;charset=UTF-8"); req.setRequestHeader("Content-Type", "text/html;charset=UTF-8");
if (this.etag) {
req.setRequestHeader("If-Match", this.etag);
}
req.send(text); req.send(text);
return true; return true;
}; };