Ionic2 : POST request not working - node.js

I prepared my server with Node.js (tested with Chrome Postman and everything works fine). It is installed in an Ubuntu 16.04 Server virtual machine and Im testing everything from the host machine (win7). Then I added Ionic2 framework on my virtual machine and start the development of the front-end but I have problem in sending the request POST.
I created a provaider with the following code:
import { Injectable } from '#angular/core';
import { Http, Headers } from '#angular/http';
import 'rxjs/add/operator/map';
#Injectable()
export class MyProvider1 {
data: any;
constructor(public http: Http) {
this.data = null;
}
login(id,pwd){
let headers = new Headers();
headers.append('Content-Type', 'application/json');
this.http.post('http://localhost:8080/',
JSON.stringify({
username: id ,
password: pwd
}), {headers: headers})
.subscribe(res => {
console.log(res.json());
});
}
}
It should be working but when the login function is called, my node.js server logs a strange request:
OPTION / 200 0.348 ms -13
Instead of a POST request. Moreover, in my host chrome browser the console shows the following failure:
XMLHttpRequest cannot load http://localhost:8080/. Response to
preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:8100' is therefore not allowed
access.
Just for trial I removed the {headers: headers} and the http.post became:
this.http.post('http://localhost:8080/',
JSON.stringify({
username: id ,
password: pwd
}))
.subscribe(res => {
console.log(res.json());
});
In this way Morgan logs in my Node.js a POST request BUT the req.body is empty (if I do console.log(req.body) the output will be {} ).
Just in case, I post in the following part of my server Node.js code:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var morgan = require('morgan');
var mongoose = require('mongoose');
//------------------------------------
//Configuration
//------------------------------------
var config = require('./config.js');
var port = process.env.PORT || config.SERVICE_PORT;
app.use(morgan('dev'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
//------------------------------------
//Routes
//------------------------------------
app.use('/admin', require('./app/routes/admin.js'));
app.use('/', require('./app/routes/guest.js'));
app.use('/chat', require('./app/routes/chat.js'));
//------------------------------------
//Server Start
//------------------------------------
mongoose.connect(config.database);
app.listen(port);
console.log('server start at port ' + port);
And my /app/routes/guest.js contains the following code:
...
router.route('/')
.get(function(req,res){
res.end('Welcome');
})
.post(function(req,res){
UsersManager.login(req.body.username,req.body.password,function(err,user){
if(err) throw err;
if(!user){
res.json({
success: false,
message: Const.notificationTokenAccessNOK
});
}else{
var token = TokenManager.createToken(user);
res.json({
success: true,
message: Const.notificationTokenAccessOK,
token: token
});
}
});
});
module.exports = router;

You can not perform network request(atleast not directly) from your ionic2 code while testing it in chrome browser.
But if you want to, You can put proxy in ionic.config.json file as followed:
{
"proxies": [{
"path": "/localhost/",
"proxyUrl": "http://localhost:8080/"
}]
}
then you can perform post request as followed :
this.http.post('/localhost/',
JSON.stringify({
username: id ,
password: pwd
}))
.subscribe(res => {
console.log(res.json());
});

Related

CORS blocking post requests - react and node.js

I am a beginner in server side programming. Trying to write code that will allow me to get data from state variable, send it to my backend and use nodemailer service to send it to an email adress. My frontend is as follows :
const handleSubmit = async () => {
try {
await axios.post(
"http://localhost:2525/send_mail",
{
state
}
);
} catch (error) {
console.log(error);
}
};
state gets sent to backend :
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const nodemailer = require('nodemailer');
require('dotenv').config();
const app = express();
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors());
app.options('',cors());
app.get('/', (req, res) => {
res.send('Server is running');
});
app.post("/send_mail", cors(), async (req, res) => {
let { state } = req.body;
const transport = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'adress#mail.com',
pass:'password'
}
});
await transport.sendMail({
from: '<myemail.#example.com>',
to: "reciever#example.com",
subject: "test email",
html: `<div><p>${state.Message}</p></div>`
});
});
app.listen(process.env.PORT || 2525, () => { console.log("Server is running"); });
If it matters, state is an object that gets filled from form data, it looks something like :
const data = {
FirstName: "",
LastName: "",
Message:"",
};
When i visit port 2525, server is indeed running with the message i gave it. But when i try to submit my form with "handleSubmit", i get the following console error:
*>
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:2525/send_mail. (Reason: CORS request did not succeed). Status code: (null).*
And it crashes the server
As you can see i am already using cors middleware to try to handle it.
I tried adding a proxy to the package.json file, as : "proxy": "http://localhost:2525", ( i did not change anything else when i did that, i don't know if that is the correct way). This did not solve anything, but at least the server did not crash any more. Instead, the POST request gets a 404:
*
POSThttp://localhost:2525/send_mail Referrer Policystrict-origin-when-cross-origin*
I tried running it in Chrome, same problem. I tried everything i could read on stackoverfrlow google or chat gpt, really that is cors-related. Even checked if port is maybe taken by something else in windows, checked that in cmd. Im at my wits end really

Json response returning HTML in nodejs/react page

I'm new react and nodejs and full stack development in general. I'm trying to make a login page in nodejs/react/mysql. Right now, I'm just trying to do get request for the main login page. I think I'm struggling with connecting the front and backend and the moment.
Nodejs app.js:
const express = require('express');
const bodyparser = require('body-parser');
const cors = require('cors');
const app = express();
const mysql = require('mysql');
let connection = mysql.createConnection({
//Connection is encrypted for security reasons.
host: '***********',
user: '***********t',
password: '***********',
database: '***********'
});
connection.connect(function(err) {
if (err) {
return console.error('error: ' + err.message);
}
console.log('Connected to the MySQL server.');
});
app.listen(3001, () => { console.log('running on port 3001'); });
app.use(cors());
app.use(express.json()); a
app.use(bodyparser.urlencoded({extended: true}));
app.get('/', (req, res) => { res.send('respond with a resource'); });
componentDidMount() react code/fetch request:
componentDidMount() {
// GET request using fetch with error handling
fetch('/')
.then(async response => {
const data = await response.text();
// console.log(data);
console.log('test',data);
// check for error response
if (!response.ok) {
// get error message from body or default to response statusText
const error = (data && data.message) || response.statusText;
return Promise.reject(error);
}
this.setState({ totalReactPackages: data.total })
})
.catch(error => {
this.setState({ errorMessage: error.toString() });
console.error('There was an error!', error);
});
}
My sql connection works fine, I think it's an issues connecting the front end and backend. Changing following line:.
const data = await response.text();
to:
const data = await response.json();
Returns the following error:
There was an error! SyntaxError: Unexpected token < in JSON at position 0
This is the html it returns in the following screenshot:
Once I figure out how to connect the front end and backend the rest of the project should be easyish to do. The react UI work and my SQl connection works fine. Any help would be greatly appreciated.
You're currently fetching data from the primary site, not the Node.js site you've created.
You should change the fetch to:
fetch('http://localhost:3001')
Additional information
The response you are sending from the backend isn't JSON:
res.send('respond with a resource');
To send JSON, you should use:
res.json({ message: "respond with a resource" });
Then you'll be able to use:
const data = await response.json();
And access the data via:
const message = data.message;
For me it worked just by appending "Https://" to the beginning of the API url.
fetch(`https://api.openweathermap.org/data/2.5/weather?q=${CITY_NAME}&appid=${API_KEY}`)
It took me days and 10s of articles/SO threads to figure out that when doing dev on your local machine the fetch request gets routed to local html document.

when i console req.body it,s give me all property with value but when i get single property value it,s give me error undefined

i am working on angular and nodejs i registering new user from angular side data properly goes to nodejs side but in nodejs side when i console req.body it,s give me properties with value but when i want to get single property value it,s give me error undefined
this is my index.js
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
//this line is use to connect with mongodb
const {mongoose} = require('./db.js');
var userController = require('./controllers/userController.js');
const app = express();
app.use(bodyParser.json());
app.use(cors({ origin : 'http://localhost:4200' }));
// it,s listening port 3000
app.listen(3000,() => { console.log('app listen port : 3000'); });
//here is the user operation start
app.use('/user',userController); //end of the user operation
this is my userController file
router.post('/',(req,res) => {
var newUser = new User({
firstName:req.body.firstName,
firstLast:req.body.lastName,
emailAddress:req.body.emailAddress,
passowrd:req.body.password,
user_role:2,
account_status:1,
});
var recordExist = false;
User.findOne({emailAddress:req.body.emailAddress},(error,doc) => {
if(doc)
recordExist = true;
else
console.log('there is an error to get record with given email :' + req.body.emailAddress);
});
res.send(req.body.emailAddress);
});
when i console req.body it,s give me everything ok properties with values
but when i console req.body.emailAddress it,s give me undefined
firstName: "abubakkar", lastName: "khan", emailAddress:
"abubakkar.tahir.khan#gmail.com", password: "12345"} firstName:
"abubakkar" lastName: "khan" emailAddress: "abubakkar.tahir.khan#gmail.com" password: "12345"
You need to parse the req.body to JSON
req.body = JSON.parse(req.body)
console.log(req.body.emailAddress) // now it will work
I just ran into this exact problem, and I realized that the problem was with my client side fetch function. It could be that the request you are making is causing the problem. I was missing the "Content-Type": "application/json" header in my request. When you forget to add this req.body is a string. If you include the "Content-Type": "application/json" header in your request then you should have an object in req.body.
// client request
fetch("/api/route", {
method: "POST",
body: JSON.stringify({ content: "foo" }),
headers: {
"Content-Type": "application/json",
},
)
Then in express you should be able to get
console.log(req.body.content)
\\ output: "foo"

Express backend dropping data when passed from Angular 5 App

I am building a little demo app to send emails from a form using Node Mailer. I've connected an Angular 5 app to an Express 4 backend. I am running things very simply, with a server.js express file in my project referencing the angular dist file. I then build the angular app and run the server.
Everything is working fine, and the email even sends, but somehow the express backend is losing the data (or I am just not accessing it correctly). The email sends with "undefined" everywhere that I try to use data.
I fill out form fields for name, phone, email, and address. Then I pull the data into a service and send it to the backend. This is my service in Angular that sends the data:
import { Injectable } from '#angular/core';
import { HttpClient } from '#angular/common/http';
#Injectable()
export class ClientService {
headers: any;
clientInfo = '';
constructor(private http: HttpClient) { }
sendEmail(clientData) {
console.log(clientData);
return this.http.post('/send-email', clientData);
}
}
When I send this http post it looks good. The request url is correct, the header is application/json, and the payload data is correct: {name: "John Doe", email: "john#johndoemail.com", phone: "18005555555", message: "test"}
Here is my server.js: (sub in a valid gmail account info where there are x's)
// Get dependencies
const express = require('express');
const nodemailer = require("nodemailer");
const path = require('path');
const http = require('http');
const bodyParser = require('body-parser');
const app = express();
const port = 4300;
// Start server
app.listen(port, function(req, res) {
console.log('Server is running at port: ', port);
})
// Point static path to dist
app.use(express.static(path.join(__dirname, 'dist')));
// Home route to serve the index file
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/index.html'));
});
// Parsers for POST data
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/send-email', function (req, res) {
console.log(req.body);
let transporter = nodemailer.createTransport({
host: 'smtp.gmail.com',
port: 465,
secure: true,
auth: {
user:'xxxxxx#gmail.com',
pass: 'xxxxxxxx',
}
});
let message = {
from: 'mailer#nodemailer.com',
to: 'xxxxx#gmail.com',
subject: 'New Client Message ' + req.body.name,
text: 'Name: ' + req.body.name + '\nEmail: ' + req.body.email + '\nPhone: ' + req.body.phone + '\n ' + req.body.message,
html: '<p>' + req.body.message + '</p>'
};
transporter.sendMail(message);
res.json(req.body);
});
In the server console req.body shows up as "{}".
Using my own email, I get a message sent from nodemailer, but all of the data used simply says "undefined".
Do I need to access the data differently? Maybe use another property of req? Anyway, it looks like the issue is in my express file, so let me know if you see any issues there.
I found the solution. I was not implementing a header with my post data. I added these changes to my service and the issue was resolved:
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders } from '#angular/common/http';
#Injectable()
export class ClientService {
httpHeader = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
})
};
constructor(private http: HttpClient) { }
sendEmail(clientData) {
console.log(clientData);
this.http.post('/send-email', clientData, this.httpHeader);
}
}
If you want to see the full demo look here: https://github.com/xTumulus/NodeMailer_AngularExpress_Demo

401 Error with post request Stormpath Express + React + Node + Gulp

When attempting to login any user, the following POST error results:
XMLHttpRequest cannot load https://api.stormpath.com/v1/applications/[APP_HREF]/login. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 401.
In my server.js file, I have put the following:
var express = require('express');
var stormpath = require('express-stormpath');
var cors = require('cors');
var app = express();
app.use(stormpath.init(app, {
apiKey: {
id: 'xyz',
secret: 'abc' // Using the unsafe inline option for example purposes
},
application: {
href: `[APP_HREF]`
},
web: {
produces: ['application/json']
},
debug: 'info'
}));
app.use(cors({
origin: 'http://localhost:8080',
credentials: true
}));
app.post('/', stormpath.loginRequired, function (req, res) {
function writeError(message) {
res.status(400);
res.json({ message: message, status: 400 });
res.end();
}
});
app.on('stormpath.ready', function () {
var server = app.listen(process.env.PORT, function() {
try {
process.send('CONNECTED');
} catch(e) {}
});
});
In my login.jsx file, I have included:
login: function(e) {
e.preventDefault();
e.stopPropagation();
this.serverRequest = $.post('https://api.stormpath.com/v1/applications/[APP_HREF]/login',
{
"username": document.getElementById("email").value,
"password": document.getElementById("pass").value
}, function (result) {
console.log(result);
});
I also have saved my stormpath.yml file.
I'm not using React-Stormpath because I already created my views for Login and Registering. It looks like I only need to access the REST api with Stormpath, but I'm not sure what I need to add in order to get the API key validated.
On the actual login.jsx file, would I have to send the ID:SECRET pair as well as part of the POST request?
I see that in your login.jsx you are trying to post directly to the Stormpath REST API, but unfortunately that isn't possible yet. Instead you will make the post to your Express server, and in turn it will communicate with Stormpath.
You already have express-stormpath in your Express server, so you just need to post your login form to /login and Stormpath will take care of the rest :)
Let us know if you run into any issues! FYI, we will be adding a "serverless" feature soon, you can follow that here: http://ideas.stormpath.com/ideas/IAM-I-59

Resources