Skip to content

Instantly share code, notes, and snippets.

@susanBuck
Last active October 7, 2025 21:50
Show Gist options
  • Select an option

  • Save susanBuck/4fcbcfb47f80abbe4db2b3fc8cab60e6 to your computer and use it in GitHub Desktop.

Select an option

Save susanBuck/4fcbcfb47f80abbe4db2b3fc8cab60e6 to your computer and use it in GitHub Desktop.
PSY1903 file updates
<!doctype html>
<html lang='en'>
<head>
<title>PSY1903</title>
<link href=data:, rel=icon>
</head>
<body>
<h1>My PSY1903 Web Server</h1>
<h2>Contents</h2>
<ul id="directory-list"></ul>
<script>
function renderTree(tree, basePath, ul) {
Object.entries(tree).forEach(([name, child]) => {
const li = document.createElement('li');
if (child && typeof child === 'object') {
// Directory: plain text
li.textContent = name;
ul.appendChild(li);
const nested = document.createElement('ul');
li.appendChild(nested);
renderTree(child, `${basePath}${name}/`, nested);
} else {
if (name === 'index.html' && basePath === '') {
// Current page: plain text
li.textContent = name;
ul.appendChild(li);
} else {
// File: link
const a = document.createElement('a');
const href = `${basePath}${name}`;
a.href = href;
a.textContent = name;
li.appendChild(a);
ul.appendChild(li);
}
}
});
}
const list = document.getElementById('directory-list');
if (location.hostname.includes('localhost')) {
fetch('/contents')
.then(response => response.json())
.then(data => {
list.innerHTML = '';
renderTree(data.files, '', list);
})
.catch(error => {
console.error('Error fetching directories:', error);
});
} else {
list.innerHTML = 'Directory listing not available on production.';
}
</script>
</body>
</html>
const express = require('express');
const app = express();
const path = require('path');
const fs = require('fs');
const findFreePort = require('find-free-port');
findFreePort(3000, (err, freePort) => {
if (err) throw err;
const PORT = freePort;
// Makes JSON request bodies accessible via req.body
app.use(express.json());
// Serve static files from the web/ directory
app.use(express.static(path.join(__dirname, 'web')));
// Set homepage to web/index.html
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'web', 'index.html'));
});
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
// GET /contents
// Route to list web contents
app.get('/contents', (req, res) => {
function readDirRecursive(dir) {
let results = {};
const entries = fs.readdirSync(dir).filter(file => file !== '.DS_Store');
entries.forEach(entry => {
const fullPath = path.join(dir, entry);
let stat;
try {
stat = fs.lstatSync(fullPath);
} catch (e) {
// Skip files that can’t be stat’ed
return;
}
if (stat.isSymbolicLink()) {
// Ignore symbolic links
return;
}
if (stat.isDirectory()) {
results[entry] = readDirRecursive(fullPath);
} else {
results[entry] = null;
}
});
return results;
}
try {
const directoryTree = readDirRecursive(path.join(__dirname, 'web'));
res.json({ files: directoryTree });
} catch (err) {
console.error('Error reading directory:', err);
res.status(500).send('Error reading directory');
}
return;
});
// POST /save
// Route to save data from experiments
app.post('/save', (req, res) => {
// Output the request body for debugging purposes
console.log(req.body);
if (!req.body.filename || !req.body.data) {
return res.status(500).json({ error: 'Missing filename or data in request body' });
}
// Set path where data will be stored
// Note: OSF expects filename (all lowercase, so that’s what we use)
const filePath = './data/' + req.body.filename;
fs.writeFile(filePath, req.body.data, (err) => {
if (err) {
console.error('Error saving the file:', err);
res.status(500).send('Error saving the data');
} else {
console.log('Data saved successfully');
res.json({
success: true,
filePath: filePath,
});
}
});
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment