mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-11-27 03:57:21 +00:00
Fix etag handling
This commit is contained in:
parent
891f0fd599
commit
60e6c8bcb2
@ -202,9 +202,7 @@ MultiWikiClientAdaptor.prototype.saveTiddler = function(tiddler,callback,options
|
|||||||
} else {
|
} else {
|
||||||
var etagInfo = self.parseEtag(etag);
|
var etagInfo = self.parseEtag(etag);
|
||||||
// Invoke the callback
|
// Invoke the callback
|
||||||
callback(null,{
|
callback(null,{},etagInfo.revision);
|
||||||
bag: etagInfo.bag
|
|
||||||
},etagInfo.revision);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -315,10 +313,10 @@ MultiWikiClientAdaptor.prototype.convertTiddlerFromTiddlyWebFormat = function(ti
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Split a TiddlyWeb Etag into its constituent parts. For example:
|
Split an MWS Etag into its constituent parts. For example:
|
||||||
|
|
||||||
```
|
```
|
||||||
"system-images_public/unsyncedIcon/946151:9f11c278ccde3a3149f339f4a1db80dd4369fc04"
|
"tiddler_id:946151"
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that the value includes the opening and closing double quotes.
|
Note that the value includes the opening and closing double quotes.
|
||||||
@ -326,22 +324,16 @@ Note that the value includes the opening and closing double quotes.
|
|||||||
The parts are:
|
The parts are:
|
||||||
|
|
||||||
```
|
```
|
||||||
<bag>/<title>/<revision>:<hash>
|
tiddler_id:<revision>
|
||||||
```
|
```
|
||||||
*/
|
*/
|
||||||
MultiWikiClientAdaptor.prototype.parseEtag = function(etag) {
|
MultiWikiClientAdaptor.prototype.parseEtag = function(etag) {
|
||||||
var firstSlash = etag.indexOf("/"),
|
const PREFIX = "\"tiddler_id:";
|
||||||
lastSlash = etag.lastIndexOf("/"),
|
if(!etag.startsWith(PREFIX)) {
|
||||||
colon = etag.lastIndexOf(":");
|
|
||||||
if(firstSlash === -1 || lastSlash === -1 || colon === -1) {
|
|
||||||
return null;
|
return null;
|
||||||
} else {
|
|
||||||
return {
|
|
||||||
bag: $tw.utils.decodeURIComponentSafe(etag.substring(1,firstSlash)),
|
|
||||||
title: $tw.utils.decodeURIComponentSafe(etag.substring(firstSlash + 1,lastSlash)),
|
|
||||||
revision: etag.substring(lastSlash + 1,colon)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
const revision = parseInt(etag.slice(PREFIX.length),10);
|
||||||
|
return isNaN(revision) ? null : revision;
|
||||||
};
|
};
|
||||||
|
|
||||||
if($tw.browser && document.location.protocol.substr(0,4) === "http" ) {
|
if($tw.browser && document.location.protocol.substr(0,4) === "http" ) {
|
||||||
|
@ -21,8 +21,9 @@ exports.handler = function(request,response,state) {
|
|||||||
var bag_name = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
var bag_name = $tw.utils.decodeURIComponentSafe(state.params[0]),
|
||||||
title = $tw.utils.decodeURIComponentSafe(state.params[1]);
|
title = $tw.utils.decodeURIComponentSafe(state.params[1]);
|
||||||
if(bag_name) {
|
if(bag_name) {
|
||||||
$tw.mws.store.deleteTiddler(title,bag_name);
|
var result = $tw.mws.store.deleteTiddler(title,bag_name);
|
||||||
response.writeHead(204, "OK", {
|
response.writeHead(204, "OK", {
|
||||||
|
Etag: "\"tiddler_id:" + result.tiddler_id + "\"",
|
||||||
"Content-Type": "text/plain"
|
"Content-Type": "text/plain"
|
||||||
});
|
});
|
||||||
response.end();
|
response.end();
|
||||||
|
@ -24,7 +24,8 @@ exports.handler = function(request,response,state) {
|
|||||||
const result = $tw.mws.store.getBagTiddlerStream(title,bag_name);
|
const result = $tw.mws.store.getBagTiddlerStream(title,bag_name);
|
||||||
if(result) {
|
if(result) {
|
||||||
response.writeHead(200, "OK",{
|
response.writeHead(200, "OK",{
|
||||||
"Content-Type": result.type
|
Etag: "\"tiddler_id:" + result.tiddler_id + "\"",
|
||||||
|
"Content-Type": result.type,
|
||||||
});
|
});
|
||||||
result.stream.pipe(response);
|
result.stream.pipe(response);
|
||||||
return;
|
return;
|
||||||
|
@ -41,13 +41,17 @@ exports.handler = function(request,response,state) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
tiddlerFields.type = tiddlerFields.type || "text/vnd.tiddlywiki";
|
tiddlerFields.type = tiddlerFields.type || "text/vnd.tiddlywiki";
|
||||||
state.sendResponse(200,{"Content-Type": "application/json"},JSON.stringify(tiddlerFields),"utf8");
|
state.sendResponse(200,{
|
||||||
|
Etag: "\"tiddler_id:" + tiddlerInfo.tiddler_id + "\"",
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
},JSON.stringify(tiddlerFields),"utf8");
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// This is not a JSON API request, we should return the raw tiddler content
|
// This is not a JSON API request, we should return the raw tiddler content
|
||||||
const result = $tw.mws.store.getBagTiddlerStream(title,bag_name);
|
const result = $tw.mws.store.getBagTiddlerStream(title,bag_name);
|
||||||
if(result) {
|
if(result) {
|
||||||
response.writeHead(200, "OK",{
|
response.writeHead(200, "OK",{
|
||||||
|
Etag: "\"tiddler_id:" + result.tiddler_id + "\"",
|
||||||
"Content-Type": result.type
|
"Content-Type": result.type
|
||||||
});
|
});
|
||||||
result.stream.pipe(response);
|
result.stream.pipe(response);
|
||||||
|
@ -41,12 +41,16 @@ exports.handler = function(request,response,state) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
tiddlerFields.type = tiddlerFields.type || "text/vnd.tiddlywiki";
|
tiddlerFields.type = tiddlerFields.type || "text/vnd.tiddlywiki";
|
||||||
state.sendResponse(200,{"Content-Type": "application/json"},JSON.stringify(tiddlerFields),"utf8");
|
state.sendResponse(200,{
|
||||||
|
Etag: "\"tiddler_id:" + tiddlerInfo.tiddler_id + "\"",
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
},JSON.stringify(tiddlerFields),"utf8");
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// This is not a JSON API request, we should return the raw tiddler content
|
// This is not a JSON API request, we should return the raw tiddler content
|
||||||
var type = tiddlerInfo.tiddler.type || "text/plain";
|
var type = tiddlerInfo.tiddler.type || "text/plain";
|
||||||
response.writeHead(200, "OK",{
|
response.writeHead(200, "OK",{
|
||||||
|
Etag: "\"tiddler_id:" + tiddlerInfo.tiddler_id + "\"",
|
||||||
"Content-Type": type
|
"Content-Type": type
|
||||||
});
|
});
|
||||||
response.write(tiddlerInfo.tiddler.text || "",($tw.config.contentTypeInfo[type] ||{encoding: "utf8"}).encoding);
|
response.write(tiddlerInfo.tiddler.text || "",($tw.config.contentTypeInfo[type] ||{encoding: "utf8"}).encoding);
|
||||||
|
@ -48,17 +48,35 @@ exports.handler = function(request,response,state) {
|
|||||||
if(markerPos === -1) {
|
if(markerPos === -1) {
|
||||||
throw new Error("Cannot find tiddler store in template");
|
throw new Error("Cannot find tiddler store in template");
|
||||||
}
|
}
|
||||||
|
function writeTiddler(tiddlerFields) {
|
||||||
|
response.write(JSON.stringify(tiddlerFields).replace(/</g,"\\u003c"));
|
||||||
|
response.write(",\n");
|
||||||
|
}
|
||||||
response.write(template.substring(0,markerPos + marker.length));
|
response.write(template.substring(0,markerPos + marker.length));
|
||||||
|
const bagInfo = {},
|
||||||
|
revisionInfo = {};
|
||||||
$tw.utils.each(recipeTiddlers,function(recipeTiddlerInfo) {
|
$tw.utils.each(recipeTiddlers,function(recipeTiddlerInfo) {
|
||||||
var result = $tw.mws.store.getRecipeTiddler(recipeTiddlerInfo.title,recipe_name);
|
var result = $tw.mws.store.getRecipeTiddler(recipeTiddlerInfo.title,recipe_name);
|
||||||
if(result) {
|
if(result) {
|
||||||
var tiddlerFields = result.tiddler;
|
bagInfo[result.tiddler.title] = result.bag_name;
|
||||||
response.write(JSON.stringify(tiddlerFields).replace(/</g,"\\u003c"));
|
revisionInfo[result.tiddler.title] = result.tiddler_id.toString();
|
||||||
response.write(",\n")
|
writeTiddler(result.tiddler);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
response.write(JSON.stringify({title: "$:/config/multiwikiclient/recipe",text: recipe_name}));
|
writeTiddler({
|
||||||
response.write(",\n")
|
title: "$:/config/multiwikiclient/tiddlers/bag",
|
||||||
|
text: JSON.stringify(bagInfo),
|
||||||
|
type: "application/json"
|
||||||
|
});
|
||||||
|
writeTiddler({
|
||||||
|
title: "$:/config/multiwikiclient/tiddlers/revision",
|
||||||
|
text: JSON.stringify(revisionInfo),
|
||||||
|
type: "application/json"
|
||||||
|
});
|
||||||
|
writeTiddler({
|
||||||
|
title: "$:/config/multiwikiclient/recipe",
|
||||||
|
text: recipe_name
|
||||||
|
});
|
||||||
response.write(template.substring(markerPos + marker.length))
|
response.write(template.substring(markerPos + marker.length))
|
||||||
// Finish response
|
// Finish response
|
||||||
response.end();
|
response.end();
|
||||||
|
@ -38,7 +38,7 @@ exports.handler = function(request,response,state) {
|
|||||||
var result = $tw.mws.store.saveRecipeTiddler(fields,recipe_name);
|
var result = $tw.mws.store.saveRecipeTiddler(fields,recipe_name);
|
||||||
if(result) {
|
if(result) {
|
||||||
response.writeHead(204, "OK",{
|
response.writeHead(204, "OK",{
|
||||||
Etag: "\"" + result.bag_name + "/" + encodeURIComponent(title) + "/" + result.tiddler_id + ":\"",
|
Etag: "\"tiddler_id:" + result.tiddler_id + "\"",
|
||||||
"Content-Type": "text/plain"
|
"Content-Type": "text/plain"
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -263,6 +263,9 @@ SqlTiddlerDatabase.prototype.saveRecipeTiddler = function(tiddlerFields,recipe_n
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Returns {tiddler_id:} of the delete marker
|
||||||
|
*/
|
||||||
SqlTiddlerDatabase.prototype.deleteTiddler = function(title,bag_name) {
|
SqlTiddlerDatabase.prototype.deleteTiddler = function(title,bag_name) {
|
||||||
// Delete the fields of this tiddler
|
// Delete the fields of this tiddler
|
||||||
this.engine.runStatement(`
|
this.engine.runStatement(`
|
||||||
@ -278,7 +281,7 @@ SqlTiddlerDatabase.prototype.deleteTiddler = function(title,bag_name) {
|
|||||||
$bag_name: bag_name
|
$bag_name: bag_name
|
||||||
});
|
});
|
||||||
// Mark the tiddler itself as deleted
|
// Mark the tiddler itself as deleted
|
||||||
this.engine.runStatement(`
|
const rowDeleteMarker = this.engine.runStatement(`
|
||||||
INSERT OR REPLACE INTO tiddlers (bag_id, title, is_deleted, attachment_blob)
|
INSERT OR REPLACE INTO tiddlers (bag_id, title, is_deleted, attachment_blob)
|
||||||
VALUES (
|
VALUES (
|
||||||
(SELECT bag_id FROM bags WHERE bag_name = $bag_name),
|
(SELECT bag_id FROM bags WHERE bag_name = $bag_name),
|
||||||
@ -290,6 +293,7 @@ SqlTiddlerDatabase.prototype.deleteTiddler = function(title,bag_name) {
|
|||||||
$title: title,
|
$title: title,
|
||||||
$bag_name: bag_name
|
$bag_name: bag_name
|
||||||
});
|
});
|
||||||
|
return {tiddler_id: rowDeleteMarker.lastInsertRowid};
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -219,7 +219,7 @@ SqlTiddlerStore.prototype.saveRecipeTiddler = function(incomingTiddlerFields,rec
|
|||||||
};
|
};
|
||||||
|
|
||||||
SqlTiddlerStore.prototype.deleteTiddler = function(title,bag_name) {
|
SqlTiddlerStore.prototype.deleteTiddler = function(title,bag_name) {
|
||||||
this.sqlTiddlerDatabase.deleteTiddler(title,bag_name);
|
return this.sqlTiddlerDatabase.deleteTiddler(title,bag_name);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -241,14 +241,19 @@ SqlTiddlerStore.prototype.getBagTiddler = function(title,bag_name) {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Get an attachment ready to stream. Returns null if there is an error or:
|
Get an attachment ready to stream. Returns null if there is an error or:
|
||||||
|
tiddler_id: revision of tiddler
|
||||||
stream: stream of file
|
stream: stream of file
|
||||||
type: type of file
|
type: type of file
|
||||||
|
Returns {tiddler_id:}
|
||||||
*/
|
*/
|
||||||
SqlTiddlerStore.prototype.getBagTiddlerStream = function(title,bag_name) {
|
SqlTiddlerStore.prototype.getBagTiddlerStream = function(title,bag_name) {
|
||||||
const tiddlerInfo = this.sqlTiddlerDatabase.getBagTiddler(title,bag_name);
|
const tiddlerInfo = this.sqlTiddlerDatabase.getBagTiddler(title,bag_name);
|
||||||
if(tiddlerInfo) {
|
if(tiddlerInfo) {
|
||||||
if(tiddlerInfo.attachment_blob) {
|
if(tiddlerInfo.attachment_blob) {
|
||||||
return this.attachmentStore.getAttachmentStream(tiddlerInfo.attachment_blob);
|
return $tw.utils.extend(
|
||||||
|
{},
|
||||||
|
this.attachmentStore.getAttachmentStream(tiddlerInfo.attachment_blob),
|
||||||
|
{tiddler_id: tiddlerInfo.tiddler_id});
|
||||||
} else {
|
} else {
|
||||||
const { Readable } = require('stream');
|
const { Readable } = require('stream');
|
||||||
const stream = new Readable();
|
const stream = new Readable();
|
||||||
@ -260,6 +265,7 @@ SqlTiddlerStore.prototype.getBagTiddlerStream = function(title,bag_name) {
|
|||||||
stream.push(null);
|
stream.push(null);
|
||||||
};
|
};
|
||||||
return {
|
return {
|
||||||
|
tiddler_id: tiddlerInfo.tiddler_id,
|
||||||
stream: stream,
|
stream: stream,
|
||||||
type: tiddlerInfo.tiddler.type || "text/plain"
|
type: tiddlerInfo.tiddler.type || "text/plain"
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user