Why am I getting an 'internal server error' with heroku deployment? - javascript

I just deployed a small weather app project with Heroku and I am getting an internal server error when user enters an invalid city or zip code. I added a .catch in my route to render an error page if this happens, and it works exactly as intended in my local version, but not on the deployed version. Does anyone know why this might be? I am using .ejs templates to render my pages.
app.get("/results_city", (req, res) => {
let query = req.query.search;
console.log("Search params:", query);
let weatherApiKey = process.env.WEATHER_API_KEY;
let weatherUrl =
"https://api.openweathermap.org/data/2.5/weather?q=" +
query +
"&appid=" +
weatherApiKey;
rp(weatherUrl)
.then((body) => {
let data = JSON.parse(body);
res.render("results", { data: data });
console.log(data);
})
.catch(err => {
if (err) {
res.render("Error")
return;
}
console.log(err);
});
});

Related

Trying to serve a file and automatically start a download with Express

Seems like many people have ran into similar kind of problem but googling hasn't helped me so far. I'm trying to serve the file to the user and automatically prompt download on client side, but all I'm getting is "The image cannot be displayed because it contains errors.
Here is my client side code:
function downloadFile(passcode){
console.log(passcode);
const payload = {"password" : passcode.toLowerCase()}
axios.post(downloadUrl, payload, {
headers : {'Content-Type' : 'application/json'}
})
.then((res) => {
console.log(res.data)
window.open(downloadUrl + '/' + res.data)
})
}
So the user types in a passcode, and clicks on the download button and should get the appropriate file. New tab opens but file doesn't stard downloading.
Here is my server side:
const getFilePath = async (req, res) => {
const passcode = req.body.password
try {
fs.readdir(path.join(homeDir + '/uploads/' + passcode), 'utf-8',(err, files) => {
files.forEach((file) => {
const filename = passcode + '/' + file
try {
res.send(filename)
res.end()
} catch (error) {
console.log(error);
}
})
})
} catch (error) {
console.log(error);
}
}
const fileDownload = async (req, res) => {
const {dir: directory, file: fileName} = req.params
const filePath = path.join(homeDir + '/uploads/' + directory + '/' + fileName)
fs.access(filePath, fs.constants.F_OK, err => {
//check that we can access the file
console.log(`${filePath} ${err ? "does not exist" : "exists"}`);
});
res.download(filePath)
res.end()
}
I even check the file with fs.access and it returns true (it prints {filepath} exists), but the file is not served at all.
Any kind of help is much appreciated!
EDIT:
Decided to work on my front end a bit to cool off, came back and immidiatelly noticed res.end() just below send file, which ends the transmission. Removed it and it works like a charm!

Connect to mySql on VPS server eventhough works locally

I have a React front-end, with a Node back-end to connect to mySql for data. It works exactly how I want locally. However, now that I'm moving it to a VPS server, I can't seem to get my configuration correct.
The error I get is: create:1 Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0. It's actually returning HTML, of the page that says it's can't find the page.
I setup an express server with this code:(I do realize I need to move login details to an ENV file... just haven't yet)
const express = require('express');
const mysql = require('mysql2');
const connection = mysql.createPool({
host : 'localhost:3306',
user : 'root',
password : 'xxxxx',
database : 'ppr'
});
const app = express();
app.use(express.json());
app.use(express.urlencoded({extended: false}));
app.get('/api/clients/all', function (req, res) {
// Connecting to the database.
connection.getConnection(function (err, connection) {
// Executing the MySQL query (select all data from the 'clients' table).
connection.query("SELECT * FROM clients", function (error, results) {
// If some error occurs, we throw an error.
if (error) throw error;
console.log(results);
res.json(results);
});
});
});
// Starting our server.
app.listen(3001, () => {
console.log('Listening on port http://localhost:3001');
});
I start this running on the server, and it runs. No errors.
But then my React app makes the first api call, and I get the error because it returns HTML instead of the data I'm expecting. Do I need to do something different to make it work in production? I have proxy setup in my local machine which probably makes it work... but what do I change for production?
Here's the API call that works locally, but not on the server if it helps:
componentDidMount() {
fetch('/api/clients/all')
.then(res => res.json())
.then((result) => {
this.setState({ clients: result });
console.log(result);
})
.then(
fetch(`/api/policy/all`)
.then(res => res.json())
.then((result) => {
this.setState({ policies: result });
console.log(result);
})
);
}

Redirect and send data from Node server back to React

I have a NodeJS server in which I'm using Express and a front-end with React. I want to know how to send data from the server to the front-end. All the solutions I've seen use a call from the front-end, then the server answers, and finally the front-end gets the data. My problem is that I don't have a call from the front-end, but a call back-end (router.get('/callback')) to back-end (router.get('/receipt/:id')). Here is the code for a better understanding.
router.get('/callback', (req,res) => {
const ref = req.query.reference;
verifyPayment(ref, (error,body)=>{
if(error){
//handle errors appropriately
console.log(error)
return res.redirect('/payment/error');
}
response = JSON.parse(body);
const data = _.at(response.data, ['reference', 'amount','customer.email', 'metadata.full_name']);
[reference, amount, email, full_name] = data;
newDonor = {reference, amount, email, full_name};
const donor = new Donor(newDonor);
donor.save().then((donor)=>{
console.log("--------------- donor" + donor);
if(!donor){
return res.redirect('/payment/error');
}
res.redirect('/payment/receipt/' + donor._id);
}).catch((e)=>{
res.redirect('/payment/error');
});
});
});
router.get('/receipt/:id', (req, res)=>{
const id = req.params.id;
Donor.findById(id).then((donor)=>{
if(!donor){
res.redirect('/payment/error')
}
// I'VE TRIED THIS
//res.redirect('http://localhost:3000/#' + donor.full_name);
/*
AND THIS
console.log(donor.full_name);
const resp = axios.post('http://localhost:3000', {params: {donor.full_name}});
console.log(resp.data);
*/
}).catch((e)=>{
res.redirect('/payment/error')
});
});
Now what I want is to come back to the front-end (a index.js using React) and get the data and show it. Any idea?????
You need to understand how the data pass between the Node server and your React App.
We use JSON objects to pass the data server to the client (look for REST APIs for more info)
Try this in your server
router.get('/receipt/:id', (req, res)=>{
const id = req.params.id;
Donor.findById(id).then((donor)=>{
if(!donor){
res.redirect('/payment/error')
}
//How to send the data
res.status(200).json({
message: "Data returned Successfully",
Fullname:"donor.full_name"
});
}).catch((e)=>{
res.redirect('/payment/error')
});

How to check for Redis Cache connection status from nodejs

I have been working on setting up a cache server for my nodejs application.
Below is my project I am working on. Simple one.
I have an external API that gives me a JSON response for a GET request.
I want to store those key and JSON (value) in a redis cache server. And I am able to do that.
Now when the GET request is called it comes to my node URL --> External API <-- JSON as response (which is stored in the cache).
For next request if the same GET comes, it goes to cache to fetch the key/value pair.
But here, if my cache server is not reachable or available, I have to go to API again to fetch the value.
I tried the code like below and it is failing when the Cache server is shutdown. How do I do a if-loop for getting the connection status of the redis cache server?
Below is my controller.js
function getRedisCacheConnection(){
const REDIS_PORT = process.env.PORT || 6379;
const client = redis.createClient(REDIS_PORT);
client.on('connect', function() {
console.log('Redis client connected');
console.log(`${client.connected}`);
});
client.on('error', function (err) {
console.log('Something went wrong ' + err);
})
return client;
}
exports.getCityCode = (req,res)=>{
var originCity = req.query.origincity;
var originState = req.query.originstate;
function setReponse(originCity, response){
return response;
}
const options = {
method: 'GET',
uri: `http://webapi.external.com/api/v3/locations?name=${originCity}`,
headers: {
'Content-Type': 'application/json'
}
}
request(options).then(function (response){
res.status(200).send(setReponse(originCity, response));
const client1 = getRedisCacheConnection();
console.dir("setting key to Cache " + originCity);
client1.setex(originCity, 3600, response);
});
}
exports.Cache = (req,res,next) => {
const originCity = req.query.origincity;
function setReponse(originCity, response){
return response;
}
const client1 = getRedisCacheConnection();
client1.get(originCity, (err,data) =>{
if(err) throw err;
if(data !== null){
console.dir(originCity + " Getting Key from Cache");
res.status(200).send(setReponse(originCity,data));
}
else{
next();
}
});
}
Here is my router.js
app.get('/citycode/', city.Cache, city.getCityCode);
you are throwing an error:
if(err) throw err;
Log the error and don't create an exception.

Consume sequence of REST from same client

Currently I am consuming REST API which requires sequential call to set authentication.
//Set User
http://localhost:8081/user username
//Get Authentication
http://localhost:8081/password password
The above sequential calls are working perfectly from Browser and Postman. But when I tried to call this from Node JS using axios.get(), server was treating this 2 request as completely different request and throwing an error like "Wrong Auth Sequence".
Is that somehow we need to explicitly mention headers to say that request coming from same client? If yes please help on this.
app.get('/', (req, res) => {
let api = `${Url}/user name ${username}`;
console.log('api - ' + api);
//Set Username
axios
.get(api)
.then(response => {
console.log(response);
response.data.includes('USER SET') ? setPassword() : console.log(res.data);
})
.catch(err => console.log(err));
res.send('Hello Word');
});
setPassword = () => {
let api = `${Url}/password ${password}`;
console.log('api - ' + api);
axios
.get(api)
.then(res => {
console.log('success: ' + res.data);
})
.catch(err => console.log('SetPasswordError' + err));
};
The application you are trying to code for is not really a RESTful API and it is expecting you to keep the connection open for multiple requests.

Categories

Resources