在 Heroku 部署中响应对 Express API 的 axios 调用

Posted

技术标签:

【中文标题】在 Heroku 部署中响应对 Express API 的 axios 调用【英文标题】:React axios calls to Express API in Heroku deployment 【发布时间】:2017-11-28 16:09:13 【问题描述】:

我有一个使用 create-react-app 构建的 React todo 应用程序,并构建了一个简单的快速服务器来查询 mongoDB 以获取所有约会对象。当我在我的机器上运行它时,它按预期工作。前端在localhost:3000 上启动,服务器在localhost:3001 上启动。我使用 axioslocalhost:3000/api/appointments 发出获取请求,以将所有约会加载到 App.js 状态。我将它上传到 Heroku,但请求时出现 CORS 错误。之后,我尝试在请求中只使用路由“api/appointments”,并且我能想到的每一个排列都以 404 错误响应。 node.env 变量在哪里启动 Heroku 上的服务器?以及如何从带有 axios 的 React 应用程序中调用它?

如果有帮助,请在不同的上下文中提出相同的问题: 当我在我的机器上运行该应用程序并使用 Postman 访问它时,我可以 GET localhost:3001/api/appointments 并且它会从数据库中返回一个 JSON 对象数组,正如我所期望的那样。当我部署到 Heroku 时,GET https://appointment-ledger-map.herokuapp.com/api/appointments 返回 index.html 的所有标记。我假设这意味着 api 服务器已启动并正在运行,因为它响应但为什么它没有按预期响应 JSON 对象数组?

// 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

然后

var cors = require('cors');

终于

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:

重新部署它,瞧 :)

希望对你有帮助

【讨论】:

以上是关于在 Heroku 部署中响应对 Express API 的 axios 调用的主要内容,如果未能解决你的问题,请参考以下文章

在heroku上部署Nodejs+Express+React+Webpack应用

使用 express 后端将 create-react-app 部署到 heroku 在浏览器中返回无效的主机标头

将 Node、Express 和 MongoDB 服务器部署到 heroku

如何将 Typescript、NodeJS 和 Express 应用程序部署到 Heroku

将 Apollo Express 服务器部署到 Heroku 时出现问题:“缺少 GET 查询。”

将React + NodeJS + Express + MySQL应用程序部署到Heroku仅部署服务器而不是React