fullstackreact / food-lookup-demo

A demonstration of using `create-react-app` with a server
MIT License
1.18k stars 372 forks source link

Cannot get route when deployed to heroku #49

Closed borisyordanov closed 6 years ago

borisyordanov commented 6 years ago

Your config has been working great so far locally. When i deployed it to Heroku i started getting the following issue:

If i go to https://enjoy-copenhagen-dev.herokuapp.com everything is fine, i can navigate through the app, no issues there.

If i go to https://enjoy-copenhagen-dev.herokuapp.com/api or whichever one of my api post and get endpoints everything works.

If i try to open any other route i get Cannot GET /route-i-tried-to-open. image

My server.js

const cors = require('cors');
const path = require('path');
const express = require('express');
const nodemailer = require('nodemailer');
const bodyParser = require('body-parser');
const app = express();

const mail = require('./emailSenders');

app.use(cors());

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'DELETE, PUT, GET, POST');
  res.header(
    'Access-Control-Allow-Headers',
    'Origin, X-Requested-With, Content-Type, Accept'
  );
  next();
});

// support json encoded bodies
app.use(bodyParser.json());
// support encoded bodies
app.use(bodyParser.urlencoded({ extended: false }));

app.set('port', process.env.PORT || 3001);

// Express only serves static assets in production
if (process.env.NODE_ENV === 'production') {
  app.use(express.static('client/build'));
}

app.get('/api', (req, res) => {});
app.post('/api/createCustomer', (req, res) => {});
app.post('/api/retrieveCustomer', (req, res) => {});
app.post('/api/createCharge', (req, res) => {});
app.post('/api/sendEmail', (req, res) => {});

app.listen(app.get('port'), () => {
  console.log(`Find the server at: http://localhost:${app.get('port')}/`); // eslint-disable-line no-console
});

package.json

{
    "name": "lookup-server",
    "version": "0.0.1",
    "private": true,
    "dependencies": {
        "babel-core": "6.14.0",
        "body-parser": "^1.18.2",
        "cors": "^2.8.4",
        "ejs": "^2.5.7",
        "email-templates": "^3.5.2",
        "express": "4.13.3",
        "fs": "0.0.2",
        "node-schedule": "^1.3.0",
        "nodemailer": "^4.4.2",
        "sql.js": "0.3.2",
        "stripe": "^5.4.0"
    },
    "scripts": {
        "start": "concurrently \"npm run server\" \"npm run client\"",
        "server": "node server.js",
        "client": "node start-client.js",
        "dev": "echo \"This command has been deprecated. Use 'npm start'\" && exit 1",
        "lint": "eslint ."
    },
    "devDependencies": {
        "concurrently": "3.1.0",
        "eslint": "^3.19.0",
        "eslint-config-airbnb": "14.1.0",
        "eslint-plugin-import": "2.2.0",
        "eslint-plugin-jsx-a11y": "4.0.0",
        "eslint-plugin-react": "6.9.0"
    }
}

file structure image

Please help me fix this!

borisyordanov commented 6 years ago

The solution is to make sure you have this in your server:

if (process.env.NODE_ENV === 'production') {
    app.use(express.static('client/build'));
}

And also add this:

app.get('*', (request, response) => {
    response.sendFile(path.join(__dirname, 'client/build', 'index.html'));
});

You can't serve a static single page application with dynamic routes without an express server set up this way.

sudhaparayil commented 6 years ago

i have the same issue ..please help me

`const express = require('express'); const mongoose = require('mongoose'); const bodyParser = require('body-parser'); const fileUpload = require('express-fileupload'); const items = require('./routes/api/items') const app = express(); const path = require('path');

//middleweare app.use(bodyParser.json()); app.use(fileUpload()); // DB Config const db = require('./config/keys').mongoURI;

// Connect to Mongo mongoose .connect(db) .then(() => console.log('MongoDB Connected...')) .catch(err => console.log(err));

// Use Routes app.use('/api/items', items);

//image upload using express-fileupload app.post('/upload', (req, res, next) => { console.log(req.files.file.name); let imageFile = req.files.file;

var imagename = Date.now()+'_'+req.files.file.name;

imageFile.mv(./client/src/upload/+imagename, function(err) { if (err) { return res.status(500).send(err); } const newItem = new Item({ name: req.body.name, filename: imagename, });

newItem.save().then(item => res.json(item));

});

})

//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 started on port ${port}));`

borisyordanov commented 6 years ago

@sudhaparayil Try this:

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'));
});
adamewhite commented 6 years ago

I'm having a similar problem. How do I configure the API port to work on Heroku?

The solution above did not work.

borisyordanov commented 6 years ago

@adamewhite Share your code? Why isn't it working?

am-you commented 5 years ago

have similar issue here. backend file and client file seperate where i have a server.js in the backend i run the whole concurrently but not working when deployed to heroku my form is in a component in client folder here is my setup : (works in localhost with a slightly different setup but cant get it to work in heroku)

const creds = require('./config/config'); const express = require('express'), path = require('path'), nodeMailer = require('nodemailer'), bodyParser = require('body-parser'), cors = require ('cors'), cors_proxy = require('cors-anywhere');

const app = express();

app.use(function (req, res, next) {

// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', '*');

// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');

// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');

// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);

// Pass to next layer of middleware
next();

});

app.use(cors()); app.set('view engine', 'ejs'); app.use(express.static('src')); app.use(bodyParser.urlencoded({extended: true})); app.use(bodyParser.json());

const PORT = process.env.PORT || 8888; const host = process.env.HOST ? '0.0.0.0' : '127.0.0.1';

app.get('/', function (req, res) { res.render('form'); });

app.post('/', function (req, res) {

const firstName = req.params.firstName;
const lastName = req.params.lastName;
const subject = req.params.subject;
const email = req.params.email;
const message = req.params.message;

const content = `firstName: ${firstName} \n lastName: ${lastName} \n email: ${email} \n subject: ${subject} message: ${message} `;

const transporter = nodeMailer.createTransport({

    host: 'smtp.gmail.com',
    port: 465,
    secure: true,
    auth: {
        user: creds.user,
        pass: creds.str
    }
});

const mail = {

    from: email,
    to: 'myemailadress@gmail.com',  
    subject: 'New Message from Contact Form',
    text: content
};

transporter.sendMail(mail, function (err, info) {

    if (err) {
        console.log(err);
        res.json({message: "message not sent: an error occured; check the server's console log"});
    } else {
        res.json({message: `message sent: ${info.messageId}`});
    }

    res.send(201, req.params);
    transporter.close();

});

});

if (process.env.NODE_ENV === "production") { app.use(express.static('client/build')); }

app.get('*', function (req, res) {
    res.sendFile(path.join(__dirname, "client", "build", "index.html"));
});

cors_proxy.createServer({
    originWhitelist: [], // Allow all origins
    requireHeader: ['origin', 'x-requested-with'],
    removeHeaders: ['cookie', 'cookie2']
}).listen(PORT, host, function () {
    console.log('Running CORS Anywhere on ' + host + ':' + PORT);
});
IkennaU commented 4 years ago

I think i have adopted all this approach, yet i get this error......

error 1}}.....Refused to load the image 'https://still-beach-83217.herokuapp.com/favicon.ico' because it violates the following Content Security Policy directive: "default-src 'none'". Note that 'img-src' was not explicitly set, so 'default-src' is used as a fallback.

error 2}}...still-beach-83217.herokuapp.com/:1 Failed to load resource: the server responded with a status of 404 (Not Found)

this are my codes.... ON server.js...

const express = require("express"); const connectDB = require("./config/db"); const path = require("path"); const app = express();

// Connect to Database connectDB(); // init middleware app.use(express.json({ extended: false })); // define routes

app.use("/api/users", require("./routes/users")); app.use("/api/auth", require("./routes/auth")); app.use("/api/contacts", require("./routes/contacts"));

// serve static assets in production if (process.env.NODE.ENV === "production") { app.use(express.static("client/build")); app.get("*", (req, res) => { res.sendFile(path.resolve(__dirname, "client", "build", "index.html", "favicon.ico")); }); } const PORT = process.env.PORT || 5000;

app.listen(PORT, () => console.log(Server started on port ${PORT})); CODE ON INDEX.JS.....

<!DOCTYPE html>

React App

ON manifest.json.....

{ "short_name": "React App", "name": "Create React App Sample", "icons": [ { "src": "favicon.ico", "sizes": "64x64 32x32 24x24 16x16", "type": "image/x-icon" }, { "src": "logo192.png", "type": "image/png", "sizes": "192x192" }, { "src": "logo512.png", "type": "image/png", "sizes": "512x512" } ], "start_url": ".", "display": "standalone", "theme_color": "#000000", "background_color": "#ffffff" }

pls help.....Thanks

zeeshanweb-official commented 4 years ago

i do have similar error... express server deployed on heroku is serving my static files fine... like my homepage and all the routing thing is working but i do have some apis to call them with axios... they are generating error 404. i dont know why this is my first time facing such issues.

jitto21 commented 4 years ago

@sudhaparayil Try this:

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'));
});

What is 'client' and 'build' ??

kawaiiyoshiyuki commented 4 years ago

Client is a folder with frontend (react) part of the stack and build is the folder where the static pages should be found after react is built. But I wonder when the build folder should be created?:/

tayyabferozi commented 4 years ago

@sudhaparayil Try this:

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'));
});

Do we have to change the "client/build" part according to our files and folders?

purveshshende2 commented 4 years ago

I have same problem

server_file.txt registerfile.txt

jon424 commented 4 years ago

I'm having an issue when reloading a page that is not the homepage. All that displays is the API request in JSON format. This is a PERN stack app deployed to Heroku. It works fine on my localhost, just not when deployed. When the user clicks on the “Earth Nights #1” card on the homepage, the user is taken to the content page for that particular playlist (https://earth-nights.herokuapp.com/episode/1). That’s great, but when I refresh the page, I only see the API info for that page:

{
"id": 1,
"title": "Earth Nights #1",
"date_of_show": "April 24, 2020",
"teaser": "Welcome to the first Earth Nights playlist!",
"card_image": "https://cdn.technologynetworks.com/tn/images/thumbs/jpeg/640_360/the-psychedelic-revolution-in-psychiatry-333007.jpg"
}

Here is the live site: https://earth-nights.herokuapp.com/

Here is my server code: indexjs.txt

guillevazquezg commented 3 years ago

I'm having the exact same problem. Deploying a MERN App with Heroku is a nightmare.

guygreenleaf commented 3 years ago

Having the exact same problem here. Any fix to this?

pnguye11 commented 3 years ago

Having the exact same problem here. Any fix to this?

If you're using axios, go into the index.js file of your src/api. Change the baseURL from pointing to your local server (localhost:5000) to the url that was given to you by heroku.

seopoint35 commented 3 years ago

i do have similar error... express server deployed on heroku is serving my static files fine... like my homepage and all the routing thing is working but i do have some apis to call them with axios... they are generating error 404. i dont know why this is my first time facing such issues.

i am facing same problem can you help me

Vaibhav-Thalanki commented 7 months ago

i do have similar error... express server deployed on heroku is serving my static files fine... like my homepage and all the routing thing is working but i do have some apis to call them with axios... they are generating error 404. i dont know why this is my first time facing such issues.

i am facing same problem can you help me

Same here, did you find a solution yet?