NodeJS Projects¶
Simple Webpage with Vanilla Node¶
Inefficient Webpage implementation¶
- Below is an implementation of a Node web server that will respond to requests.
- However, this implementation is not efficient and elegant as we will need to create multiple if-else cases in the server object which will clutter the code.
//import libraries
const http = require('http');
const path = require('path');
const fs = require('fs');
// declare port to listen on - either environment var or pre-defined
const PORT = process.env.port || 5000;
//create server object
const server =http.createServer((req,res)=>{
//basic request handling
if (req.url == '/'){
fs.readFile(path.join(__dirname,'public','hello.html'),
(err,content)=>
{
if (err) throw err;
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(content);
})
}
});
// start server listener
server.listen(PORT, () => console.log(`Server running on port ${PORT}`));
Slightly Better Implementation¶
-
Below is a slightly better implementation of the web server but still not the best. It can be more elegant and cleaner by more abstraction.
//import libraries const http = require('http'); const path = require('path'); const fs = require('fs'); // declare port to listen on - either environment var or pre-defined const PORT = process.env.port || 5000; const server =http.createServer((req,res)=>{ //buildFilePath let filePath = path.join( __dirname, 'public', req.url === '/' ? 'hello.html' : req.url); // Get File Extension let extname = path.extname(filePath); // Set Content-Type let contentType = 'text/html'; //Check for ext and set Content-type switch(extname){ case '.js': contentType = 'text/javascript'; break; case '.css': contentType = 'text/css'; break; case '.json': contentType = 'application/json'; break; case '.png': contentType = 'image/png'; break; case '.jpg': contentType = 'image/jpg'; break; } //Read and serve file fs.readFile(filePath,(err,content) => { if(err) { //Handle 404 Error if(err.code == 'ENOENT'){ fs.readFile(path.join(__dirname,'public','404.html'), (err,content)=> { res.writeHead(200, {'Content-Type': 'text/html'}); res.end(content, 'utf8'); }) } // Some other server errors else{ res.writeHead(500); res.end(`Server Error: ${err.code}`); } } //Success Response if resource is found else{ res.writeHead(200,{'Content-type':contentType}); res.end(content,'utf8'); } }); }); server.listen(PORT, () => console.log(`Server running on port ${PORT}`));
-
A simple webpage project will end here. Usually framework like ExpressJS is used to create a simple webserver and using frameworks will make the process easier and cleaner.
Adding of Portswigger Academy Lab names to Trello board via Trello REST API Automation with NodeJS¶
- The inspiration of this project comes from the need to automate adding of cards into trello.
- Adding of cards using the web application is too slow and repititive as we have 200 over cards name to add.
- References :
Cleaning Data from Portswigger¶
- We looked into the HTML of the portswigger website and noticed that the title is an HTML anchor.
- Hence, with the help of curl and grep we extract only all the anchor texts that contains the lab links.
- We also noticed that all the labs will start with
lab-
in the URL.
curl https://portswigger.net/web-security/all-labs | grep 'lab-' > out.txt
- We wanted to modify the marker "EXPERT", "PRACTITIONER" and "APPRENTICE" to "E","P","A" respectively and still have the lab title.
- We then make use of cyberchef to get the cleaned ouput. The Cyberchef recipe is as below :
[{"op":"Strip HTML tags","args":[true,true]},{"op":"Find / Replace","args":[{"option":"Regex","string":"APPRENTICE"},"\\r|A|",true,false,true,false]},{"op":"Find / Replace","args":[{"option":"Regex","string":"PRACTITIONER"},"\\r|P|",true,false,true,false]},{"op":"Find / Replace","args":[{"option":"Regex","string":"EXPERT"},"\\r|E|",true,false,true,false]},{"op":"Remove whitespace","args":[false,false,true,true,true,false]}]
Sample output of cleaned data :
Getting the required Information from Trello¶
- Based on the trello references above, we know that we will need four variables:
idlist
: ID of the list we want to add tokey
: API Key for Trellotoken
: Server Token for Trelloname
: Name of the card to be added
Node.JS Code¶
- The idea would be to create a
add_card
function that takes in the name to be added in afunction.js
file - Then, using a foreach loop in
index.js
read the text file and pass the variable into theadd_card
function in the iteratively. - The solution below will result in "ERROR 429"., as there is rate limiting on Atlassian end
- Ideally we will need to create a promisified
sleep
function that can be awaited. (Maybe Version 2?)
Index.js¶
import { add_card,syncReadFile } from './functions.js';
var names = syncReadFile('o.txt','utf-8');
names.forEach(name => add_card(name));
functions.js¶
import fetch from 'node-fetch';
export async function add_card(card_name){
try {
const response = await fetch('https://api.trello.com/1/cards?'+
'idList=[list_id]&' +
'key=[API_KEY]&' +
'token=[API_Token]&' +
'name=' + card_name.toString(), {
method: 'POST',
headers: {
'Accept': 'application/json'
}
});
console.log(
`Response: ${response.status} ${response.statusText}`
);
const text = await response.text();
return console.log(text);
} catch (err) {
return console.error(err);
}
}
export function syncReadFile(filename) {
const contents = readFileSync(filename, 'utf-8');
const arr = contents.split(/\r?\n/);
console.log(arr);
return arr;
}
Real Time Markdown Editor (Re-make)¶
- The Sample Project is a remake of this this project real-time markdown viewer from repo that teaches coding through projects. This project is a collaborative markdown editor which allows multiple users to edit and view the same markdown together in realtime.
- The old project is using vulnerable dependency (ShareJS) and redis server which in our implementation we do not want to use any of these. As such, there are some differences as compared to the original implementation.
- We will base our project on this repo which is a WYSIWYG markdown editor and build the collaboration portion from here.
- ExpressJS and EJSwill be the main dependencies used in this project.
Initialising Project¶
mkdir RTMDEditor
code RTMDEditor
npm init
npm install express ejs
{WIP}