I'm currently working on a research project for my CSCI class that requires studying cyber security in great detail. Replicating what a phishing site might look like is one of the goals I've set for myself. But I'm having trouble understanding how to add information to the URL and add it to the MongoDB collection. The URL that will put the email address and password into the collection is "https://URL.com/insert?email=EMAIL#gmail.com&password=123456." I am a complete novice when it comes to creating APIs, thus I need some assistance.
I have so far made a simple form and a js file to insert the form's data into MongoDB, but I'm unable to tweak it such that it accepts parameters for URLs instead.
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap#3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<h1>To MongoDB</h1>
<form class="container" method="post" action="/">
<div class="form-group">
<input class="form-control" name="email">
</div>
<div>
<textarea class="form-control" name="password"></textarea>
</div>
<button>ADD</button>
</form>
</body>
</html>
JS:
const express = require('express');
const app = express();
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended: true}));
mongoose.connect("mongodb+srv://<USERNAME>:<PASS>#<CLUSTER>.mongodb.net/Data", { useNewUrlParser: true}, { useUnifiedTopology: true})
const dataSchema = {
email: String,
password: String
}
const Data = mongoose.model("Data", dataSchema);
app.get("/", function(req, res) {
//res.send("express is working");
res.sendFile(__dirname + "/index.html");
})
//app.post
app.post("/", function(req, res){
let newData = new Data({
email: req.body.email,
password: req.body.password
});
newData.save();
res.redirect("/");
})
app.listen(3000, function() {
console.log("server is running on port : 3000");
})
You can access the url query parameters using req.query.
If your URL is https://URL.com/insert?email=EMAIL#gmail.com&password=123456
you can access the parameters with req.query.email and req.query.password
To handle blank inputs, you have to add a check
A relevant code snippet would be:
app.get("/insert", function(req, res){
if (!req.query.email || !req.query.password) {
return res.status(400).send("failed");
}
let newData = new Data({
email: req.query.email,
password: req.query.password
});
newData.save();
res.send("success");
});
Related
I would like to know how to pass the "myBlogs" variable that I have in my Node.js file ("server.js") to a frontend JavaScript file ("blogs.js"). Once I have access to it in the JS file, I would then map through the array that is stored in that variable and output a template for each blog in an HTML file ("blogs.html").
Later, the idea is to get the blogs data from a database (MongoDB) instead of having them hard coded. I have seen how to do this with Express and a templating engine (EJS), but as practice for a beginner, I would like to understand the basics of if and how it can be done without these tools.
My file structure:
blogs.css
blogs.html
blogs.js
server.js
server.js:
const http = require("http");
const fs = require("fs");
const myBlogs = [
{
title: "My first blog",
author: "John",
},
{
title: "My second blog",
author: "Mike",
},
];
const server = http.createServer((req, res) => {
console.log("request made");
// set header content type
let path = "";
switch (req.url) {
case "/blogs.css":
path += "blogs.css";
res.setHeader("Content-Type", "text/css");
break;
case "/blogs.js":
path += "blogs.js";
res.setHeader("Content-Type", "text/javascript");
break;
default:
path += "blogs.html";
res.setHeader("Content-Type", "text/html");
}
// send file
fs.readFile(path, (err, data) => {
if (err) {
console.log(err);
res.end();
} else {
res.write(data);
res.end();
}
});
});
server.listen(3000, "localhost", () => {
console.log("listening for requests on port 3000");
});
blogs.js:
const container = document.querySelector("div")
const html = myBlogs.map(blog => (
`<h2>${blog.title}</h2>
<p>${blog.author}</p>`
))
container.innerHTML = html;
blogs.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="blogs.css" />
</head>
<body>
<div></div>
<script src="blogs.js"></script>
</body>
</html>
blogs.css:
p {
color: red;
}
P.S.: If such an approach is completely wrong, could you please explain the correct way this would be done without the use of Express and a templating engine?
server.js
// send file
fs.readFile(path, "utf8", (err, data) => {
if (err) {
console.log(err);
res.end();
} else {
res.write(data.replace(/%MY_BLOGS%/g, JSON.stringify(myBlogs)));
res.end();
}
});
blogs.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="blogs.css" />
<script>
var myBlogs = %MY_BLOGS%;
console.log(myBlogs);
</script>
</head>
<body>
<div></div>
<script src="blogs.js"></script>
</body>
</html>
This is incredibly hacky and not a good practice at all. It basically just finds %MY_BLOGS% and interpolates a JSON encoded object. Since JSON is valid JS, it will be directly accessible in your client side JS. You can now access myBlogs in blogs.js since it's a global variable.
Instead of using HTTP you could use something like express.js with ejs to pass backend data to front end.
npm i express ejs
Now you have express.js and ejs installed write some simple code like this:
server.js
const express = require('express')
// Create new server
const app = express()
// This will read read all the files in static and add them eg;
// static/style.css would now be able to do localhost:3000/style.css
app.use(express.static("static"))
// Set the view engine from text to ejs
app.set('view engine', 'ejs')
// app.get means you are using the get method on the url "/"
app.get('/', (req,res) => {
// res.render is the method for ejs
// res.render(file, options)
res.render('blogs', {
// Now on the front end you would be able to get data
data: example
})
})
// Start listening on X port
app.listen(3000, () => {
console.log("Listening on port 3000")
})
views/blogs.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="blogs.css" />
</head>
<body>
<div>My blogs <%= locals.data %></div>
</body>
</html>
In ejs you use <% %> to run something and <%= %> to output something
Your project structure would look something like this:
static
blogs.css
blogs.js
views
blogs.ejs
server.js
You should read up on express.js and ejs
I'm trying to make a simple to do list and I can't figure out the "delete" button. I don't get any errors, the buttons just doesn't do anything. I tried a lot of things but just can't seem to get it working. I'm not sure if the problem is with form action in the ejs file or with the app.delete in my index.js or both. Thank you in advance!
ejs file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>To Do List</title>
</head>
<body>
<h1>To Do List</h1>
<form action="/todo" method="post">
<input type="text" name="task">
<button>Add</button>
</form>
<ul>
<% for(let c of todos) { %>
<li>
<%= c.task %>
<form action="/todo/<%=c.id%>?_method=DELETE" method="POST"><button>Delete</button></form>
<%= c.id%>
</li>
<% } %>
</ul>
</body>
</html>
index.js file:
const express = require('express');
const app = express();
const path = require('path');
const methodOverride = require('method-override');
const { v4: uuid } = require('uuid');
uuid();
app.use(methodOverride('_method'));
app.use(express.urlencoded({ extended: true }));
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
let todos = [
{
id: uuid(),
task: '1st task, testing'
}
]
//TO DO INDEX
app.get('/todo', (req, res) => {
res.render('todo', { todos });
})
//CREATE NEW TASK
app.post('/todo', (req, res) => {
const { task, id } = req.body;
todos.push({ task, id: uuid() });
res.redirect('todo')
})
//DELETE TASK
app.delete('/todo/:id', (req, res) => {
const { id } = req.body;
todos = todos.filter(c => c.id !== id);
console.log(todos);
res.redirect('/todo')
})
app.listen(3000, () => {
console.log('LISTENING ON PORT 3000')
})
You have configured the delete route in your express app with method type DELETE that is app.delete(…), but in your html form
<form action="/todo/<%=c.id%>?_method=DELETE" method="POST">
The method is mentioned as POST. So express is not accepting it.
Form in html allows only GET and POST request.
You’ll need to trigger those delete api calls using fetch api or jquery or ajax.
Also i am not sure why that _method=DELETE is written in form action. According to me it not need there if your frontend is jinja/Django. If it’s something else then I’m not sure.
To get more insights about why it isn’t working, open the network tab in the browsers console and click your button. It should send a network call to you backend and you should be able to see there why backend isn’t doing anything for that call.
SOLVED IT
I just had to change const { id } = req.body; to const { id } = req.params;
I'm hosting a web app on localhost:3000 via NodeJS (with MySQL database via WAMP). Front end has a button to insert a record into a MySQL database table (called tblbacktrack). It runs the query as expected exactly 6 times, then stops working altogether, without an error or crash. 6 times, every time. If I change the query to a delete, same problem: 6 deletions is all I get until I refresh the page via the browser.
App2.js:
const express = require('express');
const mysql = require('mysql');
const multer = require('multer');
const upload = multer({ dest: 'uploads/' });
// create connection
const db = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '',
database: 'journey_test'
})
// connect to mysql
db.connect(err => {
if(err) {
throw err
}
console.log('MySQL Connected');
})
const app = express()
app.use(express.static('public'));
app.set('view engine', 'ejs');
// This pulls index.ejs to the root folder location of the site.
app.get('/', function (req, res) {
res.render('index2');
});
app.post('/deleteBtDb/', upload.none(), function (req, res, next) {
// let sql = `DELETE from tblbacktrack limit 1`
let sql = `INSERT into tblbacktrack (btEntryNum, btDate) values ('E: 19810809', '2021-05-05');`
let query = db.query(sql, (err, results) => {
if(err) {
throw err
}
})
})
// Let the console know that the server has started on port 3000
app.listen('3000', () => {
console.log('Server Started on port 3000')
})
index2.ejs:
<!DOCTYPE html>
<html>
<head>
<link href="/css/style.css" rel="stylesheet" type="text/css" media="all" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
</head>
<body>
<div class="container">
<div class="Header">
</div>
<div class="Footer"></div>
<div class="Middle">
<div id="Middle-Center" class="Middle-Center"></div>
<div id="Middle-Left" class="Middle-Left"></div>
<div id="Middle-Right" class="Middle-Right"><%- include ('../views/middle-right'); %></div>
</div>
</div>
</body>
Middle-right.ejs:
<div><button onclick="deleteBtDb()">Click me</button></div>
<script>
function deleteBtDb() {
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "./deleteBtDb/", true);
xhttp.send();
}
</script>
If I run the same queries in phpMyAdmin, they work, and I can definitely run them successfully more than 6 times there. If I set up a for loop in app2.js, such that a single click of the index2.ejs button should insert 10 new records, it successfully inserts 10 new records. Please help! I don't know how to further troubleshoot this.
Solved it!
I wasn't using a "res" object in there. Added "res.status(201).json()", and it's all better now.
app.post('/deleteBtDb/', upload.none(), function (req, res, next) {
let sql = `DELETE from tblbacktrack order by btID ASC limit 1`
let query = db.query(sql, (err, results) => {
if(err) {
throw err
}
})
res.status(201).json();
})
I'm trying to make a very simple return coming from Node.js to Ajax. I'm using Express.js to make this possible.
I have code from the previous route that I did in order to write and manage JSON files and it works just fine.
The problem comes from the second route that always throws an error when I'm trying to make it return something with the JQuery ajax success method. It is the most simple form of send that I found but still doesn't work.
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test 2</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
</head>
<body>
Cod: <input type="text" name="cod" id="cod">
Text: <input type="text" name="text" id="text">
<button id="boton">PRUEBA</button>
<button id="getText">GET TEXT</button>
<script>
$('#boton').click(function() {
let cod=$('#cod').val();
let text=$('#text').val();
console.log(cod);
console.log(text);
$.ajax({
type: 'POST',
data: {
cod: cod,
text: text,
},
url: 'http://localhost:1337/prueba'
});
});
$('#getText').click(function() {
$.ajax({
type: 'POST',
data: {
},
success: (result) => {
console.log(result);
},
error: (result) => {
console.log('ERROR');
},
url: 'http://localhost:1337/getText'
});
});
</script>
</body>
</html>
app.js
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/prueba', function(req, res) {
// ... First Route. The code here works just fine so I don't add it here.
});
app.post('/getText', function(req, res) {
let text = "Hola mundo";
console.log(text);
res.send(text);
});
app.listen(1337, () => console.log('Started server at http://localhost:1337!'));
When you click the 'GET TEXT' Button it enters inside the '/getText' route in app.js and console.logs the text on the node.js terminal so that's not the issue.
The issue seems to come from the res.send() function.
In the browser console it logs 'ERROR' as it appears in the ajax error method associated to the 'GET TEXT' Button. I can't find a way to make it return success.
Could anyone help me? I'm so stuck with this project for work.
looks like a CORS issue... do you serve index.html from the same location?
It works serving index.html from node
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/prueba', function(req, res) {
// ... First Route. The code here works just fine so I don't add it here.
});
app.post('/getText', function(req, res) {
let text = "Hola mundo";
console.log(text);
res.send(text);
});
app.get('*', function (req, res) {
res.sendFile('index.html', {root: '.'})
})
app.listen(1337, () => console.log('Started server at http://localhost:1337!'));
There are several options for node/express, e.g. express middleware
I'm pretty new to using express and the responses here on StackOverflow have been very confusing. What I have is JSON data that I am retrieving using app.get(). What I want is to modify this data and send it to my index.html file. I know that I can simply use the fetch function to get the data in my index file from the get endpoint but I need to use both the app.post() and app.put() function.
I'm having trouble understanding your question.
Here's a sample code that uses axios and plain vanilla javascript to get some data from backend and then in frontend, you can modify the data. You can replace axios for fetch and it'll still work.
app.js
const express = require("express");
const bodyParser = require("body-parser");
const port = 8000;
const app = express();
/* Simulating data, a better approach would be to use some storage like MySQL... */
let data = {
name: "Elon Musk",
age: "48",
height: "1.88m"
};
app.use(express.static("public"));
/* body-parser is required so the server can parse the data sent. */
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
/* get the data... */
app.get("/api/mydata", function(req, res) {
return res.json(data);
});
/* this is where the client will post the data */
app.post("/api/newdata", function(req, res) {
data.name = req.body.name;
data.age = req.body.age;
return res.json("OK!");
});
app.listen(port, function() {
console.log("Listening on 8000");
});
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<input type="text" id="name" placeholder="Name..." value="">
<input type="text" id="age" placeholder="Age..." value="">
<button type="button" id="setValues">Change values!</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.19.0/axios.js"></script>
<script>
window.addEventListener("load", function() {
axios.get("/api/mydata").then(function(res) {
document.getElementById("name").value = res.data.name;
document.getElementById("age").value = res.data.age;
})
});
document.getElementById("setValues").addEventListener("click", function() {
axios.post("/api/newdata", {
name: document.getElementById("name").value,
age: document.getElementById("age").value
}).then(function(res) {
console.log("Sent!");
})
})
</script>
</body>
</html>
If you have any questions, let me know!