Accessing the internal API with React, Axios on Heroku

I am creating a complete React stack application that accesses its own API using Axios. In my local environment, it works as expected with a server responding with JSON data, which then displays correctly.

axios.get('/api/questions/categories')

      

I deployed to Heroku and the app starts fine and MongoDB is connected. Now, when the same GET request is made, it doesn't make it to the end. When I log the response from Axios to the console, it contains the actual HTML pages, not the expected JSON object.

To further clarify, if I manually type ' http: // localhost: 8080 / api / questions / categories ' in the address bar, the expected JSON data is displayed. If I do the same with an application in Heroku, I see that a "#" is appended to the URL and the page display does not change, no error messages. This leads me to think what the router is reacting to, but I haven't been able to figure out how / why.

My stack: Node, Express, Mongo, React

Don't use Redux

Using Axios to Call Your Own API

// Dependencies
var express = require('express');
var path = require('path');
var webpack = require('webpack');
var webpackMiddleware = require('webpack-dev-middleware');
var webpackHotMiddleware = require('webpack-hot-middleware');
var config = require('./webpack.config.js');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var morgan = require('morgan');

var inDev = process.env.NODE_ENV !== 'production';
var port = inDev ? 8080 : process.env.PORT;
var app = express();

// MIDDLEWARE

if (inDev){
  var compiler = webpack(config);
  var middleware = webpackMiddleware(compiler, {
    publicPath: config.output.publicPath,
    contentBase: 'app',
    stats: {
      colors: true,
      hash: false,
      timings: true,
      chunks: false,
      chunkModules: false,
      modules: false
    }
  });

  app.use(morgan('dev'));
  app.use(middleware);
  app.use(webpackHotMiddleware(compiler));
  app.get('/', function response(req, res) {
    res.write(middleware.fileSystem.readFileSync(path.join(__dirname,     'dist/index.html')));
    res.end();
  });
} else {
  app.use(express.static(__dirname + '/dist'));
  app.get('*', function response(req, res) {
    res.sendFile(path.join(__dirname, 'dist/index.html'));
  });
}

app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());

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 caching so we get the most recent comments
  res.setHeader('Cache-Control', 'no-cache');
  next();
});

// DATABASE

var dbPath = inDev ? 'mongodb://localhost/quizMe' :     'mongodb://heroku_pmjl5579:c28cf07fpf05uus13ipjeur5s7@ds143000.mlab.com:43000/heroku_pmjl5579';

mongoose.connect(dbPath);

// ROUTING / API

// var indexRoute = require('./routes/index');
var questionsRoute = require('./routes/api/questions');
// app.use('/', indexRoute);
app.use('/api/questions', questionsRoute);

app.listen(port, function(){
  console.log('Express server up on ' + port);
});

      

Thanks for any help!

+3


source to share


1 answer


Most single page applications route all requests to the root path and let the front end router take over. I suspect this is what is happening with your application.

Do you have any kind of request forwarding logic in your tailcode or any server config code?



What you can do is whitelist some paths that you don't need to bring to the front, like the ones that start with / api. It will be helpful to insert the server side config here.

In your server configuration, when it inDev

is false

, you have app.get('*', ...)

one that catches all requests and responds with a static single page application. Hence API requests will give the same response as well. You will need to rearrange your routes to match /api

before the template *

. Some examples can be found here

+2


source







All Articles