window location replace works only one time - javascript

This is very complicated term for me because i am confused how things are done. I have React & Express application where you can upload data and when you upload it will redirect you to other page where your data is displayed, but problem is that it only redirects you one time and when you go back to main page and try to upload file second time it is not uploaded and whole application crashes
here is recipe.js file (part of it) (react)
axios({
method: 'post',
url: '/api/recipes',
config: {headers: {'Content-Type': 'multipart/form-data' }},
data: data
})
.then(res => {
window.location.replace(res.data.location)
})
.catch(err => {
if(err.response){
if(err.response.data.redirect === true){
window.location.replace(err.response.data.location)
}
if(err.response.data.message){
alert(err.response.data.message)
}
}
});
recipe.js (part of it)(expressjs)
const recipe = await Dish.create({
author: user.username,
name: name,
//properties and values
})
return res.status(200).send({
location: '/recipe/' + recipe.name + '/' + recipe._id
})
view-recipe.js (express (part))
componentDidMount(){
const { match: { params } } = this.props;
console.log(`/api/recipe/${params.dishName}/${params.id}`)
axios.get(`/api/recipe/${params.dishName}/${params.id}`)
.then(res => res.data)
.then(data =>{
console.log(data)
}).catch(err=>{
if(err.response.data.message){
alert(err.response.data.message)
}
})
}
view-recipe.js (express)
router.get('/:dishName/:id', async (req, res) => {
try {
const name = req.params.dishName;
const id = req.params.id;
console.log('name ' + name + ' id ' + id)
const recipe = await Dish.findOne({
name: name,
_id: id
}).lean();
if (!recipe) {
return res.status(404).send({
message: 'recipe not found'
})
}
return res.status(200).send({
recipe
})
} catch (err) {
return res.status(500).send({
message: err.message
})
}
})
and finally
index.js (express, for where is guard determinig whether jwt validation token is expired or not and route configurations )
router.use('/api/recipes', guardr, require('./recipe'))
router.use('/api/recipe', require('./view-recipe'))
What is wrong with this code? By the way, before window.location.replace() in recipe.js file (client) i had window.location.href instead and it worked 2 times. it is really confusing for me because i am doing this difficult project for the first time. Thanks!

Related

Why is fetch('api.apify.org') not working when I host it online but do working in localhost

I got this strange error I don't understand
Have been using for a long time and it worked, just yesterday it stopped working
module.exports.login = async(req, res, next) => {
const { username, password } = req.body;
const ips = req.user.ip;
const email = req.user.email;
fetch('https://api.ipify.org')
.then((res) => res.text())
.then(ip => {
fetch(`http://ip-api.com/json/${ip}`)
.then(response =>response.json())
.then(data => {
console.log(data)
const city = data.city
const country = data.country
const location = `${city}, ${country}`
if (ip === ips) {
req.flash('success', `welcome back ${username}`);
const redirectUrl = req.session.returnTo || '/index';
console.log(req.session.returnTo)
delete req.session.returnTo;
res.redirect(redirectUrl);
} else {
...
};
})
.catch(err => {
req.logout(function(err) {
if (err) { return next(err); }
req.flash('error', 'An error occured')
res.redirect('/login');
});
})
})
.catch(err => {
req.logout(function(err) {
if (err) { return next(err); }
req.flash('error', 'An error occured, This may be due to bad network')
res.redirect('/login');
});
})
};
The last catch(err with message 'An error occured, This may be due to bad network' is what am getting
But it working in m localhost, but when I upload it online it does not take any action rather it trows error
Please any help with this?
Thanks for any future help
Trying to get user ip with fecth('api.ipify.org') but is giving me error when I put it online but working in my localhost
I actually found the answer, node-fetch just currently updated their v3.0.3 package
Reasons is that it works only in ESM which you use 'import' instead of require(), And if that does not work you get error except you go back using v2 or less.
Which is not Ok for me so I diverted to use 'axios'
npm install axios
Example
async() {
await axios.get('api.ipify.org')
.then(response => {
console.log(response)
}.catch(err => console.log(err))
return
};
The response contains the ip address
But if you still need to use node-fetch use the link 'node-fetch'
Full code below
module.exports.login = async(req, res, next) => {
const { username, password } = req.body;
const ips = req.user.ip;
const email = req.user.email;
await axios.get('https://api.ipify.org')
.then(async(response) => {
const ip = response.data
await axios.get(`http://ip-api.com/json/${ip}`)
.then(response => {
const data = response.data
console.log(data)
const city = data.city
const country = data.country
const location = `${city}, ${country}`
if (ip === ips) {
req.flash('success', `welcome back ${username}`);
const redirectUrl = req.session.returnTo || '/index';
console.log(req.session.returnTo)
delete req.session.returnTo;
res.redirect(redirectUrl);
} else {
...
};
})
.catch(err => {
req.logout(function(err) {
if (err) { return next(err); }
req.flash('error', 'An error occured')
res.redirect('/login');
});
})
})
.catch(err => {
req.logout(function(err) {
if (err) { return next(err); }
req.flash('error', 'An error occured, This may be due to bad network')
res.redirect('/login');
});
})
};

How to code a checkbox that saves changes after refreshing page

I'm trying to change the checkbox data on the server using the patch method, but I can't do it. Give me an advise, please, how to do it correctly.
I send a patch request, 202 code is returned. In the preview (developer tools in the browser) it is shown that the changed data is returned from the server, but for some reason the changes do not occur in the db.json file. After I check the checkbox and refresh the page it’s like I never checked the box.
I need an input checkbox that will send a PATCH request to the server to change the TODO-list state.
What I have so far:
async function editCheckbox(id) {
try {
checkbox = {
completed: document.querySelector(`[data-id="${id}"]` + ' input[type="checkbox"]').checked
}
await fetch('http://localhost:8080/todo/' + id, {
method: 'PATCH',
body: JSON.stringify(checkbox),
headers: {
'Content-Type': 'application/json; charset=utf-8',
},
});
} catch (err) {
console.log(err);
}
}
And I use a patch on the route:
app.patch("/todo/:id", (req, res) => {
const { id } = req.params;
let rawdata = fs.readFileSync("db.json", "utf8");
let content = JSON.parse(rawdata);
if (!content.find((i) => i.id == id)) {
return res.status(404).json({ message: "Todo with that id not found" });
} else {
const newTodo = req.body;
const toWrite = content.map((i) => {
if (i.id === id) {
return newTodo;
}
return i;
});
fs.writeFileSync("db.json", JSON.stringify(toWrite), (err) => {
if (err) {
console.error(err);
}
});
res.status(202).json(newTodo);
}
});

Why am I getting different response from my data when local and when on heroku?

I am working on an Application which i have also deployed in heroku. The issue is that when I login in using heroku, user is nested inside a data object. but when I work locally or use postman, user isnt nested.
Help Please.
I get this response on the deployed version.
data: {
user: {
email: "my_email"
name: "my_name"
role: "user"
_id: "6205807deeadcfa734f954f3".
}
status: "success"
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYyMDU4MDdkZWVhZGNmYTczNGY5NTRmMyIsImlhdCI6MTY0NDg0NTYyMCwiZXhwIjoxNjQ1NDUwNDIwfQ.YeWFNrN8rsLPJvvU8JQDwBVG4aBqqEuo7ssgLrR3O8M"
But when I log in locally, I get the response as
user: {
email: "my_email"
name: "my_name"
role: "user"
_id: "6205807deeadcfa734f954f3".
}
status: "success"
token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYyMDU4MDdkZWVhZGNmYTczNGY5NTRmMyIsImlhdCI
For Heroku, the USER is nested inside data but for local host and postman, the user isnt nested.
My codes are:
exports.login = catchAsync(async (req, res, next) => {
const { email, password } = req.body
if (!email || !password) {
return next(new AppError('Please provide email and password!', 400))
}
const user = await User.findOne({ email }).select('+password')
if (!user || !(await user.comparePassword(password, user.password))) {
return next(new AppError('Incorrect email or password', 401))
}
createSendToken(user, 200, req, res)
})
These are my api codes
const createSendToken = (user, statusCode, req, res) => {
const token = signToken(user._id)
res.cookie('jwt', token, {
expires: new Date(
Date.now() + process.env.JWT_COOKIE_EXPIRES_IN * 24 * 60 * 60 * 1000
),
httpOnly: true,
})
user.password = undefined
res.status(statusCode).json({
status: 'success',
token,
user,
})
}
For my react, The function code is:
function request(path, { data = null, token = null, method = 'GET' }) {
return (
fetch(`${process.env.REACT_APP_API}${path}`, {
method,
headers: {
Authorization: token ? `Bearer ${token}` : '',
'Content-Type': 'application/json',
},
body:
method !== 'GET' && method !== 'DELETE' ? JSON.stringify(data) : null,
})
.then((response) => {
// If Successful
if (response.ok) {
if (method === 'DELETE') {
// If delete, nothing returned
return true
}
return response.json()
}
// If errors
return response
.json()
.then((json) => {
// Handle Json Error response from server
if (response.status === 400) {
const errors = Object.keys(json).map(
(k) => `${json[k].join(' ')}`
)
throw new Error(errors.join(' '))
}
throw new Error(JSON.stringify(json))
})
.catch((e) => {
if (e.name === 'SyntaxError') {
throw new Error(response.statusText)
}
throw new Error(e)
})
})
.catch((e) => {
// Handle all errors
toast(e.message, { type: 'error' })
})
)
}
The main sign in function
export function signIn(email, password) {
return request('/api/v1/auth/login', {
data: { email, password },
method: 'POST',
})
}
Then I import this into my auth context and execute it there
import {signIn as signInApi} from '../apis'
const AuthContext = createContext()
export const AuthProvider = ({ children }) => {
const [token, setToken] = useState(localStorage.getItem('token'))
const [user, setUser] = useState(
JSON.parse(localStorage.getItem('user'))
)
const [loading, setLoading] = useState(false)
const signIn = async (email, password, callback) => {
setLoading(true)
const res = await signInApi(email, password)
if (res.token) {
localStorage.setItem('token', res.token)
localStorage.setItem('user', JSON.stringify(res.user)) // This stores the user in localhost but returns undefined for user in the one deployed to heroku. I have to use
localStorage.setItem('user', JSON.stringify(res.data.user)) which now works on the deployed one but not on the local one
setToken(res.token)
setUser(res.user)
callback()
}
setLoading(false)
}
}
it seems the deployed version is using built in implementaion of createSendToken and not the one you provided. need to check your project structure.
in order to validate this change the function name and the call createSendToken to something else and you will find the issue

Fail to send data back to React

I am new to React and Node js. I have defined a function that run a Python script from my Node.js application using child process, and I have an router post that called pythonExecute and return that result back to
React. Router seemed to have trouble sending the data back to react using react.json(data),can someone please help and see what I did wrong and how to fix it?
Function
const pythonExecute = (data, input) => {
const res = {
err: false,
msg: ""
}
return new Promise((resolve, reject)=>{
const fileName = "test.py"
saveFile(fileName, data)
.then(()=>{
const filePath = path.join(__dirname,"../test.py")
const spawn = require("child_process").spawn;
const pythonProcess = spawn('python',[filePath]);
pythonProcess.stdout.on('data', (data) => {
console.log(data.toString());
resolve(data)
});
})
.catch(()=>{
console.log("ERROR SAVE FILE"+ saveFileRes)
const err = {
err: true,
output: "Internal Server Error!"
}
resolve(err)
})
})
Express Router
const execute = require('../../compile/compile')
router.post('/submit', (req,res)=>{
console.log(req.body)
const code = req.body.code
const input = req.body.input
const lang = req.body.lang
return execute.pythonExecute(code, input)
.then(data=>{
console.log("SUCCESSFULL PROMISE " + data)
console.log("SENDING " + data)
res.write(data)
deleteFile(path.join(__dirname, '../../test.py'))
})
.catch(err => {
console.log("ERROR PROMISE " + err)
deleteFile(path.join(__dirname, '../../test.py'))
})
}
)
React
export default class Ide extends Component {
state={
code: code.cpp,
result: 'Submit Code to See Result',
lang: 'cpp'
}
onSubmitHandler = (e) => {
e.preventDefault()
alert("submit code")
axios.post(`${secret.url}code/submit`,this.state)
.then(res=>{
console.log(res.data)
const data = res.data
if(data.err){
// Error in user code
this.setState({
result: data.error
})
}else{
this.setState({
result: data.output
})
}
})
.catch(err=>{
console.log(err)
})
}
Logs
Server started at port 8000
{
code: '# Your code will come here\nprint("b")',
result: 'Submit Code to See Result',
lang: 'python'
}
SAVING FILES
The file was saved!
FILE PATH >> \ide-server\test.py
[6 7 8]
SUCCESSFULL PROMISE [6 7 8]
SENDING [6 7 8]
File deleted!
SORRY NOT DELETED
File deleted!
File deleted!
if you want to send a JSON structure to react App try to do on server:
res.send(JSON.stringify(data))
data must be like {values: [6, 7, 8]} or smth else
on client:
axios.post(`${secret.url}code/submit`,this.state)
.then(res=> res.json())
.then(result => console.log(result))
...
if you want to send a plain text:
res.send(data)
on client:
axios.post(`${secret.url}code/submit`,this.state)
.then(res=> res.text())
.then(result => console.log(result))
...
And don't forget use res.end() after res.write();

SyntaxError: Unexpected end of input in fetch API

I face a new problem that has been asked before in this link. But It is not relevant to my problem.
What I have implemented is a very simple API using nodejs, express-framework and mongoose.
The problem is with fetch API. I want to submit some ID and post it to the server. In the server side I redirect it to the proper URL base on the ID that user entered. Whenever I test this part, this error is being raised in front-end side and points to return response.json() line.
SyntaxError: Unexpected end of input
Here is my code:
Front-End:
function submitCode(){
var nationalCode = document.getElementById('nationalCode').value
var data = {
nationalCode: nationalCode,
creationDate: new Date().toLocaleDateString()
}
fetch('/submit', {
method: 'POST',
redirect:'manual',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(data)
},
).then(response => {
return response.json()
}).then(jsonData => {
console.log('success:', jsonData)
history.pushState(null, null, "/lashkhor")
}).catch(e => {
console.log('error:', e)
return e
})
}
Back-End:
app.post('/submit', (req, res) => {
var nationalCode = req.body.nationalCode
var creationDate = req.body.creationDate
query = {'nationalCode': nationalCode}
nationalCodeModel.find(query, (err, success) => {
if (err) {
console.log('error:', err)
}
else if (success.length == 0){
nationalCodeModel.create({
nationalCode: nationalCode,
creationDate: creationDate
})
console.log('salam khoshgele daei!')
res.redirect('/khoshgeledaei')
}
else if (success.length > 0) {
console.log('lashkhor detected')
res.redirect('/lashkhor')
}
})
})
app.get('/lashkhor', (req, res) => {
console.log('here')
res.send('salam')
})
I can't find any hint to solve it. I would be thankful if anyone could help me.
PS: Whole code is available in this repository
Thanks!
You are trying to parse text into json.
You can use res.json() instead of res.send() from your backend.

Categories

Resources