Best practice for using API - node.js

I have some CRUD controllers set up in my project like this:
var getMaps = function (req, res) {
Map.find({}).exec(function (err, collections) {
res.send(collections);
});
};
In order to use these in the server side code, I've been using node's http.get like this:
var options = {
host: 'localhost',
port: 3030,
path: '/api/map'
};
http.get(options, function (res) {
var data = '';
res.on("data", function (chunk) {
data += chunk;
}).on('end', function () {
data = JSON.parse(data);
console.log(data);
});
}).on('error', function (e) {
console.log("Got error: " + e.message);
});
where my routes file contains
app.get('/api/map', map.getMaps);
Is this the correct way of doing it? It seems like it would be slow since it is an http request but I don't know any other way to do it

Better you go through $http and $resource links once to have a better understanding of angular's APIs.
You can also try out the MEANs CRUD module which comes by default when you generate a MEAN application.

Related

Getting Checking your browser before accessing template and 503 status code with https.request(options,callback) node.js

I want to get the html of this page for parsing(click the link to understand what content i want to get).
750-bond list
Here's my code to request this page content
var https = require("https");
var fs = require("fs");
var options = {
hostname: "www.prizebond.net",
port: 443,
path: "/dlist.php?num=455",
method: "GET"
};
var response = "";
var req = https.request(options, function (res) {
res.setEncoding("UTF-8");
console.log(res.statusCode);
res.on("data", function (chunk) {
response += chunk;
});
res.on("end", function () {
fs.writeFile("750-bond.html", response, function (err) {
if (err) {
console.log(err.message);
}
console.log("File downloaded");
});
console.log("end");
});
});
req.end();
Now the problem is that in my 750-bont.html file, I am getting the weird the
result of "Checking your browser before accessing the prizebond.net" not the
original content. Here's the screenshot what I got when I open the 750-
bond.html file in browser.
What I am doing wrong? And how can I get the original content of this webpage?
You can't, unless you write something more sophisticated, but you probably shouldn't.
The purpose of Cloudflare-protection is to prevent what you are trying to realize unfortunately.
You could look into a possibility to access whatever you want to access by a public API or something that prizebond.net provides for example.

Wait for JSON response data from POST request in nodejs (mocha test)

I'm aware that there are several questions related to mine, but I didn't find any of them useful:
this one doesn't apply to my case, I'm actually getting the answer, it's the contents that I can't get.
on this one, on the other hand, the problem is a wrong handling of an asynchronous call, which is not my case
there, well, I really didn't fully understand this question
And so on...
Then, I think this is a legitimate question. I'm actually performing some encryption in my server (express routing in node) through a post request:
app.post('/encrypt', encrypt);
Encrypt is doing:
function encrypt(req,res) {
if(req.body.key && req.body.message) {
var encryptedMessage = Encrypter.encrypt(req.body.key,req.body.message);
return res.status(200).json({ message: encryptedMessage });
}
res.status(409).json({ message: 'the message could not be encrypted, no key found' });
}
}
So, I tested this via console.log, and it's working. When the server receives the request, the encrypted message is being generated.
At the same time, I'm testing my thing with mocha and I'm doing it like so:
describe('# Here is where the fun starts ', function () {
/**
* Start and stop the server
*/
before(function () {
server.listen(port);
});
after(function () {
server.close();
});
it('Requesting an encrypted message', function(done) {
var postData = querystring.stringify({
key : key,
message : message
});
var options = {
hostname: hostname,
port: port,
path: '/encrypt',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': postData.length
}
};
var req = http.request(options, function(res) {
res.statusCode.should.equal(200);
var encryptedMessage = res.message;
encryptedMessage.should.not.equal(message);
done();
});
req.on('error', function(e) {
//I'm aware should.fail doesn't work like this
should.fail('problem with request: ' + e.message);
});
req.write(postData);
req.end();
});
});
So, whenever I execute the tests, it fails with Uncaught TypeError: Cannot read property 'should' of undefined because res.message does not exist.
None of the res.on (data, end, events is working, so I suppose the data should be available from there. First I had this:
var req = http.request(options, function(res) {
res.statusCode.should.equal(200);
var encryptedMessage;
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
encryptedMessage = chunk.message;
});
encryptedMessage.should.not.equal(message);
done();
});
But res.on was never accessed (the console.log didn't show anything). I'm therefore a bit stuck here. I'm surely doing some basic stuff wrong, but I don't have a clue, and the many questions I found doesn't seem to apply to my case.
Weird enough, if I launch a test server and then I curl it
curl --data "key=secret&message=veryimportantstuffiabsolutellyneedtoprotect" localhost:2409/encrypt
Curl justs waits ad aeternam.
Actually I was doing it properly at the beginning, and the problem was indeed the same than in the second question I mentionned I was actually "clearing" my context with done() before the post data arrived. The solution is:
var req = http.request(options, function(res) {
res.statusCode.should.equal(200);
res.on('data', function(data) {
encryptedMessage = JSON.parse(data).message;
encryptedMessage.should.not.equal(message);
done();
});
});
In such a way that done() is only called when the data has been threated. Otherwise, mocha will not wait for the answer.

node.js multiple http requests

I am a newbie to node and js and try to create a website in express that makes three Rest API calls before rendering the page. At the moment I have the below, which returns some json which I convert into a list of objects.
Some of these properties only return id values and I would like to run three more API requests that return lookups on these Id's so that I can present this data to the user as meaningful values.
I could do this synchronously by running the next API call where I am currently rendering the index page, but that looks really messy. All the async tutorials I have seen confuse the hell out of my newbie way of thinking though. Can someone post an easy to follow example for async that somewhat reflects the below structure?
var issues_json = "";
var request = http.request(options, function(response) {
console.log("statusCode: ", res.statusCode);
console.log("headers: ", res.headers);
response.on("data", function(data) {
issues_json += data;
});
response.on("end", function() {
console.log(issues_json);
var column_obj = JSON.parse(issues_json);
res.render('index', {
title: 'List of Issues',
response: issues_json,
objects: column_obj
});
});
response.on("error", function(e) {
console.log(e.Message);
res.render('index', {
title: 'error',
e: e.Message
});
});
});
request.end();
You should use Request
You would have something like
app.get("/route", function(req, res) {
var callbackThree = function(error, resp, body) {
var data = JSON.parse(body);
res.send({title; "My Title", data: data});
}
var callbackTwo = function(error, resp, body) {
request("api.com/42", callBackThree);
}
var callbackOne = function(error, resp, body) {
request("api.com/things", callBackTwo);
}
request("api.com/users", callBackOne);
}
check this out: https://github.com/JacksonTian/eventproxy. It's a js lib which makes async calls into events. The only difference from the ticked answer is its way of writing code.

node.js: Mock http request and response

Is there convenient way to mock the HTTP Request and Response objects for unit testing middlewares?
It looks like both https://github.com/howardabrams/node-mocks-http and https://github.com/vojtajina/node-mocks can be used to create mock http.ServerRequest and http.ServerResponse objects.
From the tag, it looks like this question is about Express. In that case, supertest is very good:
var request = require('supertest')
, express = require('express');
var app = express();
app.get('/user', function(req, res){
res.send(201, { name: 'tobi' });
});
request(app)
.get('/user')
.expect('Content-Type', /json/)
.expect('Content-Length', '20')
.expect(201)
.end(function(err, res){
if (err) throw err;
});
For general Node use, Flatiron Nock looks like a good option:
var nock = require('nock');
var example = nock('http://example.com')
.get('/foo')
.reply(200, { foo: 'bar' });
var http = require('http');
var options = {
host: 'example.com',
port: 80,
path: '/foo',
method: 'GET'
}
var req = http.request(options, function(res) {
res.on('data', function(chunk) {
console.log('BODY: ' + chunk);
});
});
req.on('error', function(e) {
console.log('error: ' + e);
});
req.end();
Output:
BODY: {"foo":"bar"}
i'm using nodejutsu mock:
https://github.com/nodejitsu/mock-request
Maybe this is what you are looking for.
I wrote a library to mock out the responses of requests made via standard HTTP or via the request model:
https://github.com/ctide/fakeweb
Check out https://github.com/timsavery/node-hmock or npm install hmock...any feedback welcome! The solution has worked well for me thus far.
Mockery looks great for this.
Essentially it hijacks require calls, and returns a different object/function stub that you specify.
Belatedly, if you're looking only to unit test the handler, you could inject express.Request and express.Response objects into the request function, or in this case, your middleware.
One that seemed to provide the minimal methods while keeping it simple was, for me, #jest-mock/express
If you're using supertest or nock, you're doing an integration test which can couple multiple tests. I'd also look into how it works internally because it is going be a pain to debug once it stops working.
it('should call next',
async () => {
const req = getMockReq({
headers: {
'user-agent': 'Chrome',
},
path: '/path',
})
const{res, next, clearMockRes} = getMockRes({})
await middleware(req, res, next)
expect(res.send).not.toHaveBeenCalledWith()
expect(next).toHaveBeenCalled()
})
I do not recommend this solution for real world usage, but this is the hack I used just to avoid exceptions in an experiment.
const mock_response_obj = {
statusCode: null,
setHeader: () => {},
writeHead: () => {},
end: () => {},
}
Obviously extend it as needed. Sharing in case anyone else is looking for a simple stopgap.
I encourage you to use motty. why do we need an another code?

How to make web service calls in Expressjs?

app.get('/', function(req, res){
var options = {
host: 'www.google.com'
};
http.get(options, function(http_res) {
http_res.on('data', function (chunk) {
res.send('BODY: ' + chunk);
});
res.end("");
});
});
I am trying to download google.com homepage, and reprint it, but I get an "Can't use mutable header APIs after sent." error
Anyone know why? or how to make http call?
Check out the example here on the node.js doc.
The method http.get is a convenience method, it handles a lot of basic stuff for a GET request, which usually has no body to it. Below is a sample of how to make a simple HTTP GET request.
var http = require("http");
var options = {
host: 'www.google.com'
};
http.get(options, function (http_res) {
// initialize the container for our data
var data = "";
// this event fires many times, each time collecting another piece of the response
http_res.on("data", function (chunk) {
// append this chunk to our growing `data` var
data += chunk;
});
// this event fires *one* time, after all the `data` events/chunks have been gathered
http_res.on("end", function () {
// you can use res.send instead of console.log to output via express
console.log(data);
});
});

Resources