I am trying to deploy my React app onto Heroku however I'm running into some graphql errors. When I manually deploy the app, the server and client both start up successfully however upon performing any actions that require a database fetch, I get a failed to fetch error and a "Failed to load resource: net::ERR_CONNECTION_REFUSED" error. I think this is because the server is in the correct location (IP-wise) but this app was created to run locally so the client is expected to be on the localhost network, not the heroku url it has now. I have changed the ENV variables various different times to see what combination of addresses would work for the server and client however nothing changed. I will post my server side code and ENV variables below:
const { ApolloServer } = require('apollo-server-express');
const cors = require('cors');
const express = require('express');
const mongoose = require('mongoose');
const resolvers = require('./resolvers/root-resolver');
const { typeDefs } = require('./typedefs/root-def');
const serverOptions = require('./server-config');
require('dotenv').config();
const { MONGO_URI, BACKEND_PORT, CLIENT_LOCAL_ORIGIN, SERVER_LOCAL_DOMAIN } = process.env;
// create express server handling our middleware
const app = express();
// since we presume cors is enabled, this next step is not optional, so cors
// is enable here instead of in options
app.use(cors({ origin: CLIENT_LOCAL_ORIGIN, credentials: true }));
const corsPolicy = async(req, res, next) => {
/*
TODO for 316 students: res.set(), Access-Control-Allow-Origin and Access-Control-Allow-Credentials headers,
have them set these, inspect error messages, understand why they're needed
*/
res.set("Access-Control-Allow-Origin", req.headers.origin.toString());
res.set("Access-Control-Allow-Credentials", true);
next();
}
app.options('*', cors());
app.use(corsPolicy);
// middleware application is configured to happen in server-config.js
serverOptions(app);
const server = new ApolloServer({
typeDefs: typeDefs,
resolvers: resolvers,
context: ({req, res}) => ({ req, res })
});
// since the express server has cors configured, cors on the apollo server
// can be false; passing the same options as defined on the express instance
// works as well
server.applyMiddleware({ app , cors: false});
mongoose.connect(MONGO_URI, {useNewUrlParser: true , useUnifiedTopology: true})
.then(() => {
app.listen({ port: BACKEND_PORT }, CLIENT_LOCAL_ORIGIN, () => {
console.log(`Server ready at ${SERVER_LOCAL_DOMAIN}:${BACKEND_PORT}`);
})
})
.catch(error => {
console.log(error)
});
[ENV Variables][1]
[1]: https://i.stack.imgur.com/5nqmp.png
Related
I'm trying to use socket io to send and receive data in realtime, but when I run server and open the client page which connects using socket.io-client, I'm getting an error
I installed cors and used it like I've done multiple times before and I tried setting the headers of my response to Allow access from different origin but nothing worked.
this is the error I'm getting:
Access to XMLHttpRequest at 'http://localhost:5000/socket.io/?EIO=4&transport=polling&t=ONQYon3' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
this is my server side code
require("dotenv").config();
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const cors = require("cors");
const { Server } = require("socket.io");
const app = express();
const server = require("http").Server(app);
const io = new Server(server);
app.use(bodyParser.json());
app.use(
cors({
origin: "*",
})
);
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
});
io.on("connection", (socket) => {
console.log("a user connected");
});
const port = process.env.PORT || 5000;
const url = process.env.MONGO_URI;
const start = async () => {
try {
await connectDB(url);
server.listen(port, (req, res) => {
console.log(`Server is listening on port ${port}`);
});
} catch (error) {
console.log(error);
}
};
start();
and all I'm doing on the frontend is using socket.io-client library to connect to the server in a react application like this.
import io from "socket.io-client";
const socket = io("http://localhost:5000");
any help is appreciated
You need to pass cors options to the io Server constructor itself.
E.g. instead of
const io = new Server(server);
you need
const io = new Server(server, {
cors: {
origin: '*',
}
});
I was able to solve the problem. it was because the client and server were running on different ports and even with cors defined socket.io needs its own cors setting in it in order to work, I changed it to this and it worked.
const io = require("socket.io")(5000, {
cors: {
origin: "*",
},
});
I am carrying out a project in MERN Stack and when making the request to the Api it returns a 404 error.
I do not know what it can be since the server works correctly, the strange thing is that sometimes when lifting it if it works without touching anything but other times it does not and I do not know how to solve it.
Another curious fact is that when raising the servers of other projects that were working correctly, I get the same error.
Error on Google Chrome DevTools:
image of error in Google Chrome
Server:
const express = require('express')
const cors = require('cors')
const mongoose = require('mongoose')
require('dotenv').config()
const app = express()
const port = process.env.PORT || 5000
app.use(cors())
app.use(express.json())
mongoose
.connect('mongodb://127.0.0.1:27017/justwatch',{useNewUrlParser:true})
.catch(e=>console.log('Connection error:',e.message))
const connection = mongoose.connection
connection.once('open',()=>{
console.log('MongoDB MOVIES database connection successfully');
})
const movieRouter = require('./routes/movie')
const seriesRouter = require('./routes/serie')
app.use('/movies',movieRouter)
app.use('/series',seriesRouter)
app.listen(port,()=>{console.log(`Server is running on port: ${port}`)})
Router:
const router = require('express').Router()
let Movie = require('../models/movie.model')
router.route('/movies').get((req,res)=>{
let limite = parseInt(req.params.number)
Movie.find().limit(12)
.then(movies=>res.json(movies))
.catch(err=>res.status(400).json('Error: '+err))
})
router.route('/').get((req,res)=>{
Movie.find().limit(12)
.then(movies=>res.json(movies))
.catch(err=>res.status(400).json('Error: '+err))
})
module.exports = router
React requests:
const getMovies = async() => {
await axios.get('localhost:5000/movies/')
.then(res=>{ console.log(res.data); setMovies(res.data) })
.catch(err=>console.log(err)) console.log(movies) }
I am trying to make Postman work with React JS using express. I am following a Mern Stack Development tutorial in free code camp. I have Cors extension enabled in my browsers, both in Chrome and in Edge. I keep getting this message in localhost:5000 "Cannot get /" and get this message {"msg":"This is CORS-enabled for an allowed domain."} in localhost:5000/users/add. My code looks something like this:
This is my server.js
const express = require('express');
const cors = require('cors');
const mongoose = require('mongoose');
require('dotenv').config();
const app = express();
const port = process.env.PORT || 5000;
app.use(cors());
app.use(express.json());
const uri = process.env.ATLAS_URI;
mongoose.connect(uri,{useNewUrlParser: true, useCreateIndex:true, useUnifiedTopology:true});
const connection= mongoose.connection;
connection.once('open', () =>{
console.log("Mongodb database connection established successfully");
})
const exercisesRouter= require('./routes/exercises');
const usersRouter= require('./routes/users');
var allowlist = ['http://localhost:5000']
var corsOptionsDelegate = function (req, callback) {
var corsOptions;
if (allowlist.indexOf(req.header('Origin')) !== -1) {
corsOptions = { origin: true } // reflect (enable) the requested origin in the CORS response
} else {
corsOptions = { origin: false } // disable CORS for this request
}
callback(null, corsOptions) // callback expects two parameters: error and options
}
app.use('./exercises',exercisesRouter);
app.use('./users', usersRouter);
app.get('/users/add', cors(corsOptionsDelegate), function (req, res, next) {
res.json({msg: 'This is CORS-enabled for an allowed domain.'})
})
app.listen(port, ()=>{
console.log(`Server is running on port: ${port}`);
});
app.listen(80, function () {
console.log('CORS-enabled web server listening on port 80')
})
cords don’t have anything to do with this
Can you tell me where is yow route for “/“ something like this
app.get(“/“, (req,res)=>{
…..
});
Yes exactly. You don’t have it. If the route/endPoint is not declared how do use expect them browsers to show you some else
When browssers open yow link at localhost:5000
They make a get request to “/“. So express just tell’em
Can not get “/“
I do not
I have this GET request that fetches data from a third party api. I want to check if there is new data every 5-10 minutes or so. Right now i have this setup on my backend.
exports.get_alerts = async (req, res) => {
const alertsUrl = `https://www.g2smart.com/g2smart/api/alert?cpo=${req.params.cpo}&status=Opened&limit=10&page=1`;
const axios = require("axios");
const auth = await refreshToken;
const currTime = moment().subtract(1, "days").format("X");
const newAlertsData = [];
const availableUsers = await axios.get(
"http://localhost:5000/api/schedule/available"
) ....
and on the front end i have this code to send a get request to my alerts api endpoint.
getAlerts = async () => {
axios
.get("/api/alerts/total_fr_hpc")
.then((response) => console.log(response.data))
.catch((err) => console.log(err));
};
timer = (time) => {
const date = new Date(time);
return `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;
};
componentDidMount() {
this.alertsInterval = setInterval(this.getAlerts, 900000);
}
componentWillUnmount() {
clearInterval(this.alertsInterval);
My question is can i have all this done on the backend only? I read a bit about websockets but that seems to be only for a continuous 2way connection between the backend and frontend.
I'd like to have something like that towards my third party apis on the node/express server, either fetching data at a set interval or a continuous connection checking for new data without having to make GET requests from my frontend. I want to be able to get new Data and store it into MongoDB even when there is nobody logged in to the client side.
I want that the data the users get is always up to date without having at least one person logged in to trigger the GET requests.
This is how my node/express server is currently setup
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const passport = require("passport");
const cors = require("cors");
const path = require("path");
const indexRouter = require("./routes/index");
const apiRouter = require("./routes/api"); //Import routes for "api" area of site
const app = express();
// CORS Middleware
app.use(cors());
app.options("*", cors());
// Bodyparser middleware
app.use(
bodyParser.urlencoded({
extended: false,
})
);
app.use(bodyParser.json());
// DB Config
const db = require("./config/keys").mongoURI;
// Connect to MongoDB
mongoose
.connect(db, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
})
.then(() => console.log("MongoDB successfully connected"))
.catch((err) => console.log(err));
// Passport middleware
app.use(passport.initialize());
// Passport config
require("./config/passport")(passport);
// Routes
// Add api routes to middleware chain.
app.use("/", indexRouter);
app.use("/api", apiRouter);
// Serve static assets (build folder) 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, "0.0.0.0", () =>
console.log(`Server up and running on port ${port} !`)
);
I am not familiar with the axios as I always use the native fetch API. Maybe the isomorphic fetch can help.
I am using Firebase Functions as the host for my MERN web app backend.
When I connect to MongoDB locally, it works and can run operations with the database. However, when I deployed to firebase functions, it failed to even connect to the database.
Code:
index.js
const functions = require('firebase-functions');
const server = require('./server.js');
exports.api = functions.runWith({ memory: "2GB", timeoutSeconds: 120 }).https.onRequest(server);
Part of server.js
const express = require("express");
const dotenv = require("dotenv");
const colors = require("colors");
const morgan = require("morgan");
const path = require("path");
const cors = require("cors");
const bodyParser = require("body-parser");
const routes = require("./routes/routes.js");
const mongooseMethods = require("./database.js");
dotenv.config({ path: "./config/config.env" });
mongooseMethods.connectDB(process.env.MONGO_URL);
const PORT = process.env.PORT || 8080;
// set up app
const app = express();
app.listen(PORT, console.log(`Server running in ${process.env.NODE_ENV} mode on port ${PORT}`.yellow.bold));
app.use(cors({ origin: true }));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(morgan("dev"));
app.use("/api", routes); // /api routes
module.exports = app;
routes.js
const express = require("express");
const app = express.Router();
const testingApi = require('../controller/testing.js');
const authApi = require('../controller/auth.js');
// testing
app.get('/testing', testingApi.testing);
// user authentication
app.post('/user/register', authApi.createUser);
module.exports = app;
api/testing/ also works
database.js
const mongoose = require("mongoose");
const mongooseMethods = {
connectDB: async (url) => {
try {
console.log("Connecting to MongoDB")
const connection = await mongoose.connect(url, { useNewUrlParser: true, useUnifiedTopology: true });
console.log(`MongoDB Connected: ${connection.connection.host}`.cyan.bold);
return connection;
} catch (error) {
console.log(`Error: ${error.message}, Exiting`.red.bold);
process.exit(1);
}
}
}
module.exports = mongooseMethods;
auth.js
const User = require('../model/user.model.js');
const bcrypt = require("bcryptjs");
let authenticationApi = {
createUser: async (req, res) => {
try {
console.log("Creating");
let newUser = new User({
...req.body
})
let result = await newUser.save();
return res.status(200).json({ result: result });
} catch (error) {
return res.status(400);
}
}
}
module.exports = authenticationApi;
The error I received when sending request to firebase is
2020-02-27T02:34:46.334044912Z D api: Function execution took 30970 ms, finished with status: 'connection error'
Yet it runs perfectly fine in local. I also don't see the console log "connected to MongoDB". I'm guessing that the problem occurs in database.js that it failed to connect to mongo at the first place yet I don't know how to solve.
I am using the paid plan in Firebase and the outbound networking should be fine.
p.s. this is my first time posting here. thanks for your time and I apologize in advance if i'm breaking any rules.
Listening on a port is not a valid operation in cloud functions:
app.listen(PORT, console.log(`Server running in ${process.env.NODE_ENV} mode on port ${PORT}`.yellow.bold));
Cloud Functions listens for you, using the URL that it was assigned, then delivers the request to your code. When you pass your express app to onRequest(), that's all wired up for you.
I suggest starting with a stripped down, simplified version of an app just to gain experience about how things work, then add in more as you get comfortable.
The reason for this to happen is that the architecture of Firebase Functions is not an actual server, but a serverless lambda-like endpoint. Since it cannot establish a lasting connection to the database, that it has to make a connection every time it received a request, the database sees this as spam and shut down further connection request from Firebase.
Therefore, you simply cannot host a complete express app with intended lasting connection in Firebase Functions.
More on that in this article