diff options
-rw-r--r-- | package.json | 4 | ||||
-rw-r--r-- | src/index.ts | 4 | ||||
-rw-r--r-- | src/public/js/form.js | 21 | ||||
-rw-r--r-- | src/routes/api.ts | 25 | ||||
-rw-r--r-- | src/views/pages/about.ejs | 5 | ||||
-rw-r--r-- | src/views/pages/index.ejs | 2 | ||||
-rw-r--r-- | src/views/partials/head.ejs | 6 |
7 files changed, 33 insertions, 34 deletions
diff --git a/package.json b/package.json index e0a656c..51a54f4 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "build:ci": "npm-run-all clean tsc", "copy-views": "cp -r ./src/views ./dist/views && cp -r ./src/public ./dist/public", "clean": "rm -rf dist", - "dev": "nodemon --watch ./src -e ts,ejs --exec yarn dev:start", + "dev": "nodemon --watch ./src -e ts,ejs,css,js --exec yarn dev:start", "dev:start": "npm-run-all build start", "lint": "eslint --ext .ts,.js ./src --fix", "start": "node dist/index.js", @@ -45,4 +45,4 @@ "repository": "https: //github.com/RosstheRoss/4951w-pendulum", "license": "MIT", "private": true -} +}
\ No newline at end of file diff --git a/src/index.ts b/src/index.ts index bd2c7d5..1bf018f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -15,7 +15,7 @@ const app = express(); // Rate limiting const rateLimiter = rateLimit({ windowMs: 1 * 60 * 1000, // 1 minute - max: 40, // Limit each IP to 100 requests per `window` (here, per 15 minutes) + max: 40, // Limit each IP to 40 requests per `window` (here, per 1 minutes) standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers legacyHeaders: false, // Disable the `X-RateLimit-*` headers }); @@ -30,7 +30,7 @@ const csrf = csurf({ cookie: true }); app.use(helmet()); // The API -app.use('/api', api); +app.use('/api/v1/', api); /* RENDERING */ diff --git a/src/public/js/form.js b/src/public/js/form.js index cfa80fd..7085422 100644 --- a/src/public/js/form.js +++ b/src/public/js/form.js @@ -1,17 +1,18 @@ +// File submit AJAX request document.getElementById('upload').onsubmit = function () { - var data = new FormData(document.getElementById('upload')); - var xhr = new XMLHttpRequest(); - xhr.open('POST', '/api/upload'); - xhr.send(data); + let xhr = new XMLHttpRequest(); + xhr.open('POST', '/api/v1/upload'); + let formData = new FormData(this); + xhr.send(formData); xhr.onreadystatechange = function () { - if (xhr.readyState == 4 && xhr.status == 200) { - var response = JSON.parse(xhr.responseText); - if (response.success) { - document.getElementById('success').style.display = 'block'; + if (xhr.readyState === 4) { + let response = JSON.parse(xhr.responseText); + if (xhr.status === 200) { + console.log(response); } else { - document.getElementById('error').style.display = 'block'; + console.log(response.error); } } }; return false; -}; +};
\ No newline at end of file diff --git a/src/routes/api.ts b/src/routes/api.ts index 4612c16..e360709 100644 --- a/src/routes/api.ts +++ b/src/routes/api.ts @@ -4,22 +4,21 @@ import cookieParser from 'cookie-parser'; import fileUpload, { UploadedFile } from 'express-fileupload'; import slowDown from 'express-slow-down'; +const api = express.Router(); + +// For file uploads +api.use(fileUpload()); // Slow down everything to prevent DoS attacks const speedLimiter = slowDown({ - windowMs: 5 * 60 * 1000, // 15 minutes - delayAfter: 50, // allow 100 requests per 5 minutes, then... + windowMs: 5 * 60 * 1000, // 5 minutes + delayAfter: 50, // allow 50 requests per 5 minutes, then... delayMs: 500 // begin adding 500ms of delay per request above 100: // request # 101 is delayed by 500ms // request # 102 is delayed by 1000ms // request # 103 is delayed by 1500ms // etc. }); - - -const api = express.Router(); - -api.use(fileUpload()); api.use(speedLimiter); // CSRF protection @@ -27,14 +26,14 @@ api.use(cookieParser()); const csrf = csurf({ cookie: true }); api.post('/upload', csrf, (req: Request, res: Response) => { + // Check if there is a file if (!req.files || Object.keys(req.files).length === 0) - return res.status(400).json({ err: 'ENOENT' }); - // Kludge to prevent a compiler error - const file: UploadedFile = req.files.file as UploadedFile; - console.log(file.mimetype); + return res.status(400).json({ error: 'No file uploaded' }); + const file: UploadedFile = req.files.file as UploadedFile; // Kludge to prevent a compiler error + // Check if the file is a python file if (file.mimetype !== 'text/x-python') - return res.status(400).json({ err: 'EINVAL' }); - res.status(200).json({ err: null }); + return res.status(400).json({ error: 'Not a Python file' }); + res.status(200).json({ file: file.name }); }); export default api;
\ No newline at end of file diff --git a/src/views/pages/about.ejs b/src/views/pages/about.ejs index 022354c..2feede5 100644 --- a/src/views/pages/about.ejs +++ b/src/views/pages/about.ejs @@ -4,12 +4,12 @@ <head> <!-- HTML headers information --> <%- include('../partials/head.ejs') %> + <title>About the Remotely Accessible Inverted Pendulum</title> </head> <body> <!-- Get the navbar --> <%- include('../partials/nav.ejs') %> - <title>About the Remotely Accessible Inverted Pendulum</title> <div class="header"> <img src="public/img/site_logo.png" alt="Pendulum logo" width="160" height="130" /> <h1>Remotely Accessible Inverted Pendulum</h1> @@ -28,8 +28,7 @@ <br /> <h1 id="Background">Background</h1> <p> - Our teams developed an inverted pendulum system that could be accessed over a computer network for use by students. The inverted pendulum is a common controls problem used in academia. This problem teaches students concepts of control loops, data filtering, - and machine learning, and web development. + Our teams developed an inverted pendulum system that could be accessed over a computer network for use by students. The inverted pendulum is a common controls problem used in academia. This problem teaches students concepts of control loops, data filtering, and machine learning. </p> <br /> <h1 id="Pendulum_info"> What is an Inverted Pendulum? </h1> diff --git a/src/views/pages/index.ejs b/src/views/pages/index.ejs index 0e6fe15..8b5f044 100644 --- a/src/views/pages/index.ejs +++ b/src/views/pages/index.ejs @@ -11,7 +11,7 @@ <!-- Get the navbar --> <%- include('../partials/nav.ejs') %> <br /> - <h2>Please upload a Python file (.py file extension) onto the Inverted Pendulum.</h2> + <h2>Please upload a Python file (.py file extension) to run on the Inverted Pendulum.</h2> <br /> <br /> <form id="upload" enctype="multipart/form-data"> <input type="hidden" name="_csrf" value="<%= csrfToken %>"> diff --git a/src/views/partials/head.ejs b/src/views/partials/head.ejs index 320f0e6..4a9d76a 100644 --- a/src/views/partials/head.ejs +++ b/src/views/partials/head.ejs @@ -1,6 +1,6 @@ <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> - <link rel="stylesheet" href="public/css/style.css" type="text/css"> - <link rel="icon" href="public/img/site_logo.png" type="image/x-icon">
\ No newline at end of file + <link rel="stylesheet" href="public/css/style.css" type="text/css" /> + <link rel="icon" href="public/img/site_logo.png" type="image/x-icon" />
\ No newline at end of file |