Upload files to "/"
This commit is contained in:
8
Dockerfile
Normal file
8
Dockerfile
Normal 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
8
compose.yml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
services:
|
||||||
|
signup:
|
||||||
|
build: .
|
||||||
|
ports:
|
||||||
|
- "8080:3000"
|
||||||
|
volumes:
|
||||||
|
- ./data:/app/data
|
||||||
|
restart: unless-stopped
|
||||||
48
server.js
Normal file
48
server.js
Normal 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}`);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user