I am working on an app with a React front-end and an Express API which are hosted on the same server.
It works fine in local but as soon as I deploy it to Heroku, each request from the front-end to the back-end returns 405: Method Not Allowed
. I have been looking for answers but most point to using CORS and I already do. I thus do not know if my problem comes from the build, from a misuse of axios or from a faulty express.js config.
I have also tried adding a react proxy URL but it does not solve the problem.
Directory stucture is as follows:
├── Express
| └── server.js
├── React
| └── App.js
├── buildScript.js
└── package.json
Here is my server.js file:
const express = require('express')
const bodyParser = require('body-parser')
const compression = require('compression')
const cors = require('cors')
const helmet = require('helmet')
const path = require('path');
// Import routes
const poisRouter = require('./routes/pois-route')
const autocompleteRouter = require('./routes/autocomplete-route')
// Set default port for express app
const PORT = process.env.PORT || 4001
const app = express()
app.use(cors())
app.use(helmet())
app.use(compression())
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
// Serve static files from the React App
app.use(express.static(path.join(__dirname, 'build')));
// Implement Poi & Autocomplete routes
app.use('/pois', poisRouter)
app.use('/autocomplete', autocompleteRouter)
// Wildcard to send back to React
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'build', 'index.html'));
});
// Start express app
app.listen(PORT, function() {
console.log(`Server is running on: ${PORT}`)
})
Example request from the React front-end, which gives me a 405 error:
const fetchPoisFromAutocomplete = async () => {
// Send GET request to 'autocomplete/fetch' endpoint
axios
.get('/autocomplete/fetch', {
latitude: latitude,
longitude: longitude
})
.then(response => {
// Update the pois state
console.dir(response.data)
})
.catch(error => console.error(`There was an error retrieving the poi list: ${error}`))
}
fetchPoisFromAutocomplete();
Package.json scripts:
"scripts": {
"build": "node ./buildScript",
"build-front": "react-scripts build",
"start": "node app/server.js",
"start-server": "nodemon app/server.js",
"start-front": "react-scripts start",
"dev": "concurrently \"npm run start-server\" \"npm run start-front\" --kill-others --kill-others-on-fail",
"test": "react-scripts test",
"eject": "react-scripts eject",
"heroku-postbuild": "react-scripts build"
},
Build Script:
const fs = require('fs')
const fse = require('fs-extra')
const childProcess = require('child_process')
if (fs.existsSync('./build')) {
fse.removeSync('./build')
}
childProcess.execSync('react-scripts build', { stdio: 'inherit' })
fse.moveSync('./build', './server/build', { overwrite: true })