Browse Source

client automatically reloads when the server restarts, and fixed issues with caching

master
mort 8 years ago
parent
commit
d8324c4031
3 changed files with 160 additions and 30 deletions
  1. 32
    4
      index.html
  2. 20
    0
      npm-debug.log
  3. 108
    26
      server.js

+ 32
- 4
index.html View File

@@ -77,7 +77,7 @@
}

// Change slides with a transition
function update() {
function update(name) {
overlay().innerHTML = "";
overlay().className = "_content";
swap(main(), overlay());
@@ -86,19 +86,47 @@
.then(response => response.text())
.then(text => {
setTimeout(() => {
history.replaceState({}, "", "/"+name+"/");
main().innerHTML = text;
overlay().className = "_content hidden";
}, 1000);
})
.catch(err => console.error(err));
}

function reload() {
var i = setInterval(() => {
fetch("/")
.then(() => {
history.replaceState({}, "", "/");
location.reload();
})
.catch(() => {});
}, 1000);
}

function await() {
// Wait for the next slide change, then update again
fetch("/await")
.then(response => update())
.catch(err => { console.error(err); update(); });
.then(response => response.json())
.then(obj => {
if (obj.evt === "next") {
update(obj.args.name);
} else if (obj.evt === "reload") {
return reload();
} else {
console.log("Unknown event: "+obj.evt);
}
await();
})
.catch(err => { console.error(err); await(); });
}

update();
await();

fetch("/init")
.then(response => response.text())
.then(name => update(name));
</script>
</body>
</html>

+ 20
- 0
npm-debug.log View File

@@ -0,0 +1,20 @@
0 info it worked if it ends with ok
1 verbose cli [ '/usr/local/bin/node', '/usr/local/bin/npm', 'start' ]
2 info using npm@3.8.3
3 info using node@v5.10.1
4 verbose stack Error: ENOENT: no such file or directory, open '/var/www/mrow.me/sonen/package.json'
4 verbose stack at Error (native)
5 verbose cwd /var/www/mrow.me/sonen
6 error Linux 3.16.0-4-amd64
7 error argv "/usr/local/bin/node" "/usr/local/bin/npm" "start"
8 error node v5.10.1
9 error npm v3.8.3
10 error path /var/www/mrow.me/sonen/package.json
11 error code ENOENT
12 error errno -2
13 error syscall open
14 error enoent ENOENT: no such file or directory, open '/var/www/mrow.me/sonen/package.json'
15 error enoent ENOENT: no such file or directory, open '/var/www/mrow.me/sonen/package.json'
15 error enoent This is most likely not a problem with npm itself
15 error enoent and is related to npm not being able to find a file.
16 verbose exit [ -2, true ]

+ 108
- 26
server.js View File

@@ -13,33 +13,74 @@ function error(res, err) {
res.end(err.toString());
}

function mimetype(path) {
var ext = pathlib.extname(path)
.substring(1)
.toLowerCase();

switch (ext) {

case "html":
case "xml":
return "text/"+ext;

case "png":
case "jpg":
case "jpeg":
case "gif":
return "image/"+ext;

case "svg":
return "image/svg+xml";

case "mov":
case "mp4":
case "ogv":
case "webm":
return "video/"+ext;

case "mp3":
case "ogg":
case "flac":
case "m4a":
return "audio/"+ext;

default:
return "application/octet-stream";
}
}

function sendfile(res, path) {
res.writeHead(200, {
"content-type": mimetype(path)
});

fs.createReadStream(path)
.on("error", err => error(res, err))
.pipe(res);
}

// The individual slide
function Slide(dir) {
var self = {};

self.dir = dir;
self.name = pathlib.parse(dir).name;

function serve(parts, res) {
if (parts.pathname === "/slide") {
fs.createReadStream(pathlib.join(dir, "index.html"))
.on("error", err => error(res, err))
.pipe(res);
} else {
fs.createReadStream(pathlib.join(dir, parts.pathname))
.on("error", err => error(res, err))
.pipe(res);
}
self.serveSlide = function(parts, res) {
sendfile(res, pathlib.join(dir, "index.html"));
}

self.serve = function(parts, res) {
try {
serve(parts, res);
} catch (err) {
if (err.code && err.code === "ENOENT")
res.writeHead(404);
self.serveFiles = function(parts, res) {

error(res, err);
// Redirect to / if /{name} is requested
if (parts.pathname.replace(/\//g, "") === self.name) {
res.writeHead(302, { location: "/" });
return res.end();
}

var name = parts.pathname.substring(1).replace(self.name, "");
sendfile(res, pathlib.join(dir, name));
}

return self;
@@ -52,6 +93,14 @@ function Slideshow(dir, changeInterval) {

var currentSlide = null;
var awaiters = [];
var slides = [];

self.sendEvent = function(evt, args) {
awaiters.forEach(res => res.end(JSON.stringify({
evt: evt,
args: args
})));
}

self.serve = function(req, res) {
var parts = urllib.parse(req.url);
@@ -60,24 +109,43 @@ function Slideshow(dir, changeInterval) {
if (parts.pathname === "/") {
res.end(index);

// /init: send initial information about current slide
} else if (parts.pathname === "/init") {
res.end(currentSlide ? currentSlide.name : "");

// /await: long polling, request won't end before a new slide comes
} else if (parts.pathname === "/await") {
awaiters.push(res);

// There's a current slide: leave serving files up to the slide
} else if (currentSlide) {
currentSlide.serve(parts, res);
// /slide: serve the current slide's html
} else if (parts.pathname === "/slide" && currentSlide) {
currentSlide.serveSlide(parts, res);

// There's no current slide show
// Serve other files
} else {
res.end("No current slideshow.");
var served = false;

for (var slide of slides) {

// If client requests /{slide-name}/*
if (slide.name === parts.pathname.substr(1, slide.name.length)) {
slide.serveFiles(parts, res);
served = true;
break;
}
}

if (!served) {
res.writeHead(404);
res.end("404");
}
}
}

// This function starts the slideshow and goes through the slides
// one by one. When done, it starts again by calling this function again.
function init() {
var slides = fs.readdirSync(dir)
slides = fs.readdirSync(dir)
.sort()
.map(file => Slide(pathlib.join(dir, file)));

@@ -96,7 +164,7 @@ function Slideshow(dir, changeInterval) {
}

// End all awaiting connections to notify slide change
awaiters.forEach(res => res.end());
self.sendEvent("next", { name: currentSlide.name });
}, changeInterval);
}
init();
@@ -106,6 +174,20 @@ function Slideshow(dir, changeInterval) {

var slideshow = Slideshow(conf.slides, conf.interval);

http.createServer((req, res) => {
function onexit() {
slideshow.sendEvent("reload");
process.exit();
}
process.on("exit", onexit);
process.on("SIGINT", onexit);
process.on("SIGTERM", onexit);

var server = http.createServer((req, res) => {
slideshow.serve(req, res);
}).listen(conf.port);
});
server.on("error", err => {
console.error(err.toString());
system.exit(1);
});
server.listen(conf.port);
console.log("Server running on port "+conf.port+".");

Loading…
Cancel
Save