POSTing json to API with Angular 2/4 - json

I am new to angular 4 and REST API development. I have developed a Login API in back-end and it works fine when I call it using Postman:
In the front-end application which is an Angular 4 project, I have created a service to call this login API. Here is the method I created in this service:
sendCredential(username: string, password: string) {
const url = 'http://localhost:8080/authenticate/user';
const body = '{"username": "' + username + '", "password": "' + password + '"}';
const headers = new Headers(
{
'Content-Type': 'application/json'
});
return this.http.post(url, body, {headers: headers});
}
My first question is:
Is this the correct way to pass the json object and call this API?
And I also created a component which calls the method in the service. Here is the method/event-handler I created in this component:
onSubmit(uname: string, pwd: string) {
this.loginService.sendCredential(uname, pwd).subscribe(
res => {
this.loggedIn = true;
localStorage.setItem('PortalAdminHasLoggedIn', 'true');
location.reload();
},
err => console.log(err)
);
}
My second question is:
How should I check whether a token is returned back or an error?

Question 1:
You do not need to stringify the body object when you do a http.post() in angular. Just use a normal object will do, and the Http class will help you parse it internally:
sendCredential(username: string, password: string) {
const url = 'http://localhost:8080/authenticate/user';
//do not need to stringify your body
const body = {
username, password
}
const headers = new Headers(
{
'Content-Type': 'application/json'
});
return this.http.post(url, body, {headers: headers});
}
Question 2:
As for your error, note that Angular also catch every http error. and by http error, it means that any status code that is <200 or >=300 will be an error. So only status codes that is in between 200 and 300 is considered successful. Upon an error received, angular will throw an Observable error, which you will need to handle explicitly (which you did it correctly):
onSubmit(uname: string, pwd: string) {
this.loginService.sendCredential(uname, pwd).subscribe(
res => {
//token should be in your res object
this.loggedIn = true;
localStorage.setItem('PortalAdminHasLoggedIn', 'true');
location.reload();
},
err => {
//handle your error here.
//there shouldn't be any token here
console.log(error);
}
);
}
With your above code, you should receive your token in your successful callback, and it will be in the res object. If there's an error, no token should be received and you should handle the error at the error callback.

Related

NodeJS server performs POST request, but returns HTTPErrorResponse

I'm using Angular's HttpClient to perform a POST request to my NodeJS server, like so:
createData(data:any):Observable<any> {
// verifying the content type is need to ensure the JSON object is sent as
// JSON object to NodeJS server
const options = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
})
};
// This still throws an HTTPResponse error, -
// SyntaxError: Unexpected token A in JSON at position 0 at JSON.parse
return this._http.post(`${this.apiUrl}`, data, options);
}
And my server's POST function is set up like so:
router.post('/', async (req,res) => {
const body = req.body;
await database.execute(`
INSERT INTO Post (
title,
body,
date_added
) VALUES (
#title,
#body,
NOW()
)
`, {
title: body.title,
body: body.body,
})
res.end('Added post')
})
When createData is called, the POST method is performed (I checked the Network panel in dev tools, the response "Added post" is returned from the server, and my json object is sent as the payload), but the console still returns this HTTPErrorResponse:
SyntaxError: Unexpected token A in JSON at position 0 at JSON.parse () at XMLHttpRequest.onLoad (http://localhost:4200/vendor.js:7508:51) at ZoneDelegate.invokeTask (ht..
What could be the cause of this error, if the server function has returned successfully?
The server could return successfully, however the callback function CreateData was expecting a JSON object to be returned from the server. Because the string returned is not JSON, an HTTPErrorResponse was thrown. The solution is to change the string returned from my server to a JSON object, like so:
router.post('/', async (req,res) => {
const body = req.body;
await database.execute(`
INSERT INTO Post (
title,
body,
date_added
) VALUES (
#title,
#body,
NOW()
)
`, {
title: body.title,
body: body.body,
})
res.end({}) // returns successfully, no error
})

Unexpected string in JSON at position <position> by sending a body with Postman

I am trying to implement the ability of the server to generate and validate JWT. I didn't have experience in TypeScript and Postman before so I got this error from the server:
json: Unexpected string in JSON at position 26
This is the request I am sending with Postman
This is the function I use to generate JWT:
app.post("/generate", async (req, res) => {
console.log("req.body: " + req.body)
let body: any = await req.body;
const { name } = await body.value;
let token = await generateUserJWT(name)
res.json({ status: true, data: name, token:token });
});
What is wrong with my request?

Stripe Error Message 405 - "append .json to uri to use rest api"

I'm using Stripe, and trying to send a test webhook to my URL and database hosted by Firebase. When I "send test webhook," I get the following error message in the Stripe Console:
Test Webhook Error: 405
"append .json to your request URI to use the rest API"
My code is a direct copy of the tutorial: https://github.com/GaryH21/Stripe-Webhooks-Tutorial/blob/master/functions/index.js
Here is the code of my index.js:
const functions = require('firebase-functions');
const stripe = require("stripe")(functions.config().keys.webhooks);
const admin = require('firebase-admin')
admin.initializeApp();
const endpointSecret = functions.config().keys.signing;
exports.events = functions.https.onRequest((request, response) => {
let sig = request.headers["stripe-signature"];
try {
let event = stripe.webhooks.constructEvent(request.rawBody, sig, endpointSecret)
return admin.database().ref('/events').push(event)
.then((snapshot) => {
return response.json({ received: true, ref: snapshot.ref.toString() })
})
.catch((err) => {
console.error(err)
return response.status(500).end() // error saving to database
})
} catch (err) {
return response.status(400).end() // signing signature failed
}
})
exports.exampleDataBaseTrigger = functions.database.ref('/events/{eventId}').onCreate((snapshot, context) => {
return console.log({
eventId: context.params.eventid,
data: snapshot.val()
})
})
The only time in the tutorial and in my code that .json is used is in the line: return response.json({ received: true, ref: snapshot.ref.toString() })
Should I be appending .json onto "request" somewhere, such as in request.RawBody?
It isn't a problem with the signing keys, as that would give the 400 Error message, which I already dealt with and fixed.
I would be happy to share the code of other files in my app, but as far as I can tell none of the rest is relevant to the problem. Thank you very much.

The action did not produce a valid response and exited unexpectedly

I want to call a Node-RED flow from IBM Cloud Functions.
const https = require('https');
function main(params) {
const path = "/" + params.route + "?" + params.query_params ;
const options = {
hostname: params.hostname,
path: path,
port: 443,
method: 'GET'
};
return new Promise((resolve, reject) => {
https.get(options, (resp) => {
resp.on('data', (d) => {
let s = d.toString();
obj = JSON.parse(s);
resolve({ "gw_result": obj })
});
});
})
}
In the Node-RED flow I'm using a HTTP request to get data from another server. For test purposes I used a GET request to google.com but have same results using another Node-RED endpoint.
As soon as I invoke the web action I get the error message "The action did not produce a valid response and exited unexpectedly". The output of the Node-RED flow appears some seconds later in the web action's log although the Node-RED flow works properly and promptly (I used debug Node-RED debug nodes to check this).
The https GET request to Node-RED works well when I replace the http request in Node-RED by something else, e.g. a Function node, even when I use a Delay node to delay the response for a second or so.
This code works, although google.com does not return an object, of course.
var rp = require('request-promise');
function main(params) {
var uri = params.hostname + params.route + params.query_params
return new Promise(function (resolve, reject) {
rp(uri)
.then(function (parsedBody) {
obj = JSON.parse(parsedBody);
resolve({ "gw_result": obj
});
})
.catch(function (err) {
resolve({ message: 'failed!!', error: err.toString() });
});
});
}

FeathersJS Error Handler Unexpected Token < Issue

I am working on an Express App with MongoDB and trying to utilize FeathersJS for all my services. Here I'm running a test try to get an error message from the server to the client, but I have an issue with the response from the error handler. My req headers have the correct application/json stuff, so I assumed the Error Handler should send valid json back.
I know I'm not using the next callback in my function, but when I try to do that it gives the same error, so I'm thinking it has to do with the Error Handler. Any direction here would be greatly appreciated!
The first error log is on the server, which is correct.
Bucket Services
error >>>>> Bucket validation failed
Possibly Unhandled Rejection: Bucket validation failed, Promise { <rejected> 'Bucket validation failed' }
>>>>>> Error: Unexpected token < in JSON at position 0
at convert (/Users/jaruesink/Documents/Projects/Buckets/node_modules/feathers-rest/node_modules/feathers-errors/lib/index.js:365:79)
at toError (/Users/jaruesink/Documents/Projects/Buckets/node_modules/feathers-rest/lib/client/base.js:24:37)
at process._tickCallback (internal/process/next_tick.js:103:7)
my create function within the BucketService class:
create({
amount,
isFund = false,
name,
type,
userID: owner
}, params, next) {
const new_bucket = new Bucket({ name, amount, type, isFund, owner });
return new_bucket.save((error) => {
console.log('error >>>>>', error.message);
if (error) { return Promise.reject(error.message); }
return Promise.resolve(new_bucket);
});
}
my router file:
const feathers = require('feathers');
const errorHandler = require('feathers-errors/handler');
const rest = require('feathers-rest');
const router = feathers();
const LoginService = require('../services/login_service');
const UserService = require('../services/user_service');
const BucketService = require('../services/bucket_service');
// Enable REST services
router.configure(rest());
router.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
next();
});
router.use('/login', new LoginService());
router.use('/user', new UserService());
router.use('/bucket', new BucketService());
// Set up error handling
router.use(errorHandler());
module.exports = router;
I figured it out, the key was to correctly pass through a callback (next) function as the third parameter to handle errors. FeathersJS handles the Promise Rejections for you on errors. Then in my test I needed to convert the Feathers-Error to JSON before I could get the message.
I changed my test to:
it('can validate an incorrect bucket', (done) => {
const invalid_bucket = {
name: 'Invalid Bucket',
};
bucket_service.create(invalid_bucket, {}, (error) => {
error = error.toJSON();
assert(error.message.length > 0);
done();
});
});
and my create function to:
create({
amount,
isFund = false,
name,
type,
userID: owner
}, params, next) {
const new_bucket = new Bucket({ name, amount, type, isFund, owner });
return new_bucket.save()
.then(created_bucket => Promise.resolve(created_bucket))
.catch(next);
}