Redirecting to a node template - javascript

I'm pretty new to node and everything that happens around, but I'm trying to make a little admin panel. There will be a login page and after login if the user is an admin the page will redirect to dashboard.ejs.
I suppose I didn't do it the correct way because what I did don't work.
Let me show you what I did :
Let's start with my main routes for admin. So these can be accesses with /admin and /admin/dashboard. If I just go to /admin the page loads normally with the login forms.
router.get('/', (req, res) => {
res.render('../views/admin/admin.ejs')
})
router.get('/dashboard', admin_check, (req, res) => {
res.render('../views/admin/dashboard.ejs')
console.log('dashboard rendered...')
})
I have a simple login button that will do some checks in the database and finally run this to redirect to the dashboard :
fetch('/admin/dashboard', {
headers: {
auth_token: sessionStorage.getItem('token')
}
})
This will correctly trigger and let the console.log() run that comes from here :
router.get('/dashboard', admin_check, (req, res) => {
res.render('../views/admin/dashboard.ejs')
console.log('dashboard rendered...')
})
The thing is, the dashboard isn't loaded while the res.render() in fact executed.
There is an error in console though :
The resource from “http://localhost:8080/admin/scripts/admin-auth.js” was blocked due to MIME type (“text/html”) mismatch (X-Content-Type-Options: nosniff).
I looked up a little bit what this was but I don't really understand anything about it.
Here is my full admin-auth.js file :
$('#login_form').submit(e => {
e.preventDefault()
fetch('/api/user/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Accept: 'application/json'
},
body: JSON.stringify({
email: $('#login_email').val(),
password: $('#login_password').val()
})
})
.then(res => res.json())
.then(data => {
if (data.status === 200) {
sessionStorage.setItem('token', data.token)
sessionStorage.setItem('user', data.user)
fetch('/api/user', {
headers: {
auth_token: data.token
}
})
.then(res => res.json())
.then(data => {
if (data.user.admin) {
fetch('/admin/dashboard', {
headers: {
auth_token: sessionStorage.getItem('token')
}
})
}
})
} else {
console.log(data.error)
}
})
})
EDIT: So I used this instead :
res.sendFile(process.cwd() + '/src/views/admin/dashboard.ejs')
But the page still don't appear. Errors are gone and in the network management I get a 200 response but that's it

Related

When I res.redirect(`/relative/url`), the response received is PATCH 404 Not found. How to fix this?

Problem: I want to 'update' a document saved on mongoDB, so i used Blog.findByIdAndUpdate(req.body.id, { 'status': req.body.status }). Till here, every thing is working fine. BUT, as soon as i add res.redirect('/user/control_articles') below it to redirect the user to another page, it returns 404 in browser console.
How can i properly "update" then "redirect" the user?
//main.js
// pre_id comes from another variable, its ok
pub_btn.addEventListener(`click`, () => {
fetch(`/user/new_article`, {
method: `PATCH`,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
'event': 'publish',
'status': 'publish',
'id': pre_id
})
})
.then(response => console.log(response))
.catch(err => console.log(err))
})
//router.js
router.patch(`/new_article`, userController.article_update)
//controller.js
exports.article_update = (req, res) => {
if(req.body.event === 'publish'){
Blog.findByIdAndUpdate(req.body.id, { 'status': req.body.status })
res.redirect(`/user/control_articles`)
}
}
I think you forget to define the GET endpoint which serves /user/control_articles
You should define it like the patch endpoint
//router.js
router.get(`/user/control_articles`, userController.articles_get)
router.patch(`/new_article`, userController.article_update)
If you doesn't forget then try awaiting until the promise is resolved using async/await syntax
//controller.js
exports.article_update = async (req, res) => {
if(req.body.event === 'publish'){
await Blog.findByIdAndUpdate(req.body.id, { 'status': req.body.status })
res.redirect(`/user/control_articles`)
}
}

Why does my api post request (Vue.js client) receive an undefined response from my express server?

My client is Vue.js using a Vuex store. I am using passport.js for authentication on the server side. Login and account registration is working. Checking mongodb shows new data. But express is sending an undefined response to the client. This is my first major javascript project so I'm hoping it's something simple my eyes just can't see yet.
client: api.js
export async function registerUser(user) {
console.log("api to register user");
console.log(user);
const route = `${api}/register`;
return fetch(route, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(user)
})
.then(response => {
console.log(response.json());
return response.json();
})
.then(json => {
console.log(json);
return json;
})
.catch(err => {
console.error(err);
});
}
client: index.js (vuex store where res is undefined)
actions: {
async register(state, user) {
apis.registerUser(user).then(res => {
if (res.success) {
this.dispatch("loadUser");
alert("successfully registered");
}
});
},
async loadUser() {
apis.getUser().then(res => {
this.commit("setUser", res.user);
});
}
}
server: app.js
app.post('/api/v1/register', function(req, res) {
const success = true;
Users=new User({email: req.body.email, username : req.body.username});
console.log(req.body);
User.register(Users, req.body.password, function(err, user) {
if (err) {
console.log('account could not be saved');
success = false;
} else {
console.log('account saved');
}
})
res.send({success: success});
});
fetch error printing to console
The server console.logs in the app.js route indicate the req.body has the right data and user account is saved successfully. No errors occur on res.send but the client gets an undefined response.
After much banging my head against the table and some outside assistance, I found a solution. I had two main issues.
I was not preventing the default on the submit button so the form was refreshing before the request was properly handled.
Mishandling of javascript promises.
Working code below:
api.js
export function registerUser(user) {
console.log("api to register user");
console.log(user);
const route = `${api}/register`;
return fetch(route, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(user)
})
.then(response => {
console.log(response.json());
return response.json();
})
}
index.js (vuex store)
actions: {
register(state, user) {
apis.registerUser(user).then(res => {
if (res.success) {
alert("successfully registered");
}
}).catch(err => {
console.error(err);
});
}
}
app.js code remained the same

ReactJS and Node.JS [JSON.parse: unexpected character at line 1 column 1 of the JSON data]

I'm getting struggle with this code, so I need a third eye on this to find a solution.
I'm developing a ReactJS app with a REST API with Node.JS (Express), and I'm getting this error:
SyntaxError: "JSON.parse: unexpected character at line 1 column 1 of the JSON data"
I'm using Sequelize ORM to work with Models and Database in Node.JS.
I'm also using CORS module for Node.JS.
This implementation works fine.
// Node.js Route for login
const router = require('express').Router();
const User = require('user');
router.post("/login", async (req, res) => {
try {
await User.findOne({
where: {
email: req.body.email,
password: req.body.password,
}
}).then((user) => {
if (!user) {
return res.send({message: "Login error!"});
} else {
const userData = {id: user.id, email: user.email};
res.send({"user": userData});
}
}).catch((err) => {
return res.send(err);
});
} catch (err) {
return res.send(err);
}
});
// ReactJS for login
loginFunction(e, data) {
e.preventDefault();
fetch('http://localhost:4500/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(response => response.json())
.then(json => {
this.setState({'user': json['user']});
})
.catch((err) => {
console.log(err);
this.setState({errors: "Login error"})
});
}
On the other hand, this implementation do not work properly and throws the SyntaxError above:
// Node.JS for Posts
const router = require('express').Router();
const Post = require('post');
router.get("/posts", async (req, res) => {
try {
await Post.findAndCountAll()
.then((posts) => {
res.send({"posts": posts});
}).catch((err) => {
return res.send(err);
});
} catch (err) {
return res.send(err);
}
});
// ReactJS for Posts
postsFunction() {
fetch('http://localhost:4500/posts', {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(json => {
this.setState({'posts': json.posts.rows});
})
.catch((err) => {
console.log(err);
this.setState({errors: "Posts error."})
});
}
As you can see both implementation have little differences, What am I missing?
PS: When I test the 2nd implementation on Postman, data is retrieving successfully.
try removing headers when using GET method
headers: {
'Content-Type': 'application/json'
}
Try to use res.json instead of res.send in the node js function that cause the error.
I found the issue!
I follow the (#vengleab so) suggestion:
console log response instead of response => response.json()
I'm realize that response returns an object like this:
Response: {
body: ReadableStream
locked: false
<prototype>: object { … }
bodyUsed: false
headers: Headers { }
ok: true
redirected: false
status: 200
statusText: "OK"
type: "basic"
url: "http://localhost:3000/admin/undefined/posts"
}
The URL attribute contain an undefined value, so when I try to console.log the .env variable API_URL that contains the localhost URL used in this line:
fetch('http://localhost:4500/posts', {
That in real function is:
fetch(process.env.API_URL + '/posts', {
The result of the console.log was undefined.
As it is explained in Create React App docs, the environment variables must start with the prefix REACT_APP_.
Finally the line works as:
fetch(process.env.REACT_APP_API_URL + '/posts', {
I found that it was because my front end react url pointed to the same url as my backend server.js running mongodb. Also clearing the cookies on the browser seems to have helped as well.

Route handler in express is not invoking anything?

I have made a simple textbox which accepts
Youtube Video URL
which slices it's video ID and use fetch to send data to my express server. I am using Youtube Data API v3
//after clicking button sends data
//input fields are defined already.
const sendData = (event) => {
event.preventDefault();
const filterUrl = input2.value.indexOf('&') != -1 ? input2.value.slice(0, input2.value.indexOf('&')) : input2.value;
const url = new URL(filterUrl).searchParams.get("v");
fetch('/', {
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
urlname: url.toString()
})
})
.then(function(res) {
console.log(res)
})
.catch(function(error) {
console.log(error)
});
}
Here is my Express Handler :
//defined routes and PARAMETER variable is globally defined
app.route('/')
.get((req, res) => {
res.render('container/index', {
title: 'Hello User!',
content: 'Welcome to youtube Comment viewer'
});
})
.post((req, res) => {
console.log("hello")
PARAMETER = req.body.urlname;
console.log(PARAMETER);
res.redirect('/randomCommentView');
});
//get request
app.get('/randomCommentView', (req, res) => {
console.log("inside");
Comments(PARAMETER)
.then((data) => {
res.render('container/comment', {
Comment: 'fgfg'
})
}).catch(err => {
if (err) res.status(404).render('container/index', {
notFound: `Your request couldn't be completed ERR: ${err}`
})
})
console.log(req.body);
});
But when i submit my Youtube video url, The page stays on the same route.
Here's the image of my output:
So it seems like the routes are being called but the page URL is not changing in the web browser .Does anyone know the possible reason for this.
Thanks,
Regards.
Since you're using javascript to make your request, only the javascript will follow your redirection.
What you can do is instead of sending a redirection from the server, send a special code that will trigger a manual redirection (window.location.href = ...) in your client-side javascript code.

Returning JSON within the same Fetch POST API call

I currently have a web app built on the Express framework for Node.js.
I'm now building a React Native app that needs to perform user login. To do this, I've created a mongo-helpers.js file that will simply perform the api calls to localhost:3000/api and return JSON. So far, I've had no problem making GET calls and receiving data, however here is my problem and what I want to do:
Objective: When the Login button is pressed (in the React Native app) make an API call to localhost:3000/api/login, passing the username and password into the body of the fetch API POST request. If the user is logged in, send back the user's Mongo Document.
Problem: Though I am able to make the API Post request and successfully log in the user, I am unable to send back the user's Mongo document with res.json(user)
Here is my code:
Express WEB APP: routes/api/api.js
// POST and login user
router.post('/login', (req, res) => {
user.findOne({name: req.body.name, password: req.body.password})
.then((user) => {
console.log(user);
res.json(user)
})
.catch((error) => res.json(error))
});
React Native App: mongo-helpers.js
// Returns a promise
// if login succeeds then return the user
// if login fails return error
exports.login = (name, password) => {
return new Promise(
(resolve, reject) => {
fetch(APP_SERVER_URL+'/login', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({name, password})
}).then((response) => {
console.log('Response', response);
}).then((data) => {
console.log(data); // returns undefined :(
resolve(data);
}).catch((error) => {
console.log('Error', error); // no error is returned
reject(error);
})
}
)
};
I am logging the response and here is what it shows. There's no user data within it
You need to call the json function and it will returns a promise, try that:
fetch(APP_SERVER_URL+'/login', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({name, password})
}).then((response) => {
response.json().then((data) => {
console.log(data)
});
}).catch((error) => {
console.log('Error', error); // no error is returned
reject(error);
})
}
https://developer.mozilla.org/en-US/docs/Web/API/Body/json
Use return response in first then callback.

Categories