NodeJS - AJAX POST 404 (Not Found) - node.js

I am trying to send values from one file to another on click of items displayed.
While doing so, I am getting the error:
POST http://localhost:4000/todo/addToCart 404 (Not Found) jquery-3.3.1.js:9600
My app.js file:
//More codes above to set-up express and all
app.use(express.static('./public'));
todoController(app); //give todocontroller the reference to express
app.listen(4000); //listen on a port
console.log('server is running');
Controller:
module.exports = function(app) {
app.get('/todo', function(req, resp) {
Todo.find({}, function(err, data) {
if (err) throw err;
console.log('get method');
resp.render('todo', {
todos: data
});
});
});
//Few More Code
app.post('/todo', urlencodedParser, function(req, resp) {
console.log('post method');
resp.render('addToCart', {
data: req.body
});
});
};
Model for data interaction:
$('li').on('click', function() { //when user clicks on an item in the list
var item = $(this).text().replace(/ /g, "-"); //traps the item user clicked on
alert(item);
$.ajax({
type: 'POST',
url: '/todo/addToCart', //+item append that item to the url
success: function(item) {
location.reload(); //refresh the page
}
});
});
Parent ejs:
<div id="todo-table">
<form id="todoForm" method="post" action="/todo">
<input type="text" name="item" placeholder="Add new Item..." required />
<button type="submit">Add Item</button>
<ul>
<% for (var i=0;i<todos.length; i++){ %>
<li>
<%=todos[i].item%>
</li>
<% } %>
</ul>
</form>
</div>
Child ejs(to which I need to re-direct):
<div id="itemSelect">Selected Item:
<form id="addToCart" method="post" action="/addToCart">
<button type="submit" id="btnCheckOut">Check out</button>
<%=data.item%>
</form>
</div>
Please help. I am new, kindly point out my mistake.
Many thanks.

The route you created on your nodejs server here:
app.post('/todo', urlencodedParser, function (req, resp) {
console.log('post method');
resp.render('addToCart', { data: req.body });
});
Matches all the POST requests made to the /todo endpoint, not the /todo/addToCart which doesnt exist. This is why you obtain a 404.
Your ajax request should be like so:
$('li').on('click', function () {
var item = $(this).text().replace(/ /g, "-");
alert(item);
$.ajax({
type: 'POST',
url: '/todo', // 'addToCart' has been removed from the path
success: function (item) {
location.reload();
}
});
});

Related

response.writeHead(302) in NodeJS not redirecting in async function callback

Below is a snippet of my NodeJS server code.
async function handleLoginReq(req, res) {
let queryDB = `
SELECT password FROM faculty_information
WHERE email='${userInfo["user-email"]}';
`;
try {
const dbres = await client.query(queryDB);
if (dbres.rows.length !== 0) {
if (dbres.rows[0].password === '') {
const errVal = 'Please register yourself correctly';
res.writeHead(302, {
'Location': `/login_page/loginPage.html?error=${encodeURIComponent(errVal)}`
});
res.end();
client.end();
} else if (userInfo["user-password"] === dbres.rows[0].password) {
res.writeHead(302, {
'Location': '/experiment_page/index.html'
});
res.end();
client.end();
} else {
const errVal = 'Incorrect password or email address';
res.writeHead(302, {
'Location': `/login_page/loginPage.html?error=${encodeURIComponent(errVal)}`
});
res.end();
client.end();
}
} else {
const errVal = 'Please sign up';
console.log(errVal);
res.statusCode(302);
res.setHeader('Location', `/login_page/loginPage.html?error=${encodeURIComponent(errVal)}`)
//res.writeHead(302, { 'Location': `/login_page/loginPage.html?error=${encodeURIComponent(errVal)}` });
res.end();
client.end();
}
} catch (err) {
res.writeHead(500);
res.end("Internal server error");
client.end();
}
}
handleLoginReq(req, res);
The client.query() function is a asynchronous function. However, none of the res.writeHead(302)'s are working inside the callback of this function. A res.writeHead(302) does work if I add it below the function call of handleLoginReq(req, res);.
handleLoginReq(req, res);
// Below redirect works
res.writeHead(302, { 'Location': '/experiment_page/index.html' });
res.end();
The above code runs when a form is submitted on /login_page/loginPage.html.
Instead of redirecting the user to either /experiment_page/index.html or back to /login_page/loginPage.html?error=something with a URL parameter, it just reloads the page to /login_page/loginPage.html.
Below is the HTML for this page.
<!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">
<link rel="stylesheet" href="/login_page/css/loginStyles.css">
<script src="/login_page/js/labelChange.js" defer></script>
<script src="/login_page/js/redirectSignUp.js" defer></script>
<script src="/login_page/js/loginValidation.js" defer></script>
<title>DigiChit - The Online Chit System | Login</title>
</head>
<body>
<nav class="navbar">
<ul>
<li><h1>DigiChit</h1></li>
<li>Home</li>
<li>About</li>
</ul>
</nav>
<div class="login-info">
<form method="POST" class="form">
<img src="/images/avatar.png" id="avatar" alt="avatar">
<h2>Login</h2>
<div class="input-group">
<input type="email" name="user-email" id="user-email" required>
<label for="user-email">Email</label>
<span id="email-error"></span>
</div>
<div class="input-group">
<input type="password" name="user-password" id="user-password" required>
<label for="user-password">Password</label>
<span id="general-error"></span>
<button type="submit" class="submit-btn" id="login-button">Login</button>
<button type="submit" class="submit-btn" id="sign-up">SignUp</button>
Forgot Password?
</div>
</form>
</div>
</body>
</html>
None of the client side JS scripts are interfering with the process either. I did put console.log()'s in all of the other conditions, and there are no clashes either where many res.writeHead() are running simultaneously.
If anyone can find why this is happening?
I tried to use res.setHeader() and res.statusCode() instead of res.writeHead() to see if anything changed, and nothing happened. I tried using promises instead of async/await and that changed nothing either.
###################################
EDIT (Updated with async/await syntax)
###################################
Here is the server code snippet containing more info on where the function is located.
const server = https.createServer(options, async function (req, res) {
// For form submissions
if (req.method.toLowerCase() === "post") {
let body = '';
req.on("data", (chunk) => {
body += chunk.toString();
})
req.on("end", async function () {
// querystring.decode converts browser query string into an object
const userInfo = querystring.decode(body); // userInfo is an object here
// Status code 302 stands for code of redirection
if (req.url.startsWith("/login_page/loginPage.html")) {
const client = createClient();
await client.connect();
let errVal = "";
async function handleLoginReq(req, res) {
// Below is the query to get user password
let dbQuery = `
SELECT password FROM faculty_information
WHERE email='${userInfo["user-email"]}';
`;
try {
const dbres = await client.query(dbQuery);
if (dbres.rows.length !== 0) {
if (dbres.rows[0].password === '') {
const errVal = 'Please register yourself correctly';
res.writeHead(302, { 'Location': `/login_page/loginPage.html?error=${encodeURIComponent(errVal)}` });
res.end();
client.end();
} else if (userInfo["user-password"] === dbres.rows[0].password) {
res.writeHead(302, { 'Location': '/experiment_page/index.html' });
res.end();
client.end();
} else {
const errVal = 'Incorrect password or email address';
res.writeHead(302, { 'Location': `/login_page/loginPage.html?error=${encodeURIComponent(errVal)}` });
res.end();
client.end();
}
} else {
const errVal = 'Please sign up';
console.log(errVal);
res.writeHead(302, { 'Location': `/login_page/loginPage.html?error=${encodeURIComponent(errVal)}` });
res.end();
client.end();
}
} catch (err) {
res.writeHead(500);
res.end("Internal server error");
client.end();
}
}
await handleLoginReq(req, res);

Getting "TypeError: Cannot read properties of null (reading 'items')" error but the code works after reloading

so I was working on making this Todo list website but I am facing a problem.
NODE.JS CODE:
//jshint esversion:6
// _______________________________Database Code_________________________________
const mongoose = require("mongoose")
none = []
main().catch(err => console.log(err));
async function main() {
mongoose.set('strictQuery', false);
await mongoose.connect('mongodb://0.0.0.0:27017/todolistDB');
}
// For the main list
const itemSchema = {
itemName: {
type: String,
required: true
}
}
const Item = mongoose.model("Item", itemSchema)
const buyFood = new Item({
itemName: "Buy Food"
})
const cookFood = new Item({
itemName: "Cook Food"
})
const eatFood = new Item({
itemName: "Eat Food"
})
const defaultItems = [buyFood, cookFood, eatFood]
// New list schema
const listSchema = {
listName: String,
items: [itemSchema]
}
const List = mongoose.model("list", listSchema)
// Function that creates new lists
function makeNewList(name) {
const list = new List({
listName: name,
items: defaultItems
})
list.save()
}
// Function that creates new list items
function createNewItem(newItem) {
const item = new Item ({
itemName: newItem
})
}
// Function to find a list
function findList(listName) {
List.findOne({listName: listName}, function(err, list) {
if (!err) {
return list
}
})
}
// _______________________________Server Code___________________________________
const express = require("express");
const bodyParser = require("body-parser");
const date = require(__dirname + "/date.js");
const _ = require("lodash")
const popup = require("node-popup")
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static("public"));
const workItems = [];
// Default Home List
app.get("/", function(req, res) {
const day = date.getDate();
Item.find(function(err, item) {
if (item.length === 0) {
Item.insertMany(defaultItems, function(err) {
if (err) {
console.log(err);
} else {
console.log("Items added successfully.");
}
})
}
else if (err) {
console.log(err);
}
else {
List.find({}, function(err, list) {
if (err) {
console.log(err);
}
else if (list.length === 0) {
res.render("list", {listTitle: day, newListItems: item, array: none});
}
else {
list.forEach(function(listName) {
console.log(listName);
})
res.render("list", {array: list, newListItems: defaultItems, listTitle: day})
}
})
}
})
});
// Creating new list items
app.post("/", function(req, res){
const item = req.body.newItem;
const listName = req.body.list;
if (listName === "day") {
createNewItem(item)
res.redirect("/")
}
// else {
// List.findOne({listName: listName}, function(err, foundList) {
// foundList.items.push(item)
// foundList.save()
// res.redirect("/" + listName)
// })
// }
});
// Deleting list items
app.post("/delete", function(req, res) {
deletedItem = String(req.body.box)
Item.deleteOne({_id: deletedItem}, function(err) {
if (err) {
console.log(err);
} else {
console.log("Item deleted successfully");
}
})
res.redirect("/")
})
// Making new lists
app.post("/list", function(req, res) {
newList = req.body.newListName.toLowerCase()
List.findOne({listName: newList}, function(err, listInSearch) {
if (!listInSearch) {
console.log("Does not exist");
makeNewList(newList)
res.redirect("/" + newList)
}
else {
console.log("Exist");
}
})
})
// Loading existing list
app.get("/:extension", function(req, res) {
extension = req.params.extension.toLowerCase()
console.log("Site ends with " + extension);
if (extension !== "list") {
List.find({}, function(err, list) {
if (err) {
console.log(err);
}
else {
List.findOne({listName: extension}, function(err, foundList) {
if (!err) {
items = foundList.items
console.log(items);
res.render("list", {array: list, newListItems: foundList.items, listTitle: _.startCase(extension)})
}
})
}
})
}
})
// app.post("/:extension", function(req, res) {
// extension = req.params.extension.toLowerCase()
// item = req.body.newItem.toString()
//
// console.log(item);
// console.log(extension);
//
// List.findOne({listName: extension}, function(err, foundList) {
// if (!err) {
// createNewItem(item)
// foundList.items.push(item)
// foundList.save()
// res.redirect("/" + extension)
// }
// })
// })
// About page
app.get("/about", function(req, res){
res.render("about");
});
// Server port
app.listen(2000, function() {
console.log("Server started on port 2000");
});
HTML CODE:
<%- include("header") -%>
<!-- Showing list title -->
<div class="content">
<div class="box" id="heading">
<h1> <%= listTitle %> </h1>
</div>
<!-- Showing all lists -->
<div class="form">
<div class="btn-group">
<button type="button" class="btn btn-danger dropdown-toggle" data-bs-toggle="dropdown" aria-expanded="false">
Lists
</button>
<ul class="dropdown-menu">
<% array.forEach(function(item) {%>
<li><a class="dropdown-item" href="/<%= item.listName %>"> <%= item.listName %> </a></li>
<% }) %>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="/">Default List</a></li>
</ul>
</div>
<!-- Making new lists -->
<div class="list drop">
<form action="/list" method="post">
<input type="text" name="newListName" placeholder="New List Name" autocomplete="off">
<button class="btn btn-primary btn-md" type="submit" name="newList">Create</button>
</form>
</div>
</div>
<!-- Showing each list item -->
<div class="box">
<% newListItems.forEach(function(item) {%>
<form class="form-group" action="/delete" method="post">
<div class="item">
<input type="checkbox" onChange="this.form.submit()" name="box" value="<%= item._id %>">
<p><%= item.itemName %></p>
</div>
</form>
<% }) %>
<!-- Adding new list items -->
<form class="item" action="/" method="post">
<input type="text" name="newItem" placeholder="New Item" autocomplete="off">
<button class="button" type="submit" name="list" value="<%= listTitle %>">+</button>
</form>
</div>
</div>
<%- include("footer") -%>
Now, the website works well for the home page but I have added the functionality to make custom lists with custom names and that's where the issue arises. Whenever I make a new list, I want to add some items to it that are then stored in mongodb database. But if you look at the "Loading existing list" section of the .js code, there's the "newListItems" parameter which is supposed to take a list of items which are later displayed on the screen using a forEach() loop in the html document using EJS. Now, I have checked it multiple times, the items always get added to the database and exist there but when it's time to render them, the "foundList.items" gives that "TypeError: Cannot read properties of null (reading 'items')" error. I don't know what to do... And one more thing, when I try to create a new list after already creating one before, the second one doesn't gets any issues whatsoever. No idea what that is but it only happens the first time.
I hope someone can help...

Vue Js Form post issues to server

I am building a website and I cannot find a way to send my SignUp form data to my server using post. I tried with axios but it didn't work.
This is basically how my signup page looks like
<template>
<div id = "app">
<!-- <router-view /> -->
<h1>{{ $t('signup') }}</h1>
<p>{{ $t('signupMsg') }}</p>
<b-form #submit="onSubmit" #reset="onReset" method="post" >
<b-form-group
id="input-group-1"
label-for="input-1"
>
<p1> Name: </p1>
<b-form-input
id="input-1"
v-model="form.name"
required
placeholder="Enter Name and Vorname"
></b-form-input>
</b-form-group>
<b-form-group id="input-group-2" label-for="input-2" >
<p1>{{ $t('tech') }}</p1>
<b-form-input
id="input-2"
v-model="form.technicianID"
required
placeholder="Enter assigned Technician ID"
></b-form-input>
</b-form-group>
<b-form-group id="input-group-3" label-for="input-3">
<p1> Email ID: </p1>
<b-form-input
id="input-3"
v-model="form.email"
required
placeholder="Enter assigned Email ID"
></b-form-input>
</b-form-group>
<b-form-group id="input-group-4" label-for="input-4">
<p1> {{ $t('branch') }} </p1>
<b-form-input
id="input-4"
v-model="form.branch"
required
placeholder="Enter your branch"
></b-form-input>
</b-form-group>
<!-- <b-button type="submit" > <router-link to="/requestsuccess">{{ $t('signup') }}</router-link> </b-button> -->
<b-button type="submit" >{{ $t('signup') }} </b-button>
<b-button type="reset" variant="danger">{{ $t('reset') }}</b-button>
<router-link to="/" class="btn btn-link">{{ $t('back') }}</router-link>
</b-form>
</div>
</template>
<script>
import axios from 'vue-axios'
export default {
name: 'signup',
data() {
return {
form: {
name: '',
technicianID: '',
email:'',
branch: ''
}
}
},
methods: {
onSubmit(evt) {
evt.preventDefault()
axios({
method: 'post',
url: '/insert',
data: this.form
})
.then(function (response) {
//handle success
console.log(response);
})
.catch(function (response) {
//handle error
console.log(response);
});
},
onReset(evt) {
evt.preventDefault()
// Reset our form values
this.form.name = ''
this.form.technicianID = ''
this.form.email = ''
this.form.branch = ''
// Trick to reset/clear native browser form validation state
this.show = false
this.$nextTick(() => {
this.show = true
})
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style>
</style>
This is how my index.js looks like for post
router.post('/insert', function(req, res, next) {
var item = {
name: req.body.name,
technicianID: req.body.technicianID,
email: req.body.email,
branch: req.body.branch
};
mongo.connect(url, function(err, db) {
assert.equal(null, err);
db.collection('users').insertOne(item, function(err, result) {
assert.equal(null, err);
console.log('Item inserted');
db.close();
});
});
res.redirect('../components/requestsuccess');
});
I am fairly new to this but I can't find a way to send my data to the server.
You can try this code below:
Backend: You can change your backend with this code below
router.post('/insert', function(req, res, next) {
console.log(req.body);
mongo.connect(url, function(err, db) {
db.collection('users').insertOne(req.body, function(err, result) {
if(err) return res.status(500).send(err);
return res.status(200).send(result.ops[0]);
db.close();
});
});
});
The code above only an example for simple case. If you want to add assert, then you can make sure it's working fine. If the simple code above it's working, then you can add assert.
Make sure you've been install cors on your server and add it in your app.js or server.js this code below:
app.use(cord({origin: "*"});
And then, make sure you call your endpoint use: http://. Not only localhost but http://localhost.
FrontEnd
onSubmit(evt) {
evt.preventDefault()
axios({
method: 'post',
url: '/insert', // make sure your endpoint is correct
data: this.form
})
.then(response => {
//handle success
console.log(response.data);
// do some stuff here: redirect or something you want
})
.catch(error => {
//handle error
console.log(error.data);
});
},
Make sure your endpoint is correct.
I hope it can help you.

Angular2 API call return nothing

My problem is, that it isn't displayed in html form. How can I solve this ?
The query is well, and I get the result on URL, but can't display it on component.html.
( It works and I see if I call the URL /api/mainstorage so it display me the JSON content.)
Index.js
var express = require('express');
var router = express.Router();
// http://localhost:3000/
router.get('/', function(req, res, next) {
res.status(200)
.json({
status: 'success',
message: 'Live long and prosper!'
});
});
var db = require('./queries');
router.get('/api/mainstorage', db.getAllDocuments);
module.exports = router;
Queries.js
var promise = require('bluebird');
var options = {
// Initialization Options
promiseLib: promise
};
var pgp = require('pg-promise')(options);
var connectionString ='postgres://dbuser:Storage#localhost/mainstorage'
var db = pgp(connectionString);
const axios = require('axios');
const API = 'http://localhost:3000';
function getAllDocuments(req, res, next) {
axios.get(`${API}/main`)
db.any('SELECT * FROM files')
.then(function (data) {
res.status(200)
.json({
status: 'success',
data: data,
message: 'Retrieved all files'
});
})
.then(documents => {
res.send(200).json();
})
.catch(function (err) {
return next(err);
});
}
module.exports = {
getAllDocuments: getAllDocuments
};
documents.component.ts
export class DocumentsComponent implements OnInit {
title = 'app works!';
mainstorage;
documents: any [];
constructor(private documentsService: DocumentsService) { }
ngOnInit() {
// Retrieve documents from the API
this.documentsService.getAllDocuments().subscribe(documents => {
this.documents = documents;
});
}
}
documents.service.ts
#Injectable()
export class DocumentsService {
constructor(private http: Http) {}
getAllDocuments(){
return this.http.get('/api/mainstorage')
.map(res => res.json());
}
}
documents.component.html
<div class="row" *ngFor="let document of documents">
<div class="card card-block">
<h4 class="card-title">{{ documents.id }}</h4>
<p class="card-text">{{document.country}}</p>
You are not able to see anything in the html because service data is asynchronous and you are trying to display it before the service returns it back.
You can solve this by wrapping your variables in *ngIf
<div *ngIf='documnets'>
<div class="row" *ngFor="let document of documents">
<div class="card card-block">
<h4 class="card-title">{{ documents.id }}</h4>
<p class="card-text">{{document.country}}</p>
</div>
</div>
</div>
*ngIf will check if there are documents and once data from service is received it will be displayed.

Elastic search is returning undefined for _id in elastic search

I am using elastic search in my application and everything works fine until you click the search result link which returns undefined. The problem I have is that the _source._id is returning undefined. So I cannot view the search result.
How can I pass the object id in /blog/article/<%= data[i]._source._id?
My code is below
router.js
router.post('/search', function(req, res, next) {
res.redirect('/search?q=' + req.body.q);
});
router.get('/search', function(req, res, next) {
if (req.query.q) {
Article.search({
query_string: { query: req.query.q}
}, function(err, results) {
results:
if (err) return next (err);
var data = results.hits.hits.map(function(hit) {
return hit;
});
res.render('main/search-result', {
query: req.query.q,
data: data
});
});
}
});
search-result.ejs
<% for (var i=0; i < data.length; i++) { %>
<div class="col-md-4">
<a href="/blog/article/<%= data[i]._source._id %>">
<div class="thumbnail">
<h3 id="data_title"><%= data[i]._source.title %></h3>
</div>
</div>
<% } %>
Finally resolved this issue by changing
<a href="/blog/article/<%= data[i]._source._id %>">
to
<a href="/blog/article/<%= data[i]._id %>">

Resources