aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Strapp <matt@mattstrapp.net>2022-02-11 11:30:40 -0600
committerMatt Strapp <matt@mattstrapp.net>2022-02-11 11:30:40 -0600
commite9cc00f8947d3aea0f802a8b8d7f2e406c3fcb1f (patch)
tree301a68cd34c73ce5ea2d158e4a4e463d183d0736
parentDo a bunch of random things (still no feature parity) (diff)
downloadee4511w-web-e9cc00f8947d3aea0f802a8b8d7f2e406c3fcb1f.tar
ee4511w-web-e9cc00f8947d3aea0f802a8b8d7f2e406c3fcb1f.tar.gz
ee4511w-web-e9cc00f8947d3aea0f802a8b8d7f2e406c3fcb1f.tar.bz2
ee4511w-web-e9cc00f8947d3aea0f802a8b8d7f2e406c3fcb1f.tar.lz
ee4511w-web-e9cc00f8947d3aea0f802a8b8d7f2e406c3fcb1f.tar.xz
ee4511w-web-e9cc00f8947d3aea0f802a8b8d7f2e406c3fcb1f.tar.zst
ee4511w-web-e9cc00f8947d3aea0f802a8b8d7f2e406c3fcb1f.zip
Finish upload API endpoint
Signed-off-by: Matt Strapp <matt@mattstrapp.net>
-rw-r--r--package.json4
-rw-r--r--src/index.ts4
-rw-r--r--src/public/js/form.js21
-rw-r--r--src/routes/api.ts25
-rw-r--r--src/views/pages/about.ejs5
-rw-r--r--src/views/pages/index.ejs2
-rw-r--r--src/views/partials/head.ejs6
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