Upload files to "/"

This commit is contained in:
2025-11-02 16:01:21 +00:00
commit c0aa16ff2f
3 changed files with 64 additions and 0 deletions

8
Dockerfile Normal file
View File

@@ -0,0 +1,8 @@
FROM node:20-alpine
WORKDIR /app
COPY server.js ./
COPY public ./public
RUN mkdir -p data && chown -R node:node /app
USER node
EXPOSE 3000
CMD ["node","server.js"]

8
compose.yml Normal file
View File

@@ -0,0 +1,8 @@
services:
signup:
build: .
ports:
- "8080:3000"
volumes:
- ./data:/app/data
restart: unless-stopped

48
server.js Normal file
View File

@@ -0,0 +1,48 @@
import { createServer } from 'http';
import { appendFile, mkdir, readFile, stat } from 'fs/promises';
import { existsSync, createReadStream } from 'fs';
import { resolve, extname } from 'path';
const PORT = process.env.PORT || 3000;
const HOST = '0.0.0.0';
const PUBLIC_DIR = resolve('./public');
const DATA_DIR = resolve('./data');
const CSV = resolve(DATA_DIR, 'signups.csv');
const emailSet = new Set();
const mime = { '.html':'text/html','.js':'application/javascript','.css':'text/css' };
async function ensureFile() {
await mkdir(DATA_DIR, { recursive:true });
if(!existsSync(CSV)) await appendFile(CSV, 'timestamp,email\n');
}
function validEmail(e){return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(e);}
async function serveFile(path, res){
try{
const st=await stat(path);
res.writeHead(200,{'Content-Type':mime[extname(path)]||'text/plain'});
createReadStream(path).pipe(res);
}catch{res.writeHead(404).end('Not found');}
}
createServer(async (req,res)=>{
if(req.url==='/api/subscribe' && req.method==='POST'){
let body='';for await(const c of req)body+=c;
try{
const {email}=JSON.parse(body);
if(!validEmail(email)){res.writeHead(400).end('Invalid');return;}
if(emailSet.has(email)){res.writeHead(200).end('OK');return;}
const line=`${new Date().toISOString()},${email}\n`;
await appendFile(CSV,line);emailSet.add(email);
res.writeHead(200).end('Saved');
}catch{res.writeHead(500).end('Error');}
return;
}
const path = req.url==='/'?resolve(PUBLIC_DIR,'index.html'):resolve(PUBLIC_DIR,req.url.slice(1));
serveFile(path,res);
}).listen(PORT,HOST,async()=>{
await ensureFile();
console.log(`Running on http://${HOST}:${PORT}`);
});