Backend Node routes not working after heroku deployment - node.js

I have recently deployed my node.js backend using Heroku but now it seems like my routes don't work anymore. It always goes through my error route to return "Could not find this route." This did not happen when I was using localhost whilst developing.
app.js:
const express = require('express');
const bodyParser = require('body-parser');
const HttpError = require('./models/httpError');
const questionRoutes = require('./routes/questionRoutes');
const app = express();
app.use(bodyParser.json());
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept, Authorization'
);
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PATCH, DELETE');
next();
});
app.use('/api/questions', questionRoutes);
app.use((req, res, next) => {
console.log(req.url);
const error = new HttpError('Could not find this route.', 404);
throw error;
});
app.use((error, req, res, next) => {
if (res.headerSent) {
return next(error);
}
res.status(error.code || 500);
res.json({ message: error.message || 'An unknown error occurred!' });
});
app.listen(process.env.PORT || 5000);
I am not using any environment variables. Here is the heroku link to my backend: https://mealoftheday.herokuapp.com/
Any help would be appreciated!

router.get('*', (request, response) => {
response.sendFile(path.join(__dirname, 'etsa2/build', 'index.html'));
});
Add this file to your routes my issue was solved hope yours too get solved

Related

CORS blocking my node server from react app localhost

Tried everything I could find on here in regards to setting up cors for my node server. Tried aliasing my localhost and that doesn't seem to work either. Also tried using the CORS unblock extension.
error: localhost/:1 Access to fetch at
'http://localhost:8080/api/login' from origin 'http://localhost:3000'
has been blocked by CORS policy: Response to preflight request doesn't
pass access control check: It does not have HTTP ok status.
:8080/api/login:1 Failed to load resource: net::ERR_FAILED
im trying to use magic link authentication in my react app. I got this POST request being made to my node server
const res = await fetch(`http://localhost:8080/api/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer ' + didToken,
},
});
my server code is
const express = require("express");
const cors = require("cors");
const { Magic } = require('#magic-sdk/admin');
require('dotenv').config();
const app = express()
const magic = new Magic(process.env.MAGIC_SECRET_KEY);
app.use("*", (req, res) => res.status(404).json({ error: "not found" }));
// Allow requests from client-side
app.use(cors({origin: process.env.CLIENT_URL}));
app.all('*', (req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Credentials', 'true');
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept, Authorization'
);
res.sendStatus(200);
next();
});
app.post('api/login', async (req, res) => {
console.log("login fired")
try {
const didToken = req.headers.authorization.substr(7);
await magic.token.validate(didToken);
res.status(200).json({ authenticated: true });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
module.exports = app
app.use(cors({origin: process.env.CLIENT_URL}));
I'd be curious what this URL is. If you want an open CORS policy you don't need to set anything any there.
Put a "/" in front of this route
app.post('/api/login', async (req, res) => {
I was able to reproduce your problem locally and this server setup worked for me to fix it.
const express = require("express");
const cors = require("cors");
const port = 8080;
const app = express();
app.use(cors());
app.post("/api/login", async (req, res) => {
console.log("login fired");
try {
res.status(200).json({ authenticated: true });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(port, () => {
console.log(`Example app listening on port ${port}`);
});
module.exports = app;

How to perform PUT in Node JS

Below is my app.js code.
import bodyParser from 'body-parser';
import cors from 'cors';
import requestIp from 'request-ip';
import os from 'os';
import { AppRoutes, AuthRoutes } from './routes';
const app = express();
app.use(cors());
app.disable('x-powered-by');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use((req, res, next)=> {
const clientIp = requestIp.getClientIp(req);
logger.debug(JSON.stringify(req.socket.address()));
logger.debug(`incoming IP ${clientIp}`);
next();
});
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
next();
});
// Api Routes.
app.use('/api/login', AppRoutes);
app.use('/api', verifyToken, AuthRoutes);
export default app;
Below is my index.js code. Below code is working fine for GET and POST but its not working for PUT. Its giving an error.
You don't have permission to access /api/save-user-profile/{user-name}.
import {
getCustomersbyId
} from './controller/customer-controller';
import { Login } from './controller/login';
import {
modelEdit,
saveProfile
} from './controller/extension';
const AuthRoutes = Router();
const AppRoutes = Router();
AuthRoutes.get('/customers/', getCustomersbyId);
AuthRoutes.post('/model-entity-links/info', modelEdit);
AuthRoutes.put('/save-user-profile/:username', saveProfile);
AppRoutes.post('/', Login);
export { AuthRoutes, AppRoutes };
When I am changing PUT to POST it is working fine. But I want to do it using PUT. Am I missing here anything to configure PUT.
I have tried below code as well in app.js. But still getting same issue.
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
My saveProile code is as below.
export const saveUserProfile = (req, res) => {
logger.debug({ method: 'saveUserProfile', message: MESSAGE.ENTER });
const { username } = req.params;
const userProfileInfo = JSON.parse(JSON.stringify(req.body));
if (username && !isEmptyObject(userProfileInfo)) {
postUserProfile(username, userProfileInfo)
.then(r=>{
res.status(200).send(r.data);
})
.catch(e=>{
logger.error({ method: 'saveUserProfile', message: e.response ? JSON.stringify(e.response.data.response_message) : e });
parseError(e, res);
});
} else {
logger.error({ method: 'saveUserProfile', message: MESSAGE.ERROR_INVALID_PARAM });
parseError(MESSAGE.ERROR_INVALID_PARAM, res, true);
}
};
I have resolved this issue. It was an apache server issue where PUT and DELETE operation was restricted. We have made changes in apache configuration and it worked. Thank you all for responses.

Angular route is not working in Combined MEAN?

I created a single page app using Angular.I'm using Node/Express on the back-end. While Express is serving my static index.html correctly.
When i try to navigation to some angular route from url address bar it saying cannot get /login...
i found this question on stackoverflow it is exactly what i am saying but its not answered yet.
Angular - Routing is not working (MEAN)
Here is my code.
var path = require("path");
var express = require("express");
var mongoose = require("mongoose");
var app = express();
require('./startups/prod')(app);
// Temp.
const TempRoutes = require("./routes/temp");
mongoose.connect('mongodb://localhost:27017/node-angular', { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => {
console.log("Connected to database.");
})
.catch(() => {
console.log("Connection Failed.");
});
app.use(express.json());
app.use("/", express.static(path.join(__dirname, "dist")));
app.use((request, response, next) => {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader(
"Access-Control-Allow-Headers",
"Origin, X-Requesed-With, Content-Type, Accept,Accept-Language,Content-Language, Authorization");
response.setHeader(
"Access-Control-Allow-Methods",
"GET, POST, PATCH, PUT, DELETE, OPTIONS");
next();
});
app.use((request, response, next) => {
response.sendFile(__dirname, path.join("dist", "index.html"))
})
module.exports = app;

Why is my route not found if I use /:var/action

My app.js has the following:
const express = require('express');
const app = express();
const userRoutes = require('./api/routes/users');
// middleware - takes info passed in through the body
app.use(express.urlencoded({extended: false}));
app.use(express.json());
// middleware - adds headers to allow CORS.
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
if(req.method === 'OPTIONS') {
res.header('Access-Control-Allow-Methods', 'PUT, POST, DELETE, GET');
res.status(200).json({});
}
next();
});
// middleware - filter all requests for users to the userRoutes
app.use('/api/v1/users', userRoutes);
// middleware - catch any requests that aren't caught by previous filters
app.use((req, res, next) => {
const error = new Error('No route found');
error.status = 404;
next(error);
});
// middleware - catch any errors that happen other places in the application (DB, etc.)
app.use((error, req, res, next) => {
res.status(error.status || 500);
res.json({
error: { message: error.message }
});
});
module.exports = app;
and my userRoutes looks like this:
const express = require('express');
const router = express.Router();
const userController = require('../controllers/userController');
const gtrController = require('../controllers/gtrController');
const DAL = require('../DAL/dal');
router.get('/:userName', (req, res, next) => {
userController.getUser(req.params.userName, DAL.findOne, gtrController.getUser)
.then((result) => {
res.status(200).json(result);
})
.catch((error) => {
console.log(error);
res.status(500).json({ Error: { message: error }})
});
});
router.get('/:userName/games', (req, res, next) => {
userController.getUserStuff(req.params.userName, () => {}, gtrController.getUserStuff)
.then((result) => {
res.status(200).json(result);
})
.catch((error) => {
console.log(error);
res.status(500).json({ Error: { message: error }})
});
});module.exports = router;
If I check / and /username in Postman, I get 200's and all is right. However, when I try /username/games, I get a 404. I'm not sure why it's not hitting my userRoutes. I'm assuming it's my app.use, but I'm not finding any relevant documentation.
Thanks a bunch.
Figured it out, I think. My router.get('/:userName/games) should be router.get('/:userName\/games')

React Express Fetch Post CORS error: Response to preflight request doesn't pass access control check: It does not have HTTP ok status

I'm trying to set up a basic user signup form with React, Node, and Express, and using fetch. However, I'm getting the following errors in the Chrome console when I try and send a post request:
1) "OPTIONS http://localhost:7001/v1/register 500 (Internal Server Error)"
2) "Access to fetch at 'http://localhost:7001/v1/register' from origin 'http://localhost:3001' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status."
My eventual goal is to save the user's email and password in a database, but for now all I want is for the request to go through to the backend and have the backend log the body to make sure everything works. I've tried several different ways of setting headers, and I have no idea what's wrong. Below is the code.
Frontend form submit function:
handleSubmit(e) {
e.preventDefault();
const signUpInfo = this.state; // { email: 'test#gmail.com', password: '123' }
console.log(signUpInfo);
fetch('http://localhost:7001/v1/register', {
method: 'POST',
body: JSON.stringify(signUpInfo),
headers: {
'Content-Type': 'application/json'
}
})
.then(res => res.json())
.then(response => console.log('Success:', response))
.catch(error => console.error('Error:', error));
}
server.js
const express = require('express');
const compression = require('compression');
const cfg = require('config');
const path = require('path');
const logger = require('morgan');
const cookieParser = require('cookie-parser')
const bodyParser = require('body-parser');
const config = require('config');
const app = express();
app.use(compression());
app.use(bodyParser());
app.use(cookieParser());
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.static(path.join(__dirname, 'public')));
app.use(function(req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,DELETE");
res.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Access-Control-Allow-Headers, Content-Type, Authorization, Origin, Accept");
res.setHeader('Access-Control-Allow-Credentials', true)
next();
});
// CONTROLLERS
const userController = require('./controllers/userController.js');
// ROUTES
app.post('/v1/register', userController.register);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
app.listen('7001', function() {
console.log('API server listening on port 7001!');
});
module.exports = app;
userController.js
exports.register = async (req, res, next) => {
try {
console.log(req.body);
res.status(200).json({ status: 200, data: req.body, message: "test" });
} catch (err) {
console.log(err);
res.status(500).json({ status: 500, data: null, message: err });
}
}
All I'm looking for is for the backend console to print out the body. It works with axios and $.ajax, but not with fetch. I've also tried using a proxy server to no avail (and would like to get it to work without a proxy).
Not sure if this is relevant, but I'm using Chrome as the browser and Sequelize.
Any help would be greatly appreciated. I feel like I'm missing something fundamental. Any helpful articles to deepen my learning would be a plus!
Instead of using
const app= express();
try to use
const app=express().use('*', cors());
and remove
app.use(function(req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,DELETE");
res.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Access-Control-Allow-Headers, Content-Type, Authorization, Origin, Accept");
res.setHeader('Access-Control-Allow-Credentials', true)
next();
});
see if this works.
First Install "cors":
npm i cors
Second import "cors":
cors = reqquire("cors");
Third use "cors":
const app = express();
app.use("*", cors());

Resources