How to send form data as json in angular2 - json

I am trying to send my form data as json but not able to do so can any one help please....
my ts,
headers.append('Content-Type', 'application/x-www-form-urlencoded')
this.http.post(this.header1+'login', JSON.stringify(form), { headers: headers })
.subscribe(
response => {
if (response.json().error_code == 0) {
// console.log(response.json().data[0].profile_id);
if (response.json().data[0].profile_id) {
localStorage.setItem('social', JSON.stringify(response.json().data[0]));
}
this.toastr.success('Loggedin successfully');
this.router.navigate(['/demo/profile']);
}
else {
this.toastr.error('Email or Password is wrong');
}
});
}
but i am not able to see any data going to server from network

i cleared it by including the following steps in my node.js
app.use(function (req, res, next) {
// Website you wish to allow to connect
res.header('Access-Control-Allow-Origin', '*');
// Request methods you wish to allow
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
// Request headers you wish to allow
res.header('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.header('Access-Control-Allow-Credentials', true);
// Pass to next layer of middleware
res.header('Access-Control-Allow-Headers', 'Content-Type, application/json');
next();
});

Related

Passing Data from node js to html

I am connecting to an authentication server which is returning the credentials and calling to my call back method. How do I pass the authenticated values back to the html to render?
Here is my code
function getHomePage()
{
// alert("here in ajax call")
$.ajax({
url: "/calloidcServer",
headers:{
'Access-Control-Allow-Methods':'POST, PUT, OPTIONS, DELETE, GET',
'Access-Control-Allow-Origin':['https://localhost:3000','https://localhost:9031'],
'Access-Control-Allow-Headers':'Origin, X-Requested-With, Content-Type, Accept',
'Access-Control-Allow-Credentials':true,
'Content-Type':'application/json',
},
type: "GET",
success: function (resp) {
console.log(resp)
$('#testoidc').append(resp);
},
error: function (resp, status, error) {
}
});
}
app.get("/calloidcServer",function (req, res, next) {
console.log('-----------------------------');
console.log('/Start login handler');
next();
},
passport.authenticate('oidc',{scope:"openid"})
)
app.get('/callback',(req,res,next) =>{
console.log(" call back from auth server here")
passport.authenticate('oidc',{ successRedirect: '/user',
failureRedirect: '/' })(req, res, next)
}
)
app.get ("/user",(req,res) =>{
res.header("Content-Type",'application/json');
var id_token_decode=jwt_decoder(req.session.tokenSet.id_token);
var decoded = jwt_decoder(req.session.tokenSet.access_token);
console.log(id_token_decode)
console.log(decoded);
console.log(path.join(__dirname + '/public/citizenHome.html'))
res.redirect("/citizenHome.html")
//res.send(JSON.stringify({tokenset:req.session.tokenSet,userinfo:req.session.userinfo},null,2));
})
When I redirect to citizenHome.html, I want to send back some data to it to show in the html? I have not used any view engine.
I am not sure if you can pass values to the HTML directly, but you can use any view-engine with Node.js that can help you pass values from the routes and render the page as you want.
You can use EJS, JADE or Pug.

How to use fetch to post with content-type of application/json

I have a react application that does a fetch call to an API as follows:
postForm(state) {
var formData = state.formData;
return fetch('http://localhost:3000/api/V0.1/formSubmit', {method: 'POST', headers: {"Content-Type": "application/json"}, body: JSON.stringify(formData)})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson);
return null;
})
.catch((error) => {
console.error(error);
});
}
however, it gets blocked by CORS as the spec states that application/json is non-standard content type.
However, I'm not sure how I can modify my fetch call to perform the required pre-flight request to get it to allow application/json.
The API call is:
app.post("/api/v0.1/formSubmit", function(req, res) {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:8080');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', '*');
var formData=req.body;
console.log(formData);
res.status(200).json(formData);
});
Before defining your routing. declare
app.use(function(req, res, next) {
var oneof = false;
if(req.headers.origin) {
res.header('Access-Control-Allow-Origin', req.headers.origin);
oneof = true;
}
if(req.headers['access-control-request-method']) {
res.header('Access-Control-Allow-Methods', req.headers['access-control-request-method']);
oneof = true;
}
if(req.headers['access-control-request-headers']) {
res.header('Access-Control-Allow-Headers', req.headers['access-control-request-headers']);
oneof = true;
}
if(oneof) {
res.header('Access-Control-Max-Age', 60 * 60 * 24 * 365);
}
// intercept OPTIONS method
if (oneof && req.method == 'OPTIONS') {
res.send(200);
}
else {
next();
}
});
In CORS, the request is checked for available methods on server. i.e. in OPTIONS request. When you get the successful response, you will able to send request.
You can enable CORS for specific pages also. study here https://github.com/expressjs/cors

Express Multiple res.json(); with middlewares

I'm trying to build a stateless API using JWT. I have a middleware function in my Router which checks if the JWT has expired, if it has, a new Token with a new timestamp is generated on the fly.
I would like to pass the new token along with the response in the JSON Object. My current approach is like this, but it of course doesn't work:
router.use(function (req, res, next) {
// JWT Expired
// Generate new JWT
res.write(JSON.stringify({token: token});
next();
});
router.get('/securedRoute' function(req, res) {
// Fetch data
res.json({data: data});
});
:
// Output should be:
{token: 'erg34jlkgjre.3f4fknlj.34f3', data: ['sdfa', 'sdf']}
It would be nice to find a way, where I don't have to alter all of my existing code and check if there is a new token.
Thanks for your help!
One option would be to add the authorization token in the response header:
router.use((request, response, next) => {
response.setHeader('Token', token);
next();
});
router.get('/securedRoute', (request, response) => {
response.json({ data: data });
});
Alternatively, you could always add the token to the request and then conditionally add the request.token into all of your routes like the previous answer suggested. Unfortunately that would mean that you need to modify all of your routes.
As an alternative you could override the response.json method and manually inject the token if it exists. In doing so, you wouldn't need to modify any of your routes.
router.use((request, response, next) => {
request.token = token;
((proxied) => {
response.json = function (data) {
if (request && request.token) {
data.token = request.token;
}
return proxied.call(this, data);
};
})(response.json);
next();
});
router.get('/securedRoute', (request, response) => {
response.json({ data: data });
});
In the example above, the response.json method is overridden in the middleware. This is done by passing a reference to the old response.json method and then calling it after conditionally injecting the token into the payload.
The answer is assuming you want to achieve that in same method
Rather than writing the token in middleware do something like
(req,res,next)=>{
req.token = newToken;
next();
}
And in your route
res.json(req.token ? {token:req.token,data:data} : {data:data});

passport send error by json

I'm making an app with express + passport and angularJS; I want to be able to send any errors produced from passport (such as username taken or no email provided) by json so my angularJS app can receive these errors in a json response. More specifically right now I want to have a json response to my signup POST method that outputs any errors. I have tried to do this for myself and I've search all over the web and stack overflow I just cannot work this out!
Here is my users route file in express:
var express = require('express');
var router = express.Router();
var isAuthenticated = require('../config/isAuthenticated');
module.exports = function(passport){
router.get('/loggedin', function(req, res){
res.send(req.isAuthenticated() ? req.user : '0');
});
router.post('/signup', passport.authenticate('local-signup', {
successRedirect : '/',
failureRedirect : '/signup',
failureFlash: true
}));
router.post('/login', passport.authenticate('local-login'), function(req, res){
res.send(req.user);
});
router.post('/signout', function(req,res){
req.logout();
res.json({redirect: '/'});
});
router.get('/authtest', isAuthenticated, function(req, res){
res.render('authtest', {user: req.user});
});
return router;
};
This is my passport signup strategy:
passport.use('local-signup', new LocalStrategy({
usernameField : 'username',
passwordField : 'password',
passReqToCallback : true
},
function(req, username, password, done){
process.nextTick(function(){
User.findOne({'local.username' : username}, function(err, user){
if(err) return done(err);
if (user) { //username already exists
return done(null, false, {message: 'Username already exists'});
} else if(!req.body.email) { //no email address provided
return done(null, false, {message: 'You must provide an email address!'});
} else {
var newUser = new User();
newUser.local.username = username;
newUser.generateHash(password, function(err, hash){
if(err) return done(err);
newUser.local.password = hash;
});
newUser.email = req.body.email;
newUser.servers = [];
newUser.save(function(err){
if(err) throw err;
return done(null, newUser);
});
};
});
});
}
));
I know looking at my code right now it looks like I haven't tried to solve this myself at all but this is just my latest working code; I have been stuck at this for the past few days!
Any help would be greatly appreciated :)
According to the current code of passport this is probably achievable by passing custom callback to handle all results of authentiction yourself. This callback is given after options or instead of those.
passport( "local-signup", { ... }, callbackFn );
or
passport( "local-login", callbackFn );
This callback is used in all resulting situations of trying to authenticae. It is thus invoked on processing errors like this:
callbackFn( err )
If (all configured) authentications have failed it is called with
callbackFn( null, false, challenge(s), status(es) )
On successfully having authenticated user the callback is invoked like so:
callbackFn( null, user, infos )
with infos optionally provided by strategies.
Now comes the bottom-side: In either situation passport.authenticate() skips usual processing but instantly invokes provided callback to care for the rest. This includes processing of any options passed in call for passport.authenticate() like flashing messages, preparing session and request for containing authenticated user etc.
Since options given passport.authenticate() are never passed into callback there is actually no obvious reason to use both.
When I was stumbling over the very same problem (linking passport-service with angular-js POST request) I declined to consider use of callback a proper solution. This callback isn't documented. And it doesn't even look quite useful for it isn't passing req, res and next to pass any actual request in callback. Thus it makes very little sense to use it at all and I'd expect it to vanish soon or to change its behaviour quite much.
So the second approach was about trying to figure out why there is a problem in AngularJS. Passport is sending plain text Unauthorized in response with status code 401. AngularJS is trying to parse this as JSON and produces Syntax error. The text Unauthorized results from passprt ending response very simply by invoking
res.statusCode = 401;
res.end(http.STATUS_CODES[res.statusCode]);
Thus a proper workaround might try to replace
either text in http.STATUS_CODES though this is having impact on processing further requests and thus isn't preferrable
or res.end() by an overloaded method acting differently if res.statusCode is 401.
Due to affecting any current request, only, I tried the latter. Replaced res.end() might be used to send any text you want:
router.post('/login',
function(req, res, next) {
var _end = res.end;
res.end = function() {
if (res.statusCode === 401) {
return _end('{"status":"Unauthorized"}');
}
return _end.apply(this, arguments);
};
next();
},
passport.authenticate('local-login'),
function(req, res) {
res.send(req.user);
}
);
Alternatively the replaced method might add previously missing response header information on content type, for this was actually causing issues in AngularJS processing that response as JSON by default.
router.post('/login',
function(req, res, next) {
var _end = res.end;
res.end = function() {
if (res.statusCode === 401) {
res.set("Content-Type", "text/plain");
}
return _end.apply(this, arguments);
};
next();
},
passport.authenticate('local-login'),
function(req, res) {
res.send(req.user);
}
);
Finally, either approach is really just a workaround. I think passport is in the need for revising this annoying limitation.

How to return a complex JSON response with Node.js?

Using nodejs and express, I'd like to return one or multiple objects (array) using JSON. In the code below I output one JSON object at a time. It works but this isn't exactly what I want. The response produced isn't a valid JSON response since I have many objects.
I am well aware that I could simply add all objects to an array and return that specific array in res.end. However I am afraid this could become heavy to process and memory intensive.
What is the proper way to acheive this with nodejs? Is query.each the right method to call?
app.get('/users/:email/messages/unread', function(req, res, next) {
var query = MessageInfo
.find({ $and: [ { 'email': req.params.email }, { 'hasBeenRead': false } ] });
res.writeHead(200, { 'Content-Type': 'application/json' });
query.each(function(err, msg) {
if (msg) {
res.write(JSON.stringify({ msgId: msg.fileName }));
} else {
res.end();
}
});
});
On express 3 you can use directly res.json({foo:bar})
res.json({ msgId: msg.fileName })
See the documentation
I don't know if this is really any different, but rather than iterate over the query cursor, you could do something like this:
query.exec(function (err, results){
if (err) res.writeHead(500, err.message)
else if (!results.length) res.writeHead(404);
else {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.write(JSON.stringify(results.map(function (msg){ return {msgId: msg.fileName}; })));
}
res.end();
});
[Edit] After reviewing the Mongoose documentation, it looks like you can send each query result as a separate chunk; the web server uses chunked transfer encoding by default so all you have to do is wrap an array around the items to make it a valid JSON object.
Roughly (untested):
app.get('/users/:email/messages/unread', function(req, res, next) {
var firstItem=true, query=MessageInfo.find(/*...*/);
res.writeHead(200, {'Content-Type': 'application/json'});
query.each(function(docs) {
// Start the JSON array or separate the next element.
res.write(firstItem ? (firstItem=false,'[') : ',');
res.write(JSON.stringify({ msgId: msg.fileName }));
});
res.end(']'); // End the JSON array and response.
});
Alternatively, as you mention, you can simply send the array contents as-is. In this case the response body will be buffered and sent immediately, which may consume a large amount of additional memory (above what is required to store the results themselves) for large result sets. For example:
// ...
var query = MessageInfo.find(/*...*/);
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(query.map(function(x){ return x.fileName })));