Network Error in react after deploy on heroku - node.js

I deployed my MERN project on heroku app but when I tried to submit my form it send me this error in console:
Access to XMLHttpRequest at 'localhost:8000/api/products' from origin
'https://thebeuter.herokuapp.com' has been blocked by CORS policy:
Cross origin requests are only supported for protocol schemes: http,
data, chrome, chrome-extension, https. Form.jsx:69 Error: Network
Error
at e.exports (createError.js:16)
at XMLHttpRequest.d.onerror (xhr.js:83)
Here is my server.js:
const express = require("express"),
app = express(),
cors = require("cors"),
port = process.env.PORT || 8000,
db = "beuter",
path = require("path"),
server = app.listen(port, () => console.log(`Listening to on port ${port}`));
app.use(cors());
app.use(express.json());
if (process.env.NODE_ENV === "production") {
app.use(express.static('beuter/build'))
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'beuter', 'build', 'index.html'));
})
}
console.log(port)
require("./server/config/database.config")(db);
require("./server/routes/product.route")(app);
and here is my Form.jsx:
const addProduct = (e) => {
e.preventDefault();
const product = {
title,
title_url,
price,
description1,
description2,
description3,
description4,
description5,
img_url1,
img_url2,
img_url3,
img_url4,
size,
size2,
fit,
fit2,
category,
};
axios
.post("localhost:8000/api/products", product)
.then((res) => {
if (res.data.errors) {
setErrors(res.data.errors);
} else {
navigate("/");
}
})
.catch((err) => console.log(err));
};
return (
...
...
...
)
How can I fix this?
Here is my project github:
https://github.com/nathannewyen/the-beuter
Thank you!
Updated:
ShopAllProducts.jsx:
useEffect(() => {
const fetchItems = async () => {
setLoading(true);
const res = await axios.get("http://localhost:8000/api/products");
setProducts(res.data);
setLoading(false);
};
document.title = `Shop - The Beuter`;
fetchItems();
}, [props]);

the answer for this question is to have env files for development and production
for development
create the file called .env.development in the root folder of your frontend app
in .env.development add this line
REACT_APP_BASE_URL="http:localhost:5000"
and in .env.production add another line as
REACT_APP_BASE_URL="https://algorithammer.herokuapp.com"
or your website (here i am showing the sample)
now make sure that you have a variable called baseURL as global variable
example:
authAPI.js (example)
exports.baseURL = process.env.REACT_APP_BASE_URL;
in Login.js (example)
import {baseURL} from "./authAPI.js"
axios
.post(`${baseURL}/login`, {
data: "sample data"
})
.then((res) => console.log(res))
.catch((err) => console.log(err));
dont forget to push the changes and deploy the heroku app again

Related

Error: Access to XMLHttpRequest has been blocked by CORS policy Flask API + NodeJs

I have a problem between frontend backend and Flask API.
To execute my project I do `npm start. This will run the ReactJs frontend dev server on port 3000.
In package.json
I added the following "proxy": "http://localhost:5000",
Next, I do
cd backend && python server.py after activating my venv
This will run the Flask API on port 5000
The Flask API has this route
from flask_cors import cross_origin
# File download Link
#app.route('/filePath', methods=['POST'])
#cross_origin()
def get_path():
data = request.get_json()["path"]
storage.child(f"files/{data}").download(f"files/Resume.pdf")
return "Success.."
Finally, in another shell I do
cd backend && node server.js running on port 8080
Which has the following post
app.post('/insert', async (req, response) => {
const mobile_number = req.body.college_name
const name = req.body.college_name
axios.get('http://localhost:3000/details').then(async (res) => {
const recruit = new RecruitModel({
mobile_number:res.data.mobile_number, name:res.data.name,
});
await recruit.save()
response.send("inserted data")
});
});
Here is where the error happens in the frontend.
const uploadFiles = (file) => {
//
if (!file) return;
if (!initialData) return null;
const storageRef = ref(storage, `files/${file.name}`);
const uploadTask = uploadBytesResumable(storageRef, file);
uploadTask.on(
"state_changed",
(snapshot) => {
const prog = Math.round(
(snapshot.bytesTransferred / snapshot.totalBytes) * 100
);
setProgress(prog);
},
(error) => console.log(error),
() => {
getDownloadURL(uploadTask.snapshot.ref).then(async () => {
console.log(file.name);
await axios.post('http://localhost:5000/filePath', {
'path': file.name
}).then(() => console.log(file.name));
update();
});
}
);
};
In await axios.post('http://localhost:5000/filePath' I'm assuming.
I get the following error:
Access to XMLHttpRequest at 'http://localhost:8080/insert' from origin
'http://localhost:3000' has been blocked by CORS policy: Response to
preflight request doesn't pass access control check: The
'Access-Control-Allow-Origin' header has a value
'http://localhost:5000' that is not equal to the supplied origin
I thought using flask-cors would fix this so I'm not sure why I'm getting this error.
I'm really struggling on this error, Any suggestions please?
EDIT
const addRecruit = () => {
axios.post("http://localhost:8080/insert", {
college_name:initialData.college_name,
email:initialData.email,
mobile_number:initialData.mobile_number, name:initialData.name
});
}
This is where the issue is happening. Because the data is being fetched between Flask and ReactJs but this /insert is in server.js
The EDIT made things clear, the issue isn't to do with your Flask api. You need to enable cors in server.js
I'm assuming you had this setup before,
const cors = require('cors');
app.use(cors());
Do this instead
const corsOptions ={
origin:'http://localhost:3000',
credentials:true, //access-control-allow-credentials:true
optionSuccessStatus:200
}
app.use(cors(corsOptions));
Don't forget to npm i cors

ERR_CONNECTION_REFUSED for React and axios

I'm trying to build a instagram scraper with puppeteer and react that works with putting the username on an input and then I want to show the scraped data on the console, I already built the puppeteer script and It works, it returns the data correctly, But I have some issues trying to get the data from a post with axios, I'm using node js and express for my server, when I try to do the post with axios I keep getting an error.
I want to write the username on the input, then I want the puppeteer script to run, and then I want to console log the data that the puppeteer script returns
Error on console
POST http://localhost:4000/api/getData/username_im_scraping net::ERR_CONNECTION_REFUSED
This is my code
Server > index.js
const path = require("path");
const express = require("express");
const webpack = require("webpack");
const cors= require('cors');
const webpackDevMiddleware = require("webpack-dev-middleware");
const webpackHotMiddleware = require("webpack-hot-middleware");
const config = require(path.join(__dirname, "../webpack.config.js"));
const compiler = webpack(config);
const app = express();
const { script } = require("./script");
app.use(webpackDevMiddleware(compiler, config.devServer));
app.use(webpackHotMiddleware(compiler));
app.use(express.static(path.join(__dirname, '../build')));
app.use(cors());
app.get("/api/getData/:username", async (req, res) => {
console.log(`starting script for user ${req.params.username}`);
const data = await script(req.params.username);
console.log(`stopping script for user ${req.params.username}`);
res.send(data);
});
app.get('/*', (req, res) => {
res.sendFile(path.join(__dirname, '../build', 'index.html'));
});
app.listen(process.env.PORT || 4000, () => {
console.log('Server is listening on port 4000');
});
Homepage.js
import React, { useState } from "react";
import axios from "axios";
const Homepage = props => {
const [username, setUsername] = useState("");
const onChange = ({ target: { value } }) => setUsername(value);
const onClick = () => {
axios.post('http://localhost:4000/api/getData/' + username, {
header: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8;application/json' },
mode: "cors"
})
.then((response) => {
console.log(response);
})
.catch((error) => {
if (error.response) {
console.log(error.response.data);
console.log(error.response.status);
console.log(error.response.headers);
} else if (error.request) {
console.log(error.request);
} else {
console.log('Error', error.message);
}
})
};
return (
<div>
Time to start coding!
<input value={username} onChange={onChange} />
<button onClick={onClick}>Get instagram followers!</button>
</div>
);
};
export default Homepage;
The problem here is you defined your route with get like app.get("/api/getData/:username") but you are sending a post request. Either change the router to app.post or your axios method to axios.get.
UPDATE
Besides the changes above, after you shared the repository with me i checked and saw you have another problem, which was that you were not running your server so the ERR_CONNECTION_REFUSED message shown.
I forked your repository and made the following changes and created a PR for it. Please take a look at it, and if you want just merge it to your master branch.
P.S please for the next time create a .gitignore file and add node_modules to there so you don't push and pull your node_modules which takes some more amount of time.

NextJS does not recognize dynamically added static assets in production

I'm running a two container docker setup; NextJS for the public facing web, and Django backend for admins to add content. The routes are nicely working with getInitialProps which fetches the added content. As the content references static images, they are connected via docker volumes (./static/media on django container and ./public/media on nextjs container).
However when a new image appears in ./public/media, the started NextJs server returns a 404 response for those images.
// EDITED SOLUTION: As suggested by #Pierfrancesco
The workaround solution is to create a custom server which dynamically serves those files
// server.js
const express = require('express')
const next = require('next')
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare().then(() => {
const server = express()
server.get('/media/images/*', (req, res) => {
// Disallow travelling up in the file tree
let target = req.originalUrl.replace("..", "")
return res.sendFile(__dirname + '/public' + target);
})
server.all('*', (req, res) => {
return handle(req, res)
})
server.listen(port, err => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
Could this be a feature request or is this a bug in NextJS?

Getting 404 (Not Found) on axios.delete()

I'm trying to implement the delete functionality for my survey creation app.
I'm using MongoDB with mongoose for the database, node.js/Express for the backend server and React/Redux for the frontend side.
Although I think I set routing correctly, I get 404 (Not Found) on axios.delete().
The error says that http://localhost:3000/api/surveys/delete/{the-survey-id-here} is not found.
I have been reading the documentation of axios, Express, mongoose and other websites, however, nothing worked for me.
I tried the following things.
Use findByIdAndRemove() instead of deleteOne()
Pass surveyId in the action creator const response = await axios.delete("/api/surveys", data: { surveyId });
Use <a></a> instead of <button></button>
Here are my codes.
SurveyList.js (react component which has the delete button)
import { fetchSurveys, deleteSurvey } from '../../actions'
...
<div className="card-action">
<a className="red-text text-accent-1">Yes: {survey.yes}</a>
<a className="red-text text-accent-1">No: {survey.no}</a>
<button
className="btn-floating btn-small waves-effect waves-light red right"
onClick={() => this.props.deleteSurvey(survey._id)}
>
<i className="material-icons">delete_forever</i>
</button>
</div>
...
const mapStateToProps = ({ surveys }) => {
return { surveys }
}
export default connect(
mapStateToProps,
{ fetchSurveys, deleteSurvey }
)(SurveyList)
actions/index.js (action creator)
export const deleteSurvey = (surveyId) => async dispatch => {
const response = await axios.delete(`/api/surveys/delete/${surveyId}`)
dispatch({ type: FETCH_SURVEYS, payload: response.data })
}
surveyRoute.js (routing handler)
app.delete('/api/surveys/delete/:surveyId', async (req, res) => {
await Survey.deleteOne({ _id: req.params.surveyId })
const surveys = await Survey.find({ _user: req.user.id }).select({
recipients: false
})
res.send(surveys)
})
server/index.js
const express = require('express')
const mongoose = require('mongoose')
const cookieSession = require('cookie-session')
const passport = require('passport')
const bodyParser = require('body-parser')
const keys = require('./config/keys')
require('./models/User')
require('./models/Survey')
require('./services/passport')
mongoose.connect(keys.mongoURI)
const app = express()
app.use(bodyParser.json())
app.use(
cookieSession({
maxAge: 30 * 24 * 60 * 60 * 1000, // milliseconds
keys: [keys.cookieKey]
})
)
app.use(passport.initialize())
app.use(passport.session())
require('./routes/authRoutes')(app)
require('./routes/billingRoutes')(app)
require('./routes/surveyRoutes')(app)
if(process.env.NODE_ENV === 'production'){
app.use(express.static('client/build'))
const path = require('path')
app.get('*',(req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
})
}
const PORT = process.env.PORT || 5000
app.listen(PORT)
In my case, leads/ is the end point. try your end point + survey id
With axios#^0.19.2
axios
.delete('/api/leads/' + id)
.then(res => {
dispatch({
type: DELETE_LEAD,
payload: id
});
So if I undestood correctly, you have a Expressjs App and a client app running on different ports, if so I think I found the issue
You are making ajax calls as if you had both frontend and backend running on the same server. Here are two possible solutions
Change the address of the Axios delete action to point to the right server if you are planning to run the backend and frontend on different servers
app.delete('http://localhost:5000/api/surveys/delete/:surveyId', async (req, res) => {
await Survey.deleteOne({ _id: req.params.surveyId })
const surveys = await Survey.find({ _user: req.user.id }).select({
recipients: false
})
res.send(surveys)
})
Off course you have to change the address once you deploy it to production and enable CORS
Build the client app for producion, this process will compile all css, js and html and save it to client/build folder as stated on line
res.sendFile(path.resolve(__dirname, 'client', 'build', 'index.html'));
This will cause the frontend and backend code to run on the same server
Thank you very much for all answers and comments. The problem was the proxy. I am using http-proxy-middleware to handle requests between different ports in the dev environment. All comments about ports made me realize that I need to check the 'setupProxy.js' file. I modified the code inside the file as below and that fixed the problem.
setupProxy.js
const proxy = require('http-proxy-middleware')
module.exports = function(app) {
app.use(proxy ('/auth/google', { target: 'http://localhost:5000' }))
app.use(proxy ('/api/**', { target: 'http://localhost:5000' }))
}
Thank you very much again for all the answers and comments.
CORS (Delete verb) must be enabled in your route middleware.
This thread may help you.

Node Fetch Request Fails on Server: Unable to Get Local Issuer Certificate

~ I'm using Node 10.9.0 and npm 6.2.0 ~
I have the following app running that allows me to make a request to the same site over http and over https.
var fetch = require('node-fetch')
const express = require('express')
const app = express()
//-- HTTP --
app.get('/test-no-ssl', function(req, res){
fetch('http://jsonplaceholder.typicode.com/users')
.then(res => res.json())
.then(users => {
res.send(users)
}).catch(function(error) {
res.send(error)
})
})
//-- HTTPS --
app.get('/test-ssl', function(req, res){
fetch('https://jsonplaceholder.typicode.com/users')
.then(res => res.json())
.then(users => {
res.send(users)
}).catch(function(error) {
res.send(error)
})
})
app.listen(3003, () =>
console.log('Listening on port 3003...')
)
Both of these work fine on my local machine and return the JSON response that Typicode provides. But when I deploy these as a Node app on my web host (FastComet), I get the following results:
HTTP /test-no-ssl - Returns the JSON as expected
HTTPS /test-ssl - Returns the following error:
{
"message" : "request to https://jsonplaceholder.typicode.com/users failed, reason: unable to get local issuer certificate",
"type" : "system",
"errno" : "UNABLE_TO_GET_ISSUER_CERT_LOCALLY",
"code" : "UNABLE_TO_GET_ISSUER_CERT_LOCALLY"
}
I searched for this error and tried a couple of the usual fixes, but nothing has helped.
These didn't work:
npm config set registry http://registry.npmjs.org/
npm set strict-ssl=false
Has anyone else run into this on a shared hosting provider (that supports Node) and has been able to get this to work? Perhaps even someone who uses FastComet? The support staff of the host doesn't seem to know what to do either, so I'm at a loss.
Try using the following:
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0
Hosting has probably some issue with list of certificate authorities... as a workaround you could try to ignore certificate validity.
const fetch = require('node-fetch')
const https = require('https')
const express = require('express')
const app = express()
const agent = new https.Agent({
rejectUnauthorized: false
})
//-- HTTP --
app.get('/test-no-ssl', function(req, res){
fetch('http://jsonplaceholder.typicode.com/users')
.then(res => res.json())
.then(users => {
res.send(users)
}).catch(function(error) {
res.send(error)
})
})
//-- HTTPS --
app.get('/test-ssl', function(req, res){
fetch('https://jsonplaceholder.typicode.com/users', { agent })
.then(res => res.json())
.then(users => {
res.send(users)
}).catch(function(error) {
res.send(error)
})
})
app.listen(3003, () =>
console.log('Listening on port 3003...')
)
Note: this has security implications, making https insecure the same way as http.

Resources