Download backend/server.js from essay003/prmsu: direct link, hf CLI and curl.
- Browser
- Download file 2.7 kB
-
https://huggingface.co/spaces/essay003/prmsu/resolve/main/backend/server.js
- Command line
-
hf download hf://spaces/essay003/prmsu/backend/server.js
-
curl -L -o server.js https://huggingface.co/spaces/essay003/prmsu/resolve/main/backend/server.js
2.7 kB
| import express from "express"; | |
| import cors from "cors"; | |
| import dotenv from "dotenv"; | |
| import fs from "node:fs"; | |
| import path from "node:path"; | |
| import multer from "multer"; | |
| import rubricRoutes from "./routes/rubricRoutes.js"; | |
| import essayRoutes from "./routes/essayRoutes.js"; | |
| import authRoutes from "./routes/authRoutes.js"; | |
| import evaluationRoutes from "./routes/evaluationRoutes.js"; | |
| dotenv.config({ quiet: true }); | |
| const app = express(); | |
| // Behind a host's proxy (Hugging Face, Render) the client address arrives in | |
| // X-Forwarded-For; without this every visitor would share the proxy's IP for rate limits. | |
| app.set("trust proxy", true); | |
| // Only the website itself may call the API from a browser. CORS_ORIGINS lists the allowed | |
| // sites, comma-separated; locally it defaults to the Vite dev server. When the website is | |
| // served by this same server (the hosted setup), requests are same-origin and CORS does | |
| // not apply at all. | |
| const allowedOrigins = (process.env.CORS_ORIGINS || "http://localhost:5173,http://127.0.0.1:5173") | |
| .split(",") | |
| .map((o) => o.trim().replace(/\/+$/, "")) | |
| .filter(Boolean); | |
| app.use( | |
| cors({ | |
| origin: (origin, cb) => cb(null, !origin || allowedOrigins.includes(origin)), | |
| }) | |
| ); | |
| app.use(express.json({ limit: "200kb" })); | |
| app.use("/api/auth", authRoutes); | |
| app.use("/api", rubricRoutes); | |
| app.use("/api", essayRoutes); | |
| app.use("/api", evaluationRoutes); | |
| // Hosted, the built website is served from here too: one address, no CORS, one process. | |
| const frontendDist = process.env.FRONTEND_DIST | |
| ? path.resolve(process.env.FRONTEND_DIST) | |
| : null; | |
| if (frontendDist && fs.existsSync(path.join(frontendDist, "index.html"))) { | |
| app.use(express.static(frontendDist)); | |
| // Any non-API path is the single-page app. | |
| app.get(/^\/(?!api\/).*/, (req, res) => res.sendFile(path.join(frontendDist, "index.html"))); | |
| } else { | |
| app.get("/", (req, res) => { | |
| res.send("Essay AI Backend Running"); | |
| }); | |
| } | |
| // Oversized uploads and oversized JSON bodies become readable messages, not stack traces. | |
| app.use((err, req, res, next) => { | |
| if (err instanceof multer.MulterError && err.code === "LIMIT_FILE_SIZE") { | |
| return res.status(413).json({ error: "File too large", message: "The photo is too large. Take it again at a lower resolution." }); | |
| } | |
| if (err?.type === "entity.too.large") { | |
| return res.status(413).json({ error: "Too large", message: "The answer is too long." }); | |
| } | |
| if (err?.message === "Only image files can be uploaded") { | |
| return res.status(400).json({ error: "Wrong file type", message: err.message }); | |
| } | |
| next(err); | |
| }); | |
| const PORT = process.env.PORT || 3000; | |
| app.listen(PORT, () => { | |
| console.log(`Server running on port ${PORT}`); | |
| }); | |