So I did the deployment exactly like here: https://medium.com/#rksmith369/how-to-deploy-mern-stack-app-on-aws-ec2-with-ssl-nginx-the-right-way-e76c1a8cd6c6
But my React App wont load, instead it gets blocked(Content Security Policy).
Maybe something with nginx? Or is my React app broken? I was searching the whole day so I thought I give it a try and ask for help.
Edit:
New Problem my homepage gets loaded, but on all of the other sites I get a 404 if I reload...
New Server.js
const express = require('express')
const mongoose = require('mongoose')
const http = require('http')
const socketio = require('socket.io')
const path = require('path')
const bodyParser = require('body-parser')
require('dotenv').config()
const app = express()
// Body Parser Middleware:
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(express.static(path.join(__dirname, 'client/build')))
mongoose
.connect(process.env.DATABASE, {
useNewUrlParser: true,
useFindAndModify: false,
useUnifiedTopology: true,
useCreateIndex: true,
})
.then(() => console.log('DB connected'))
.catch(() => console.log('DB Connection Error:', err))
const server = http.createServer(app)
const io = socketio(server, {
cors: {
origin: process.env.CLIENT_URL,
methods: ['GET', 'POST'],
},
})
// Assign socket object to every request
app.use(function (req, res, next) {
req.io = io
next()
})
// Routes
const orderRoutes = require('./routes/order')
// Middleware
app.use('/api', orderRoutes)
const PORT = process.env.PORT || 5000
server.listen(PORT, console.log(`Server lรคuft auf Port: ${PORT}`))
React App package.json
{
"name": "client",
"version": "0.1.0",
"private": true,
"proxy": "http://localhost:5000",
"dependencies": {
"#testing-library/jest-dom": "^5.11.10",
"#testing-library/react": "^11.2.6",
"#testing-library/user-event": "^12.8.3",
"antd": "^4.15.6",
"axios": "^0.21.1",
"lodash": "^4.17.21",
"react": "^17.0.2",
"react-bootstrap": "^1.5.2",
"react-dom": "^17.0.2",
"react-redux": "^7.2.3",
"react-router-bootstrap": "^0.25.0",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"react-slick": "^0.28.1",
"react-toastify": "^7.0.3",
"redux": "^4.0.5",
"redux-devtools-extension": "^2.13.9",
"redux-thunk": "^2.3.0",
"socket.io-client": "^4.1.2",
"web-vitals": "^1.1.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
the problem is not with your React App or the your server, but its with your helmet configuration.
Update your CORS configuration to provide a valid content security policy. For example
app.use(helmet({
contentSecurityPolicy: {
directives: {
...helmet.contentSecurityPolicy.getDefaultDirectives(),
'script-src': ["'self'", 'https://apis.google.com'],
'style-src': ["'self'", "'unsafe-inline'", 'https://fonts.googleapis.com'],
'connect-src': ["'self'", 'https://accounts.google.com' ],
'img-src': ['https:', 'data:'],
},
},
}));
To read more about CSP checkout this
MDN doc
helmet
Related
I am trying to get my react frontend to establish connection with my node backend. The node backend works when I am using PostMan. I have gone through most of the options suggested on this plateform but none is helping.
This is the Fetch request in react
import axios from 'axios'
// Sending Request to register User
let URL = "/user/"
const register = async (userData) => {
let response = await axios.post(URL + 'register', userData)
if (response.data) {
localStorage.setItem('user', JSON.stringify(response.data))
}
return register.data
}
This is my package.json file for the react:
{
"name": "frontend",
"version": "0.1.0",
"private": true,
"options": {
"allowedHosts": [
"localhost",
".localhost"
],
"proxy":"http://localhost:8000"
},
"dependencies": {
"#reduxjs/toolkit": "^1.8.6",
"#testing-library/jest-dom": "^5.16.5",
"#testing-library/react": "^13.4.0",
"#testing-library/user-event": "^14.4.3",
"axios": "^1.1.2",
"bootstrap": "^5.2.2",
"react": "^18.2.0",
"react-bootstrap": "^2.5.0",
"react-dom": "^18.2.0",
"react-icons": "^4.4.0",
"react-redux": "^8.0.4",
"react-router-dom": "^6.4.2",
"react-scripts": "5.0.1",
"react-toastify": "^9.0.8",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
This is my Node index.js file to handle the post request
require('dotenv').config()
const express = require('express')
const bodyParser = require('body-parser')
const { connectToDb } = require('./database/db');
const cors = require('cors')
const port = process.env.PORT || 5000
connectToDb();
const app = express()
app.use(express.json())
app.use(bodyParser.urlencoded({extended:true}))
app.use(cors())
app.use('/user', require('./routes/userRoutes'))
app.listen(port, () => {
console.log(`Server is running on ${port}`)
})
What should am I not doing right?
I get an error where the heroku page in browser just return this error Cannot GET / and when I am console log , it is saying 404 error but i have no idea on the error, already change the HTTPS to HTTP in server index.js .Any there change that I need to make ? Already tried other solution also not working fine it still have an error with the server, how can i fix this. Below i attach server index.js and my package.json.
server index.js
const express = require("express");
const app = express();
const http = require("https");
const { Server } = require("socket.io");
const cors = require("cors");
const server = http.createServer(app);
const user = [];
app.use(cors());
const io = new Server(server, {
cors: {
origin: "http://testing.herokuapp.com/" + (process.env.PORT || 5000),
methods: ["GET", "POST"],
},
});
io.on("connection", (socket) => {
user.push(socket.id);
socket.on("join_room", (data) =>{
socket.join(data);
})
socket.on("send_message", (data) => {
let new_data = {user_id: data.id, msg: data.text};
socket.to(data.room).emit("receive_message", new_data);
})
});
server.listen(process.env.PORT || 5000, () => {
console.log("SERVER OK");
});
package.json
{
"name": "client",
"version": "0.1.0",
"private": true,
"dependencies": {
"#testing-library/jest-dom": "^5.16.4",
"#testing-library/react": "^13.2.0",
"#testing-library/user-event": "^13.5.0",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-scripts": "5.0.1",
"socket.io-client": "^4.5.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"autoprefixer": "^10.4.7",
"postcss": "^8.4.14",
"react-router-dom": "^6.3.0",
"tailwindcss": "^3.0.24"
}
}
FIX: after following some advice I ditched the setupProxy and put the full API urls into the axios request. This threw a cors error so I imported CORS & added app.use(cors()) into my index.js & when I redeployed the app ran as intended
I am trying to deploy a MERN stack practise project for the first time. I am quite a new coder.
My project works perfectly fine in development/locally. My React app running on localhost:3000 connects to the Node/Express/MongoDB Atlas API that I deployed to Heroku & can make requests successfully.
However when I open the deployed Netlify app it fails to load any data & the Heroku logs show no activity which suggests it's not connecting to the backend at all.
Here are some bits of code that may be relevant:
-----------Backend---------------
environment.js (info in <> redacted)
export const dbURI = process.env.MONGODB_URI || 'mongodb+srv://<name>:<password>#festivalist.iyq41.mongodb.net/festivalist?retryWrites=true&w=majority'
export const port = process.env.PORT || 4000
export const secret = process.env.SECRET || '<secret>'
index.js
import express from 'express'
const app = express()
import mongoose from 'mongoose'
import router from './config/router.js'
import { port, dbURI } from './config/environment.js'
const startServer = async () => {
try {
await mongoose.connect(dbURI, { useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true })
console.log('๐ Database has connected successfully')
app.use(express.json())
app.use((req, _res, next) => {
console.log(`๐จ Incoming request: ${req.method} - ${req.url}`)
next()
})
app.use('/api', router)
app.listen(port, () => console.log(`๐ Express is up and running on port ${port}`))
} catch (err) {
console.log('๐ Something went wrong starting the app')
console.log(err)
}
}
startServer()
package.json
{
"name": "sei-project-three",
"version": "1.0.0",
"main": "index.js",
"dependencies": {
"bcrypt": "^5.0.1",
"dotenv": "^10.0.0",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"mongo": "^0.1.0",
"mongoose": "^5.12.0",
"nodemon": "^2.0.14"
},
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"seed": "node db/seeds.js",
"dev": "nodemon",
"start": "node index.js"
},
"devDependencies": {
"eslint": "^7.22.0"
},
"engines": {
"node": "16.8.0"
}
}
-------------Front end --------------
setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware')
module.exports = function (app) {
app.use(createProxyMiddleware('/api', { target: 'https://festivalist-api.herokuapp.com', "changeOrigin": true }))
}
example request
const ArtistIndex = () => {
const [artists, setArtists] = useState([])
useEffect(() => {
const getData = async () => {
const { data } = await axios.get('/api/artists')
setArtists(data)
}
console.log('artists2', artists)
getData()
}, [])
package.json
{
"name": "client",
"version": "0.1.0",
"private": true,
"dependencies": {
"axios": "^0.21.1",
"http-proxy-middleware": "^1.0.5",
"mapbox-gl": "^2.2.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-map-gl": "^5.2.5",
"react-mapbox-gl": "^5.1.1",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"sass": "^1.42.1",
"semantic-ui-css": "^2.4.1",
"semantic-ui-react": "^2.0.3"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"#typescript-eslint/eslint-plugin": "^4.25.0",
"#typescript-eslint/parser": "^4.25.0",
"babel-eslint": "^10.1.0",
"eslint": "^7.27.0",
"eslint-config-react-app": "^6.0.0",
"eslint-plugin-flowtype": "^5.7.2",
"eslint-plugin-import": "^2.23.3",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-react": "^7.23.2",
"eslint-plugin-react-hooks": "^4.2.0"
}
}
Some notes:
I have whitelisted all IP addresses in MongoDB Atlas 0.0.0.0/0
I'm unsure why but I have to put '/api/' on the end of the heroku api url to get the data ie: https://festivalist-api.herokuapp.com/api/festivals
I added Config Vars in Heroku but I think that stopped my app from working locally so I deleted them. Also not fully sure I understand what they do.
I have been trying to deploy this for days now so any advice would be a help or any troubleshooting tips since I am new to coding! Thanks
You have to put '/api' in at the end of heroku API because that's what you've used in your backend index.js app.use('/api', router)
The problem seems like something to do with the middle-wear setupProxy.js since you can ping the API already. One workaround is to just update your requests to use the full URI. i.e
const ArtistIndex = () => {
const [artists, setArtists] = useState([])
useEffect(() => {
const getData = async () => {
const { data } = await axios.get('https://festivalist-api.herokuapp.com/api/artists')
setArtists(data)
}
console.log('artists2', artists)
getData()
}, [])
I have created a sample project in reactjs and using node for backend. I have build react project with webpack. Now I want to render my react app from the server-side but got stuck with an error:
const express = require('express');
const path = require('path');
const logger = require('morgan');
const bodyParser = require('body-parser');
const cors = require('cors');
const { renderToString } = require("react-dom/server");
const { StaticRouter } = require("react-router-dom")
const React = require("react");
const App = require('./src/App')
const session = require('express-session');
const routes = require('./server/index');
const port = process.env.PORT || 3000;
const app = express();
app.use(express.static(path.join(__dirname, 'dist')));
app.use(cors());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
//app.use(cookieParser());
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');
// 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();
});
// end
app.use('/', routes);
app.use((req, res, next) => {
var err = new Error('Not Found');
err.status = 404;
next(err);
});
if (app.get('env') === 'development') {
app.use((err, req, res, next) => {
res.status(err.status || 500);
res.json({
message: err.message,
error: err,
});
});
}
app.use((err, req, res, next) => {
res.status(err.status || 500);
res.json({
message: err.message,
error: {},
});
});
router.get("*", (req, res) => {
// Render the component to a string.
const html = ReactDOMServer.renderToString(
<StaticRouter location={req.url} context={context}>
<App />
</StaticRouter>
);
const finalDocument =`<html>
<head>
<title>Your App Title</title>
</head>
<body>
<div id="root">${html}</div>
</body>
</html>
`;
res.send(finalDocument);
});
app.listen(port, () => {
console.log('Api Server running on port' + port);
});
module.exports = app;
package.json
{
"name": "ssrnodereact",
"version": "0.1.0",
"private": true,
"dependencies": {
"#material-ui/core": "^4.12.2",
"#material-ui/icons": "^4.11.2",
"#testing-library/jest-dom": "^5.14.1",
"#testing-library/react": "^11.2.7",
"#testing-library/user-event": "^12.8.3",
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"cryptr": "^6.0.2",
"dotenv": "^10.0.0",
"express": "^4.17.1",
"express-session": "^1.17.2",
"formik": "^2.2.9",
"helmet": "^4.6.0",
"morgan": "^1.10.0",
"nodemailer": "^6.6.3",
"path": "^0.12.7",
"pg": "^8.7.1",
"prettier": "^2.3.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-ga": "^3.3.0",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"typescript": "^4.3.5",
"web-vitals": "^1.1.2",
"yup": "^0.32.9"
},
"scripts": {
"build": "webpack --mode production",
"start": "npm run build && nodemon server.js",
"test": "react-scripts test",
"eject": "react-scripts eject",
"format": "prettier --write ./**/*.{js,jsx,ts,tsx,css,md,json,html} --config ./.prettierrc"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"#babel/core": "^7.15.0",
"#babel/preset-env": "^7.15.0",
"#babel/preset-react": "^7.14.5",
"babel-loader": "^8.2.2",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^3.2.0",
"react-hot-loader": "^4.13.0",
"ts-loader": "^8.3.0",
"webpack": "^4.44.0",
"webpack-cli": "^4.7.2",
"webpack-dev-server": "^3.11.2"
}
}
Got following error:
error
I have tried the following solutions but have not been able to resolve the error:
React Serverside rendering Unexpected token, JSX and Babel
I'm not sure if React is a framework that suits your needs. Server-side rendering can be accomplished much easier and more efficiently using a framework like NextJS.
You can check this plugin and it has examples for you to do the SSR easily.
I have this folder tree:
This is my actual app.yaml:
runtime: nodejs
env: flex
manual_scaling:
instances: 1
resources:
cpu: 1
memory_gb: 0.5
disk_size_gb: 10
handlers:
- url: /api/.*
static_files: server/server.js
upload: server/server.js
- url: /
static_files: www/build/index.html
upload: www/build/index.html
- url: /
static_dir: www/build
But always, when I try to deploy the app with the following command: gcloud app deploy --stop-previous-version the process end whit this error:
Step #0: Application detection failed: Error: node.js checker: Neither "start" in the "scripts" section of "package.json" nor the "server.js" file were found.
The server/package.json is:
{
"name": "server",
"version": "1.5.2",
"engines": {
"node": "13.x"
},
"main": "server.js",
"description": "ConstaFAST server",
"scripts": {
"start": "node server.js"
},
"license": "MIT",
"dependencies": {
"#hapi/joi": "^16.1.7",
"base64-img": "^1.0.4",
"bcryptjs": "^2.4.3",
"body-parser": "^1.19.0",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"generate-password": "^1.4.2",
"jsonwebtoken": "^8.5.1",
"mongoose": "^5.8.4",
"nodemailer": "^6.4.2",
"pdfkit": "^0.11.0",
"qrcode": "^1.4.4"
},
"devDependencies": {
"morgan": "^1.9.1"
}
}
and the www/package.json is:
{
"name": "www",
"version": "0.1.6",
"private": true,
"engines": {
"node": "13.x"
},
"dependencies": {
"#material-ui/core": "^4.8.2",
"#material-ui/icons": "^4.5.1",
"bootstrap": "^4.4.1",
"formik": "^2.1.1",
"jspdf": "^1.5.3",
"qrcode": "^1.4.4",
"qrcode.react": "^1.0.0",
"react": "^16.11.0",
"react-bootstrap": "^1.0.0-beta.14",
"react-dom": "^16.11.0",
"react-router": "^5.1.2",
"react-router-dom": "^5.1.2",
"react-scripts": "3.3.0",
"react-stripe-elements": "^6.0.1",
"yup": "^0.28.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
And at the end, the content of server/server.js is:
const express = require('express');
const app = express();
const path = require('path');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
require('dotenv').config()
const agencyRoutes = require('./api/routes/agency');
const companyRoutes = require('./api/routes/company');
const userRoutes = require('./api/routes/user');
const qrcodeRoutes = require('./api/routes/qrcode');
const vehicleRoutes = require('./api/routes/vehicle');
const writerRoutes = require('./api/routes/writer');
const port = process.env.PORT || 8080;
mongoose.connect(String(process.env.DB_CONNECT), {
useCreateIndex: true,
useNewUrlParser: true,
useUnifiedTopology: true
}, () => console.log('Connect to the database'));
mongoose.Promise = global.Promise;
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use( (req, res, next) => {
res.header('Access-Control-Allow-Origin', 'https://constafast.cf');
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept, Authorization'
);
res.header('Connection', 'Keep-Alive');
if ( req.method === 'OPTIONS' ) {
res.header('Access-Control-Allow-Methods', 'PUT, POST, PATCH, DELETE, GET');
return res.status(200).json({});
}
next();
});
app.use(express.static(path.resolve(__dirname, '../www', 'build')));
app.use('/api/agency', agencyRoutes);
app.use('/api/company', companyRoutes);
app.use('/api/user', userRoutes);
app.use('/api/qrcode', qrcodeRoutes);
app.use('/api/vehicle', vehicleRoutes);
app.use('/api/writer', writerRoutes);
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, '../www', 'build', 'index.html'));
});
app.use( (req, res, next) => {
const error = new Error('Not found');
error.status = 404;
next(error);
});
app.use( (error, req, res, next) => {
res.status(error.status || 500);
res.json({
error: {
message: error.message
}
});
});
app.listen(port, () => console.log(`Server up and running on port ${port}`));
module.exports = app;
I see no way of specifying the location of the package.json and server.js files, neither in the app.yaml reference, nor in the gcloud app deploy reference, so I'd guess it has to be located side-by-side with the app.yaml file (as seen in the sample app).
The error you see could very well be caused by the deployment command not finding the mentioned files where it expects them.
In other words you'd have to move/copy the app.yaml file in the server directory. It might be possible to symlink the file to avoid actual code duplication if you want to also deploy from another directory (it works for the standard environment, but I'm not certain the same is true for the flexible one).
Side note: I don't think your static handlers (which I suspect could also be the reason for which you seek such app structure) will be working - there's no mention of such capability in the app.yaml reference or in the Serving Static Files section. Maybe you accidentally looked at the standard environment docs? (check How to tell if a Google App Engine documentation page applies to the 1st/2nd generation standard or the flexible environment) If you drop the handlers there's very little left in the app.yaml file - a rather low re-use value for the effort to do so (if even possible). I'd just keep things simple and stick to the recommended way.