问题
I have a React todo app I built using create-react-app and I built a simple express server to query mongoDB to get all the appointment objects. It works just as expected when I am running it on my machine. The front end spins up on localhost:3000
and the server on localhost:3001
. I use axios to make a get request to localhost:3000/api/appointments
to load all the appointments into the App.js state. I uploaded it to Heroku and I got a CORS error on the request. After that, I tried to just use the route 'api/appointments' in the request and every permutation of that I can come up with which all respond with 404 errors.
Where does the node.env variable spin up the server on Heroku? And how do I call it fromm a React app with axios?
Same question in a different context if it helps:
When I run the app on my machine and access it with Postman, I can GET localhost:3001/api/appointments
and it returns an array of JSON objects from the database just as I would expect. When I deploy to Heroku GET https://appointment-ledger-map.herokuapp.com/api/appointments
returns all the markup for index.html. I assume this means that the api server is up and running because it responds but why is it not responding with the array of JSON objects as expected?
// server.js
var express = require('express');
var mongoose = require('mongoose');
var bodyParser = require('body-parser');
var Appointment = require('./model/appointments');
//and create our instances
var app = express();
var router = express.Router();
//set our port to either a predetermined port number if you have set
//it up, or 3001
var nodeEnv = process.env.NODE_ENV || 'development';
var port = process.env.PORT || 3001;
var host = process.env.HOST || '0.0.0.0';
//db config
mongoose.connect('mongodb://josh11:josh11@ds133162.mlab.com:33162/heroku_tl016m5d');
//now we should configure the API to use bodyParser and look for
//JSON data in the request body
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
//To prevent errors from Cross Origin Resource Sharing, we will set
//our headers to allow CORS with middleware like so:
app.use(function(req, res, next) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Credentials', 'true');
res.setHeader('Access-Control-Allow-Methods', 'GET,HEAD,OPTIONS,POST,PUT,DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers');
//and remove cacheing so we get the most recent appointments
res.setHeader('Cache-Control', 'no-cache');
next();
});
//now we can set the route path & initialize the API
router.get('/', function(req, res) {
res.send({ message: 'API Initialized!'});
console.log('Api initialized');
});
//Use our router configuration when we call /api
app.use('/api', router);
//starts the server and listens for requests
app.listen(port, host, function() {
console.log(`api running on port ${port}`);
});
//adding the /appointments route to our /api router
router.route('/api/appointments')
//retrieve all appointments from the database
.get(function(req, res) {
//looks at our Appointment Schema
Appointment.find(function(err, appointments) {
if (err)
res.send(err);
//responds with a json object of our database appointments.
res.send(appointments)
});
console.log(appointments);
})
//post new appointment to the database
.post(function(req, res) {
var appointment = new Appointment();
//body parser lets us use the req.body
appointment.appointmentTitle = req.body.appointmentTitle;
appointment.appointmentDate = req.body.appointmentDate;
appointment.appointmentTime = req.body.appointmentTime;
appointment.appointmentDescription = req.body.appointmentDescription;
appointment.appointmentDestination = req.body.appointmentDestination;
appointment.appointmentOrigin = req.body.appointmentOrigin;
appointment.travelMode = req.body.travelMode;
appointment.save(function(err) {
if (err)
res.send(err);
res.send({ message: 'Appointment successfully added!' });
});
});
// App.js
loadAppointments() {
axios.get('/api/appointments')
.then(res => {
this.setState({
appointments: res.data,
filteredAppointments: res.data
});
})
}
回答1:
npm install cors --save
then
var cors = require('cors');
finally
mongoose.connect('mongodb://josh11:josh11@ds133162.mlab.com:33162/heroku_tl016m5d');
//now we should configure the API to use bodyParser and look for
//JSON data in the request body
app.use(cors()); **//Must be before BodyParser**
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
//To prevent errors from Cross Origin Resource Sharing, we will set
//our headers to allow CORS with middleware like so:
Re-deploy it and voila :)
Hope it helped you
来源:https://stackoverflow.com/questions/44749205/react-axios-calls-to-express-api-in-heroku-deployment