'Why is my Axios POST Request Returning a 405 Error in Production?
I have a React website with a simple contact (which you can find here) form that's powered by Nodemailer and an Express backend. The form sends an email as expected when testing locally. But after deploying to Heroku I'm getting a 405 error in Production whenever I submit the form.
Here are the relevant parts of my initial configuration:
server/index.js:
const express = require('express');
const path = require('path');
const cors = require('cors');
const nodemailer = require('nodemailer');
const dotenv = require('dotenv');
let app = express();
dotenv.config();
app.use(express.json());
app.options('*', cors());
app.get('/api', (req, res) => {
res.send('Welcome to the backend!')
});
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, '../client/build', 'index.html'));
});
// have Node serve the files for our built React app
app.use(express.static(path.resolve(__dirname, '../client/build')));
app.use('/public', express.static(path.join(__dirname, 'public')));
let transporter = nodemailer.createTransport({
host: process.env.MAIL_HOST,
name: process.env.MAIL_HOST,
port: 465,
secure: true,
auth: {
user: process.env.MAIL_USER,
pass: process.env.MAIL_PASS
},
tls: { rejectUnauthorized: false },
logger: true
});
transporter.verify((error, success) => {
console.log(error ? error : 'Server is ready to take our messages');
});
app.post('/api', cors(), (req, res) => {
const name = req.body.data.name,
email = req.body.data.email,
message = req.body.data.message,
mail = {
from: name + ' <' + email + '>',
to: process.env.MAIL_TO,
subject: 'Contact Form Submission',
text: message
};
transporter.sendMail(mail, (err, data) => {
res.json({ status: err ? 'fail' : 'success' });
});
});
const PORT = process.env.PORT || 3001
app.listen(PORT, () => console.info(`server has started on ${PORT}`))
Submit Handler in my Contact Form Component:
const submitRequest = async (e) => {
e.preventDefault();
const data = { name, email, message };
axios.post('/api', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
data
})
.then(response => {
if (response.data.status === 'success') {
setName('');
setEmail('');
setMessage('');
setSubmitted(true);
} else if (response.data.status === 'fail') {
// do something
}
return response;
});
};
.htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule . /index.html [L]
</IfModule>
static.json
{
"root": "client/build/",
"clean_urls": false,
"routes": {
"/**": "index.html"
}
}
Operating under the assumption that this is a CORS issue, here's what I've tried:
- Adding
app.use(cors())to Express backend inserver/index.js- I wasn't sure this was necessary given that I'm already passing incors()when defining my/apiroute, but I nonetheless tried it - Adding Additional request headers
Access-Control-Allow-MethodsandAccess-Control-Allow-Originto my axios POST request -- ie:
axios.post('/api', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Access-Control-Allow-Methods': 'POST',
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json'
},
data
})
But neither of these changes fixed the problem. Is there something else I should be adding to the request header of my axios POST request and/or to my server/index.js file? Could my .htaccess file be the culprit? Or is it something else entirely? Any guidance would be greatly appreciated!
Solution 1:[1]
The create-react-app buildpack uses the heroku/static buildpack which in turn uses a nginx web server. Unfortunately nginx does not allow POST calls from static pages.
Try using a GET request instead.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Damian Busz |

