React application on node express server - how to route - node.js

I have simple express server in node:
const express = require('express')
const path = require('path')
const application = express()
const port = process.env.PORT || 80
const PUBLIC_DIR = 'public'
application.use(express.static(path.join(__dirname, PUBLIC_DIR)))
application.listen(port)
//handle 404
application.use((req, res) => {
res.send('404: Page not Found', 404)
});
//handle 500
application.use((error, req, res, next) => {
res.send('500: Internal Server Error', 500)
});
console.log(['HTTP server running on ', process.env.HOST, ' / ', port].join(''))
When I put "builded" react app into folder public, server return index.html good. But problem is in react routers.
I have routers like this:
/
/home
/about
When I go to url localhost/ - works fine, return index html with full app, but problem is when I go to /home, /about, server return 404, how to fix it? How to redirect to react route? I hope you understand me.
Thank you for any help

after you build the react try using :-
app.use(require('body-parser').json({ limit: '50mb' }));
app.use(require('body-parser').urlencoded({ limit: '50mb', extended: true, parameterLimit: 1000000 }));
app.use(express.static(path.join(__dirname, '../client')));
switch (process.env.NODE_ENV) {
case 'production':
app.use(express.static('./client/build/'));
app.use('/', express.static('./client/build/index.html'));
break;
default:
app.use(express.static('./client/'));
app.use(express.static('./', config.staticOptions));
app.use('/', express.static('./client/index.html'));
break;
}

Try to return all the routes from index.html as follows:
const express = require('express')
const path = require('path')
const application = express()
const port = process.env.PORT || 80
const PUBLIC_DIR = 'public'
application.use(express.static(path.join(__dirname, PUBLIC_DIR)))
application.listen(port)
app.use(express.static('client/build')); //use your build path my build path under the root folder is client/build
const path = require('path');
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client','build', 'index.html')); //use your build path my build path under the root folder is client/build
});
//handle 404
application.use((req, res) => {
res.send('404: Page not Found', 404)
});
//handle 500
application.use((error, req, res, next) => {
res.send('500: Internal Server Error', 500)
});
console.log(['HTTP server running on ', process.env.HOST, ' / ', port].join(''))

Related

NodeJS api not returning any response

I used this https://medium.com/weekly-webtips/create-and-deploy-your-first-react-web-app-with-a-node-js-backend-ec622e0328d7 to create React Front End and NodeJS backend. On running locally, it worked but I deployed it on Heroku. I didn't receive any response from express server api.
app.get("/test/", (request, response) => {
response.send({"name":"Hello Test!!!"});
});
my proxy setting looks like this
Result in http://localhost:3000/
Hello from the frontend!
Hello Test!!!
Result in https://react-node-js-test.herokuapp.com/
Hello from the frontend!
"proxy": "http://localhost:5000",
server.js
// Import dependencies
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const path = require('path');
// Create a new express application named 'app'
const app = express();
// Set our backend port to be either an environment variable or port 5000
const port = process.env.PORT || 5000;
// This application level middleware prints incoming requests to the servers console, useful to see incoming requests
app.use((req, res, next) => {
console.log(`Request_Endpoint: ${req.method} ${req.url}`);
next();
});
// Configure the bodyParser middleware
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
// Configure the CORs middleware
app.use(cors());
// This middleware informs the express application to serve our compiled React files
if (process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'staging') {
app.use(express.static(path.join(__dirname, 'client/build')));
app.get('*', function (req, res) {
res.sendFile(path.join(__dirname, 'client/build', 'index.html'));
});
};
// // Catch any bad requests
// app.get('*', (req, res) => {
// res.status(200).json({
// msg: 'Catch All'
// });
// });
app.get("/test/", (request, response) => {
response.send({"name":"Hello Test!!!"});
});
// Configure our server to listen on the port defiend by our port variable
app.listen(port, () => console.log(`BACK_END_SERVICE_PORT: ${port}`));
Any help would be great
// MOVE THIS BEOFRE get("*")
// Because * will handle all incoming requests
app.get("/test/", (request, response) => {
response.send({"name":"Hello Test!!!"});
});
// This middleware informs the express application to serve our compiled React files
if (process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'staging') {
app.use(express.static(path.join(__dirname, 'client/build')));
app.get('*', function (req, res) {
res.sendFile(path.join(__dirname, 'client/build', 'index.html'));
});
};

Node js response Failed to load resource: the server responded with a status of 404 (Not Found)

I'm trying to make initial connection between my node js with apache2 web server backend to my React frontend. I'm newbie at all of this and trying to make it work on local machine before deployment.
I read about CORS and solve an issue with access origin headers with it, but I can't understand what am I missing here.
the server runs and listening to port 3000
the frontend on port 3001
my frontend code is:
import React from 'react';
import axios from 'axios';
import logo from './logo.svg';
import './App.css';
export default class App extends React.Component {
state = {
persons: []
}
componentDidMount() {
axios.get(`/ping`, {
headers: {
"Access-Control-Allow-Origin": "*"
}
})
.then(res => {
const persons = res.data;
this.setState({ persons });
})
}
render() {
return (
<h1>dfdfdfdfdf{this.state.persons}</h1>
)
}
}
And My Backend code is:
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var cors = require('cors');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use(cors());
app.use('/', indexRouter);
app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
const hostname = '127.0.0.1';
const port = 3000;
// 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.use(express.static(path.join(__dirname, 'build')))
app.get('/ping', (req, res) => {
return res.send('pong')
})
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'build', 'index.html'))
})
app.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
module.exports = app;
I keep getting the errors:
Failed to load resource: the server responded with a status of 404 (Not Found)
0.chunk.js:779
Unhandled Promise Rejection: Error: Request failed with status code 404
(anonymous function) (0.chunk.js:779)
promiseReactionJob

Why is my MEVN app only showing the backend when deploying to Heroku?

My app is currently deployed online through Heroku but it is displaying the backend server rather than my Vue app.
Note: I have an if statement in app.js that serves the files only in production. I removed the if statement to see if the app would appear without environmental conditions. It did not work.
Also I have a minified Vue js folder called dist in my express directory.
Updated
The heroku method I am using is the Heroku Git Cli
$ cd my-project/
$ git init
$ heroku git:remote -a testingew
$ git add .
$ git commit -am "make it better"
$ git push heroku master
This is what I see, which is the backend response to the "/" route. The code is in app.js
app.js
The full code
const serveStatic = require("serve-static");
const path = require("path");
const express = require("express");
const app = express();
const userRoutes = require("./routes/user");
const budgetRoutes = require("./routes/budget");
const profileRoutes = require("./routes/profile");
require("dotenv/config");
const port = process.env.PORT || 3000;
const cors = require("cors");
const morgan = require("morgan");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const cookieParser = require("cookie-parser");
const sessions = require("express-session");
const MongoStore = require("connect-mongo")(sessions);
const passport = require("passport");
const passportSetup = require("./config/passport.js");
//Log when making request
app.use(morgan("combined"));
//Parse body for post request
app.use(cookieParser());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var corsOption = {
origin: true,
methods: "GET,HEAD,PUT,PATCH,POST,DELETE",
credentials: true
};
app.use(cors(corsOption));
app.use(
sessions({
secret: process.env.SESSION_COOKIEKEY,
saveUninitialized: false,
resave: false,
store: new MongoStore({
mongooseConnection: mongoose.connection
}),
cookie: {
// secure: true,
maxAge: 86400000
}
})
);
//Initialize passport
app.use(passport.initialize());
app.use(passport.session());
//Automatic route placer
app.use("/auth", userRoutes);
app.use("/api/budget", budgetRoutes);
app.use("/api/profile", profileRoutes);
app.get("/", (req, res) => {
res.send("App is on");
});
//404 error and pas to error handler
app.use((req, res, next) => {
const error = new Error("An error has occured");
error.status = 404;
next(error);
});
//Error handler
app.use((error, req, res, next) => {
//Respond Client
res.status(error.status || 500);
res.json({
error: {
message: error.message
}
});
console.log(error.message);
});
//Mongo connection
mongoose.connect(
process.env.DB_CONNECTION,
{
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false
},
() => console.log("connected to mongo atlas")
);
//Handle production
app.use(express.static(path.join(__dirname, "dist")));
// Redirect all requests to `index.html`
app.get("/*", (req, res) => {
res.sendFile(path.join(__dirname, "dist", "index.html"));
});
//Start app
app.listen(port, () => {
console.log(`Server is on port ${port}`);
});
Vue Router
Note: I am also using route navigation guards within components if that means anything
import Vue from "vue";
import VueRouter from "vue-router";
//import axios from "axios";
Vue.use(VueRouter);
const routes = [
{
path: "/",
name: "login",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () =>
import(/* webpackChunkName: "about" */ "../views/Login.vue")
},
{
path: "/userprofile",
name: "userProfile",
component: () => import("../views/userProfile.vue"),
meta: {
requireAuth: true
}
},
{
path: "/budgetform",
name: "form",
component: () => import("../views/budgetForm.vue"),
meta: {
requireAuth: true
}
},
{
path: "/mybudget",
name: "myBudget",
component: () => import("../views/myBudget.vue"),
meta: {
requireAuth: true
}
}
];
const router = new VueRouter({
mode: "history",
base: process.env.BASE_URL,
routes
});
export default router;
File directory of Express
Hopefully this helps
EDIT
Based on your edit showing your Express app, you need to remove everything between
app.use("/api/profile", profileRoutes);
and Mongo. The app can't run if you do other things on the route instead. The "App is on" and error checking stuff is blocking your app. I don't think you mean to run the error on every route, but that's what's happening. I would suggest browsing some Express tutorials and starting from scratch to try to understand why that can't work.
ORIGINAL
Try to replace everything above app.listen with:
// Serve static assets
app.use(express.static(path.join(__dirname, 'dist')));
// Redirect all requests to `index.html`
app.get('/*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist', 'index.html'));
})
Your wildcard match was wrong, and would only match file paths that begin with a dot, path.join wasn't used correctly, there should be no slash literals. I changed some other syntax too. If this doesn't completely fix the issue, there are many possibilities for error that are beyond the scope of this question:
1) directory structure
2) .gitignore
3) vue-router
4) package.json start script

Node.js - Specifying URL in Heroku yields internal server error, running locally works fine

I'm having some issues with my application after it's been deployed to heroku. When I specify the URL, or refresh the browser on a page OTHER than the homepage I am getting an "Internal Server error" and the page doesn't load. However when I click the links which naviagte me to those pages from the home page it works fine. When I run the server locally it does not give me this error.
Based on my research this is probably an error on the server side. Here is my code:
Node.js backend
const express = require("express");
const bodyParser = require("body-parser");
const passport = require("passport");
const users = require("./routes/api/users");
const actions = require("./routes/api/dbActions");
const app = express();
// Bodyparser middleware
app.use(
bodyParser.urlencoded({
extended: false
})
);
app.use(bodyParser.json());
// Passport middleware
app.use(passport.initialize());
// Passport config
require("./config/passport")(passport);
// Routes
app.use("/api/users", users);
app.use("/api/dbActions", actions);
// Serve static assets if in production
if (process.env.NODE_ENV === 'production') {
// Set static folder
app.use(express.static('client/build'));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
});
}
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server running on port ${port} !`));
Any idea why this might be happening?
Thanks!!
In my server.js file I included the following:
const path = require('path');
Which seems to have worked for me.

Redirected you too many times - Express/node on Heroku

Using Express/node on Heroku I get an error: Redirected you too many times or net::ERR_TOO_MANY_REDIRECTS in the console.
I'm new to Express and I tried to add a redirect so all http requests on my two custom domains get redirected to https. This is what's breaking the site. If any has ideas to fix it that would be amazing!
var express = require('express');
const path = require('path');
var app = express();
// process.env.PORT gets the port for Heroku or goes to 3000
const PORT = process.env.PORT || 3000;
app.enable('trust proxy');
// in production on Heroku - re-route everything to https
if (process.env.NODE_ENV==="production") {
app.use((req, res, next) => {
if (req.header['x-forwarded-proto'] !== 'https') {
res.redirect('https://' + req.hostname + req.url);
} else {
next()
}
})
}
app.use(express.static(path.join(__dirname, '/public')));
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'public/index.html'));
});
app.listen(PORT, function() {
console.log('Express server is up on port:' + PORT);
});
Use req.header('x-forwarded-proto') instead.
And to make sure, console.log process.env.NODE_ENV and req.header('x-forwarded-proto'), req.hostname, req.url to see your redirection works as expected

Resources