I have a small backend with ExpressJS that sends an email, I have deployed this backend on a Heroku site, I have tried it with postman and everything is ok, it works, but when I want to use it from my gatsby site, it throws a problem with cors, the gatsby site is running on my localhost.
ExpressJS code:
import dotenv from 'dotenv';
import express from 'express';
import nodemailer from 'nodemailer';
import cors from 'cors';
if (process.env.NODE_ENV !== 'production') {
dotenv.config();
}
const app = express();
app.use(express.urlencoded({ extended: true }));
app.use(cors());
const contactAddress = process.env.CONTACT_ADDRESS || '';
const mailer = nodemailer.createTransport({
service: 'Gmail',
auth: {
user: process.env.GMAIL_ADDRESS,
pass: process.env.GMAIL_PASSWORD,
},
});
app.post('/contact', (req, res) => {
if (!req.body.from)
return res.status(400).json({ message: 'From is required' });
if (!req.body.message)
return res.status(400).json({ message: 'Message is required' });
mailer.sendMail(
{
from: req.body.from,
to: [contactAddress],
subject: 'Contact from API',
html: `<h3>${req.body.from}</h3><br>${req.body.message}`,
},
(err, info) => {
if (err) {
console.log(err);
return res.status(500).send(err);
}
res.status(200).json({ success: true });
}
);
});
app.listen(process.env.PORT || 8000);
console.log(`App running on port ${process.env.PORT || 8000}`);
Code on frontend that make the request:
const onSubmit = async (data: IFormInputs) => {
console.log(data);
const formData = new FormData();
Object.keys(data).forEach((el) => {
formData.append(el, data[el]);
});
try {
const res = await fetch(`${BACKEND_URL}contact`, {
method: 'POST',
body: formData,
});
console.log(res);
} catch (e) {
console.log(e);
}
}
I have also tried adding some configuration on the fetch, but it does not work anyways
const res = await fetch(`${BACKEND_URL}contact`, {
method: 'POST',
mode: 'cors',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json',
},
referrerPolicy: 'origin',
body: formData,
});
The error throws the following error:
{
status: 400,
statusText: "Bad Request",
type: "cors",
ok: false,
}
I have searched similar questions on StackOverflow, but any of the solutions have worked for me.
The answer on this post does not work for me, because I don't have the backend and the frontend on localhost, I am consuming the API from my Heroku site.
Thanks in advance!
You are listening on the port 8000. Are you sure it's correct? Let's try on posts 8080.
You can also set headers:
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", '*');
res.header("Access-Control-Allow-Credentials", true);
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header("Access-Control-Allow-Headers", 'Origin,X-Requested-With,Content-Type,Accept,content-type,application/json');
next();
});
Related
I have been dealing with this issue where I am attempting to make a get request to a third-party API using Axios in my Node.js server. The endpoint requires a username and password which I am passing along as follows:
export const getStream = async(req, res) => {
let conn = createConnection(config);
let query = `SELECT * FROM cameras WHERE id = ${req.params.id}`
conn.connect();
conn.query(query, async (error, rows, _) => {
const camera = rows[0];
const {ip, user, pass} = camera;
if (error) {
return res.json({ "status": "failure", "error": error });
}
const tok = `${user}:${pass}`;
const userPass = Buffer.from(tok)
const base64data = userPass.toString('base64');
const basic = `Basic ${base64data}`;
const result = await axios({
method: 'get',
url: `<API URL>`,
headers: {
'Authorization': basic,
'Content-Type': 'multipart/x-mixed-replace; boundary=--myboundary'
},
auth: {username: user, password: pass}
})
res.json(result)
});
conn.end();
}
I am then calling this endpoint in my React front-end as such:
const getStream = async () => {
try {
const result = await publicRequest.get(`camera/getStream/${id}`)
console.log(result)
} catch (error) {
console.error(error)
}
}
Each time I make this request, my node server crashes and I get a 401 unauthorized error in my console. It appears that my Authorization header is not getting passed to the server even though everything else gets passed along as so.
headers: {
Accept: 'application/json, text/plain, */*',
'Content-Type': 'multipart/x-mixed-replace; boundary=--myboundary',
'User-Agent': 'axios/0.26.1'
},
method: 'get',
url: '<url>',
auth: { username: '<username>', password: '<password>' },
data: undefined
For extra information, this is how my node server is setup
import express, { urlencoded, json } from 'express';
import userRoute from './routes/userRoute.js';
import cameraRoute from './routes/cameraRoute.js';
import cors from 'cors';
const app = express();
app.use(cors());
app.options('*', cors());
app.use(json())
app.use(urlencoded({ extended: true }));
app.use(express.static('public'));
app.use('/api/user', userRoute);
app.use('/api/camera', cameraRoute);
const port = process.env.PORT || 8080;
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
I have been working on this issue for several days and each time I try something new, I always get a 401 error, and the server crashes.
Any suggestions would be greatly appreciated.
I've a simple API in Express/Node and I also have a simple angular application for posting blogs. The only problem is when I hit the /contribute route using POST method. I'm getting this error on both chrome and firefox:
error: error { target: XMLHttpRequest, isTrusted: true, lengthComputable: false, … }
headers: Object { normalizedNames: Map(0), lazyUpdate: null, headers: Map(0) }
message: "Http failure response for localhost:3000/api/contribute: 0 Unknown Error"
name: "HttpErrorResponse"
ok: false
status: 0
statusText: "Unknown Error"
url: "localhost:3000/api/contribute"
: {…}
constructor: class HttpErrorResponse { constructor(init) }
: {…}
constructor: class HttpResponseBase { constructor(init, defaultStatus, defaultStatusText) }
: {…
Here's my server side code.
api.js
...
router.post('/contribute', (req, res) => {
console.log('Pushing new article');
let userPost = req.body;
let post = new Post(userPost);
post.save((error, registeredPost) => {
if (error) {
console.log(error);
} else {
res.status(200).send(registeredPost);
}
})
})
...
module.exports = router;
server.js
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
const api = require('./routes/api');
const cors = require('cors');
app.use(bodyParser.json());
// app.use(cors({ origin: 'http://localhost:4200' })); <--- TRIED THIS ALSO
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200');
// Request methods you wish to allow
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Request headers you wish to allow
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
// Set to true if you need the website to include cookies in the requests sent
// to the API (e.g. in case you use sessions)
res.setHeader('Access-Control-Allow-Credentials', true);
// Pass to next layer of middleware
next();
});
app.use('/api', api);
app.get('/', function(req, res) {
res.send('Server is up and running!');
})
app.listen(3000, function() {
console.log('Server listening port:3000');
});
Yes, server is up and running.
Here is angular code.
auth.service.ts
private _contributeUrl = "https://localhost:3000/api/contribute";
...
pushNewPost(newPost) {
console.log("here is the new post", newPost); // GETTING CORRECT OUTPUT
return this._http.post<any>(this._contributeUrl, newPost);
}
contribute.component.ts
this._auth.pushNewPost(this.makeNewPost)
.subscribe (
res => {
(<HTMLInputElement>document.getElementById("inputTitle")).value="";
this.editorForm.reset();
this.addSingle();
},
err => console.log(err)
);
Now the fun part is that the same code is working perfectly when I make a post request to this route using Postman without any error.
Please correct my mistake. After adding:
pushNewPost(newPost) {
console.log("here is the new post", newPost);
let headers = new HttpHeaders({
'Content-Type': 'application/json',
});
let options = { headers: headers };
return this._http.post<any>(this._contributeUrl, newPost);
}
I'm getting this:
Seems like you are not sending in the headers from angular. Make the following changes:
pushNewPost(newPost) {
// adding the headers
const headers = new HttpHeaders({
'Content-Type': 'application/json',
});
const options = { headers: headers };
return this._http.post<any>(this._contributeUrl, newPost, options);
}
i have a server.js which has listening port 4000. Please check below code
const port = 4000;
const express = require('express')
const cors = require('cors')
const app = express()
const mysql = require('mysql');
const con = mysql.createConnection({
host: "localhost",
user: "root",
password: "",
database: "musteri"
});
con.connect(function(err) {
if (err) throw err;
console.log("Database Connected!");
});
app.use(cors());
app.use(express.urlencoded({ extended: false }));
// Parse JSON bodies (as sent by API clients)
app.use(express.json());
app.get('/user', function(req, res, next) {
console.log(req);
con.query('select * from musteri_ayarlar', function (error, results, fields) {
if(error) throw error;
res.send(JSON.stringify(results));
});
});
app.listen(port, (err) => {
if(err) { console.log(err) };
console.log('Service Port ' + port + ' started')
})
with above code listening localhost:4000/user
i can access without any problem from chrome when i call localhost:4000/user that returns a record from mysql.
My problem started when i call localhost:4000/user adress from fetch api.
it saying POST http://localhost:4000/user 404 (Not Found)
Here is my fetch code from app.jsx
componentDidMount() {
const requestOptions = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Access-Control-Allow-Origin':'*',
'Content-Type': 'applications/json'
},
body: JSON.stringify({ username: "John", password: 30 })
};
fetch(`http://localhost:4000/user`, requestOptions)
.then(handleResponse => handleResponse.text())
.then(user => {
console.log(user);
localStorage.setItem('user', JSON.stringify(user));
return user;
});
}```
What is wrong with my fetchAPI code? Thanks.
app.get('/user', function(req, res, next) {
console.log(req);
con.query('select * from musteri_ayarlar', function (error, results, fields) {
if(error) throw error;
res.send(JSON.stringify(results));
});
});
you have made an get endpoint here to access it
Change the request method in fetch
const requestOptions = {
method: 'GET',
headers: {
'Accept': 'application/json',
'Access-Control-Allow-Origin':'*',
'Content-Type': 'applications/json'
}
};
GET doesn't accept any body , as you are not using the request , this will satisfy
I am trying to deploy an angular 7 website that uses nodemailer to send receive emails but keep getting error 500 internal server error.
The angular side of the bunch works fine but i can't seem to figure out how to run the node server on the web (I realize this might be a dumb question but forgive me I am a newbie)
This is my contact us service
url: string = "/send"; //THIS MIGHT BE A PROBLEM
constructor(private http: HttpClient) {}
sendMessage(messageContent: any) {
return this.http.post(this.url, JSON.stringify(messageContent), {
headers: new HttpHeaders({ "Content-Type": "application/json" }),
responseType: "text"
});
And this is my server.js file
const express = require("express");
const nodemailer = require("nodemailer");
const app = express();
const port = 3000;
const bodyParser = require("body-parser");
const transporter = nodemailer.createTransport({
host: "smtp.gmail.com",
provider: "gmail",
port: 465,
secure: true,
auth: {
user: "an email",
pass: "a password"
},
tls: {
rejectUnauthorized: false
}
});
app.use(bodyParser.json());
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
next();
});
app.post("/send", function(req, res) {
let senderName = req.body.name;
let senderEmail = req.body.email;
let messageSubject = req.body.subject;
let messageText = req.body.message;
let copyToSender = req.body.contactFormCopy;
let mailOptions = {
to: ["anemail"],
from: senderName,
subject: messageSubject,
text: messageText,
replyTo: senderEmail
};
if (senderName === "") {
res.status(400);
res.send({
message: "Bad request"
});
return;
}
if (senderEmail === "") {
res.status(400);
res.send({
message: "Bad request"
});
return;
}
if (messageSubject === "") {
res.status(400);
res.send({
message: "Bad request"
});
return;
}
if (messageText === "") {
res.status(400);
res.send({
message: "Bad request"
});
return;
}
if (copyToSender) {
mailOptions.to.push(senderEmail);
}
transporter.sendMail(mailOptions, function(error, response) {
if (error) {
console.log(error);
res.end("error");
} else {
console.log("Message sent: ", response);
res.end("sent");
}
});
});
app.listen(port, function() {
console.log("Express started on port: ", port);
});
I try to send data from my client to my server. For that, i use React with NextJS, because you have the server and client-side in one app.
I use the following handleSubmitFunction:
handleSubmit() {
const email = this.state.email;
fetch('/', {
method: 'POST',
body: email,
});
}
and this is my server.js file in the located in / at my project
const express = require('express')
const next = require('next')
const bodyParser = require('body-parser')
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare()
.then(() => {
const server = express()
//parse application
server.use(bodyParser.urlencoded({ extended: false}))
//parse application/json
server.use(bodyParser.json())
server.post('/', (req, res) => {
console.log(req.body.email);
res.end("success!");
})
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(3000, (err) => {
if (err) throw err
console.log('> Ready on http://localhost:3000')
})
})
.catch((ex) => {
console.error(ex.stack)
process.exit(1)
})
When the handleSubmit Function is running, i get the following Output from the Server Console:
Cannot read property 'email' of undefined
Where exactly is my mistake?
I have little experience in node JS environments. I would be very grateful if you could show me concrete solutions. Thank you for your replies.
It seems you have to parse header and JSON.stringify the email.
fetch('/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({email:email}),
}).then((res)=> console.log('Worked'))