How to extend the response timeout default time? - javascript

I'm having a little problem with thread blocking algorithms.
I have a route that generates a zip with huge size files.
The flow works like this:
GetUrls > ObtainHugeSizeBuffer > GenerateZIP > UploadZIPToCloud
I cannot modify the timeout response default time of 2 minutes with the express-timeout module. I've also been trying to break the loopholes in the .nextTick() function.
I've even tried to look over queueing but I don't think that applies in this situation.
Do you guys have any idea how to expand the response time? - I strictly need to for one route only.

// start the server
const server = app.listen(8080);
// increase the timeout to 4 minutes
server.timeout = 240000;
This is the easiest way to extend server timeout, but it affects everything, not just one method.
In your case (you wan't it only for on specific route):
'use strict';
const ms = require('ms');
const express = require('express');
const router = express.Router();
router.route('/upload-files')
.post(
setConnectionTimeout('12h'),
require('./actions/upload-files').responseHandler
);
function setConnectionTimeout(time) {
var delay = typeof time === 'string'
? ms(time)
: Number(time || 5000);
return function (req, res, next) {
res.connection.setTimeout(delay);
next();
}
}
exports.router = router;
Not my code, found it in this thead: Node Express specific timeout value per route
You need to google better :)

Related

Accessing server-side text file using JavaScript

I am making a website for students to give test... I will be also hosting it. But I want to make the code such that a particular student can give the test only once a day. So, I thought of placing a text (.txt) file on the server and read and write the dates, the student last gave the test. But, I came to know about the fact that JavaScript cannot access server-side files. So, is there a way to do the thing I want to?
Note : I want to do both reading and writing into the file
You'll need to use a client-server model:
Client makes a HTTP request to the server
Server receives the request and reads the file on behalf of the client
Here's a bare-bones example in express:
import express from 'express';
import bodyParser from 'body-parser';
import cookieParser from 'cookie-parser';
import level from 'level';
const app = express();
app.use(cookieParser());
const {Level} = level;
const lastTakenDates = new Level('lastTakenDates', {valueEncoding: 'json'});
const jsonParser = bodyParser.json();
app.post('/start', jsonParser, async (request, response) => {
const username = somehowGetUsername(request.cookies.session);
const now = Date.now();
const lastTaken = await lastTakenDates.get(username);
if (!lastTaken || (lastTaken + 1000 * 60 * 60 * 24) < now) {
await lastTakenDates.put(username, now);
response.status(200).send("OK");
return;
}
response.status(403).send("You can only take the quiz once a day");
});
I am answering my question because I found a very easy way to accomplish the task. Its just simply easy to use PHP. You can write a simple PHP script for handling the file and then activate that script using an AJAX request which can be posted through JQuery. The text to be written can be set as a cookie using javascript and that cookie will be accessed through PHP and the task will be accomplished !!!!
Also, a big thanks to all the sincere effortsof #Richie Bendall to help me

Node / Express race condition on DB operations

I have an express route that needs to retrieve a row from a db, check if a field has a value set and if not set it. The row data then gets sent back to the client.
I know that node runs on a single thread but I/O operations do actually run asynchronously so I think I may have a problem if whilst the first client is waiting to write to db, a second client comes and reads a null value and performs the write a second time.
I can't have this happen as the value written is a shared value that there can only be one of.
Am I correct that this could happen and if so what is a recommended way to handle this?
Thanks.
let express = require('express');
let router = express.Router();
router.post('/getRoomStateByRoomUrl', async (req, res, next) => {
const roomUrl = req.body.room_url;
try {
//READ FROM DB
const roomState = await RoomStateModel.getRoomStateByRoomUrl(roomUrl);
if(!roomState.tokboxSessionID) {
const newSessionID = await TokboxService.createSession();
//WRITE TO DB
await RoomStateModel.setTokboxSessionID(newSessionID);
roomState.tokboxSessionID = newSessionID;
}
res.status(200).json(roomState);
} catch (error) {
next(error);
}
});

Issue with multiple routes in one file - only two out of three work, the last one won't work

I'm working on making an API using express and MySQL. I'm having issues with my routes. I have it in a separate folder, requiring the different controller files and exporting the router at the end. Here's the issue. The last router.get function will not work. I can swap it and whatever is last will not work. I'll get back an empty array. I'm at a loss as to what can be wrong. Here's my code, the routes file:
const express = require('express');
const router = express.Router();
const getEmployeesController = require('../controllers/getEmployees');
const getEmployeesByIdController = require('../controllers/getEmployeesById');
const getEmployeesByFirstNameController = require('../controllers/getEmployeesByFirstName');
router.get('/', getEmployeesController.getEmployees);
router.get('/:id', getEmployeesByIdController.getEmployeesById);
router.get('/:first_name', getEmployeesByFirstNameController.getEmployeesByFirstName);
module.exports = router;
The 'first_name' router worked when it was second, after the '/', but now it won't. Same with the 'id', worked when its second, but not when it's third.
Here's the controller function, one as an example:
const mysql = require('mysql')
const pool = require('../mysql/connection')
const { handleSQLError } = require('../mysql/error')
const getEmployeesById = (req, res) => {
let sql = "SELECT ?? FROM ?? WHERE ?? = ?"
sql = mysql.format(sql, ['*', 'employees', 'emp_no', req.params.id])
pool.query(sql, (err, rows) => {
if (err) return handleSQLError(res, err)
return res.json(rows);
})
}
module.exports = { getEmployeesById };
/:first_name and /:id match the exact same URLs so only the first one you register is going to get all the matching URLs. They both match /anything.
You really can't define routes like that. There's no way Express knows which route handler you want to use with /anything is the requested URL.
Instead, you need to define a route structure where those two types of URLs are different and you can design a route handler that will uniquely catch each one. I personally don't ever use top level wildcard routes like this because they match every top level URL and they prohibit you using top level URLs for any other purpose in your site.
Instead, you might change your URL design to do this:
router.get('/id/:id', ...)
router.get('/firstname/:firstname', ...);
Then, it would be completely clear from the URL what type of resource was being requested and each route would match only the appropriate URLs.

How express.route determined route

I'm start learning about Node.js (with Express.js) and React.js. So I have some question about Express Router
Let's see my part of code
server.js
const app = express();
const apiRouter = require("./Routes/apiRoute");
app.use("/api", apiRouter);
app.listen(3000, () => {
console.log("application run on port " + 3000);
});
/Routes/apiRoute.js
const express = require("express");
const router = express.Router();
router.route("/user/:id")
.post((req,res)=>{
// Do something
})
router.route("/user/status")
.post((req,res) => {
// do something
});
So. My question is How express route determined which method to go.
From my example code if I send POST request like this http://localhost:3000/api/user/status
express router will see status is :id right ?
in the otherhand if I move route for /user/status up it's will go as I expected right ?
Thank you.
Express matches route in chronological order.
Express starts to match URL with the first route that has been declared in the script and then moves to the next if it does not match. This is because of the fact that Express is a Javascript framework. The function you pass to a route i.e. (req, res) => {...} is actually a js callback function that would be called if the user hit the route matching the corresponding string declared. And in Javascript, the callback that is set first for an event is called first because these callbacks are maintained in a queue. A queue is FIFO as we all know.
If you want both "/user/:id" and "/user/status" to work, you would have to declare the later one first in your code and then the first one.

Limiting the number of request by user in any given hour [Nodejs]

I'm building a server side application using Nodejs and Express and for some reason i was thinking about how to limit the number of request by user in a fixed amount of time to prevent hackers from spamming and trying to break down the server.
I am a little concerned with people abusing/spamming the available services with a large number of requests.
so is there any idea about how to build an express middleware that allows me to control the number of request send by specific user based on his access_token
the questions are:
1) how to build this middleware and what is the best way to do this?
2) is there any module that can do the job?
3) is there any other solution or a structure that allows me to secure my server against this kind of attack?
All suggestions are welcome.
There's a bunch of existing modules out there, but this seems to be what you're looking for:
https://www.npmjs.com/package/tokenthrottle
In the Node community there is almost always a module to do all or part of what you're looking for. You almost never have to reinvent the wheel.
Just collect the request ips/whatever in a Map that keeps a counter running. When the counter hits a certain just show an error page:
const app = Express();
const ips = new Map;
const limit = 20;
app.use((req, res, next) => {
const count = ips.get(req.ip) || 0;
if(count < 20){
ips.set(req.ip, count + 1);
next();
} else {
res.end("spam filter activated, sorry :(");
}
});
// ... your endpoints
app.listen(80);
That will block certain ips until you restart the server. However you could also reset the Map at a certain interval:
setInterval(() => ips.clear(), 60 * 60 * 1000);

Categories