Where's the response's body using nodeJS request? - node.js

I'm implementing a simple app that simply sends some GET request to a nodeJS-express endpoint. This endpoint is returning just this:
router.get('/', (request, response) => {
response.status(500).send("Error message");
}
My app is using request to send the request like this:
request.get(BASE_URL)
.on("error", err => {
console.log(`ERROR: ${err}`)
})
.on("response", res => {
console.log(`RESPONSE: ${res.statusCode} - ${res.body}`)
});
But body is always undefined. I have tried to use:
.on("response", res => {
res.on("data", () => {
console.log(`RESPONSE: ${res.statusCode} - ${data}`)
}
});
But the data is some byte array. I just want the string message, where it is and how can I get it without using the callback syntax?

If You are using express you will need to inject the body-parser middleware for parsing the request body.
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.post('/login', (req, res) => {
console.log(req.body); //data
})

Related

Using axios to execute a post request in nodejs but I am not able to receive data in the post route

I am trying to execute a post request using axios but the req.body is showing empty object . Here is my code :
const postData = {
tournamentId: tournamentId,
category: category,
contestantId: contestantId,
};
axios.post(`${process.env.URL}/joinTournament`, postData)
.then((res) => {
console.log(`Status: ${res.status}`);
console.log("Body: ", res.data);
})
.catch((err) => {
console.error(err);
});
Try a few things like test your backend logic with Postman (An API Development Tool). Then try to console log your request in backend to confirm the request reaching is correct.
If all that checkout turn to your libraries if you are using expressjs try to use a middleware like body-parser and cors to send back responses
The Code being something like
For Cors
//Cors
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
app.get('/products/:id', function (req, res, next) {
res.json({msg: 'This is CORS-enabled for all origins!'})
})
app.listen(69, function () {
console.log('CORS-enabled web server listening on port 80')
})
For Body-parser
//body-parser
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
// parse various different custom JSON types as JSON
app.use(bodyParser.json({ type: 'application/*+json' }))
// parse some custom thing into a Buffer
app.use(bodyParser.raw({ type: 'application/vnd.custom-type' }))
// parse an HTML body into a string
app.use(bodyParser.text({ type: 'text/html' })
Might as well setup a checker block where you'd check that if the request is missing some necessary info to send back some understandable response.
I have solved this issue using qs and calling stringify method on postData . Here is my solution :
const qs = require("qs");
const postData = {
tournamentId: tournamentId,
category: category,
contestantId: contestantId,
};
axios.post(`${process.env.URL}/joinTournament`, qs.stringify(postData))
.then((res) => {
console.log(`Status: ${res.status}`);
console.log("Body: ", res.data);
})
.catch((err) => {
console.error(err);
});
if your server works very well with request from postman and every things is Ok, you can do like this, without third party module

Node.js: Is there a way to mock the prometheus pushgateway server?

I am using node.js package prom-client to try to push different custom metrics to the Prometheus Pushgateway server.
The code is working and now I am writing the test code for the functionality. I wonder whether there is a way to mock the Prometheus Pushgateway server?
I had tried to use a normal express API server (like the following)
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
let data = null;
// ROUTES FOR OUR API
// =============================================================================
const router = express.Router();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
router.get('/', (req, res) => {
console.log("pushgateway server: get to '/' received");
res.json(data);
});
router.post('/', (req, res) => {
console.log("pushgateway server: post to '/' received");
console.log(req.body);
data = req.body;
res.send('POST request to the homepage');
})
app.use(router);
// API JSON BASED ERRORS
// =============================================================================
app.use((err, req, res, next) => {
if (req.xhr) {
console.error(err);
res.status(500).send({ err: 'Something failed!' });
} else {
next(err);
}
});
app.use((err, req, res, next) => { // eslint-disable-line
console.error(err);
res.status(500).send({ err: err.message });
});
// START THE SERVER
// =============================================================================
const port = 9876;
const server = app.listen(port, '0.0.0.0');
console.log(`Prometheus Pushgateway Mock Server is listening on port ${port}`);
// SHUTDOWN HANDLING
// =============================================================================
// Nodemon Signal Handling
process.once('SIGUSR2', () => {
console.log('Received kill signal, attempting gracefully close');
server.close(() => {
console.log('Closed out remaining connections');
process.kill(process.pid, 'SIGUSR2');
});
setTimeout(() => {
console.error('Timeout, forcefully shutting down');
process.kill(process.pid, 'SIGUSR2');
}, 3000);
});
module.exports = server;
but it did not work -- when I call gateway.pushAdd() on my test code, the server did not receive any post message.
Can anyone give me some hints on how to do this (mock the prometheus pushgateway server)?
There are different options out there to mock a third party http server. Here are 3:
Nock
Dyson
Stubborn
Disclaimer: I am the maintainer behind stubborn.
Nock and Dyson are the most popular ones, they have pro and cons. Stubborn is more recent and tries to cover some limitations of Nock and Dyson.
You can checkout this reddit post first comment I wrote for a comparison between the 3 solutions.
So I have solved the problem by creating a simple http server.
The following is the code of the server:
const http = require('http');
const body = [];
let text = null;
let path = null;
function createServer(port) {
return http.createServer()
.on('request', (req, res) => {
if (req.method === 'POST' || req.method === 'PUT') {
path = req.url;
req.on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
text = Buffer.concat(body).toString();
res.end(`${req.method} success`);
}).on('error', (err) => {
console.error(err);
});
} else if (req.method === 'GET') {
res.end(JSON.stringify({ path, text }));
} else if (req.method === 'DELETE') {
path = null;
text = null;
res.end('DELETE success');
}
}).on('error', (err) => {
console.log(`Server error: ${err}`);
})
.listen(port, '0.0.0.0');
}
module.exports = (createServer);
The server accepts POST/PUT/DELETE/GET requests, to handle the pushAdd()/push()/delete() functions of the gateway to handle the metric data, as well as checking the push data on the mocked pushgateway.
Also, the request.url and the text data pushed to the server are saved and passed to the test program for verification.
The following is one of the test cases (using Mocha+Chai):
describe('Check adding custom push count metric', () => {
it('Check connection: should return - network status: 200, result contains custom count metric string', async () => {
metricInstance = promMetric.createCustomPushMetric({
name: 'test_counter',
help: 'Used to test the pushgateway for custom counter metrics',
type: 'counter',
jobName: 'custom-metric-pushgateway-counter',
groupings: { key: 'test', type: 'customMetric' },
});
await promMetric.addPushMetric(metricInstance, 0.879);
await sleep(500);
const result = await chai.request(mockPgwServer).get('/');
expect(result).to.have.status(200);
const json = JSON.parse(result.text);
expect(json.path).to.equal('/metrics/job/custom-metric-pushgateway-counter/key/test/type/customMetric');
expect(json.text).to.match(/# HELP Push_gateway_test_test_counter Used to test the pushgateway for custom counter metrics/);
expect(json.text).to.match(/# TYPE Push_gateway_test_test_counter counter/);
expect(json.text).to.match(/Push_gateway_test_test_counter 0.879/);
});
});
The "path" and "text" stored in the server when the metric is posted from the client are sent back to the client when queried and verified.

Error : Cannot set headers after they are sent to the client

When I hit the signup route "req.body" doesn't pick any up any of the POST values, however whenever the same code is tested on Postman - with body raw method - the values display.
const router = require('express').Router();
const bodyParser = require('body-parser');
const Promise = require('bluebird');
router.use(bodyParser.json());
router.use(bodyParser.urlencoded({
extended: true
}));
const registration = require('./services/registration');
router.get('/', (req, res, next) => {
res.send('Admin Welcome');
});
router.get('/signup', (req, res, next) => {
res.render('user/signup');
});
router.post('/signup', (req, res, next) => {
res.send(req.body);
registration.registration(req.body);
.then(ok=>{
res.redirect('signin')
})
.catch(err => {
res.render('error', {message: err})
})
})
router.get('/signin', (req, res, next) => {
res.render('user/signin');
});
original code
router.post("/signup", (req, res, next) => {
res.send(req.body);
registration
.registration(req.body)
.then(ok => {
res.redirect("signin");
})
.catch(err => {
res.render("error", { message: err });
});
});
The res object represents the HTTP response that an Express app sends when it gets an HTTP request. In the following link you can see all the methods that are exposed for res object:
https://expressjs.com/en/api.html#res
Method that you are using at the beginning of you route handler is:
res.send([body])
And as it can be read from the documentation it sends the HTTP response. Now you can send that response only once, otherwise you will get an error:
Error : Cannot set headers after they are sent to the client
And what you are trying to do in the handler is to redirect result to "signin" page afterwards already sending the response with res.send(req.body).
Take this fake route for an example:
router.post("/example", (req, res, next) => {
res.send('1');
res.send('2');
res.send('3');
});
Contrary to what you might believe, it wont return values (1,2,3), but actually return value 1 and raise and error that was previously described.
Finally to solve your issue you need to remove line containing res.send(req.body) and double check if registration.registration service is correctly handling provided data, in this case req.body.

POST an item to JSON server db- Angular

I'm trying to POST an Item to my db in my json server. I'm sending the POST request from Angular. When I do so, I get the following error:
Note: when I do the get in a the GET end point it works fine. I'm very new on the server side
POST ERROR 404:
Http failure response for http://localhost:3000/addMember: 404 Not Found
SERVER.JS
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const request = require('request');
const app = express();
....
app.use(cors());
app.use(express.static('assets'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.disable('x-powered-by');
app.use(xssFilter());
app.use(nosniff());
app.set('etag', false);
app.use(
helmet({
noCache: true
})
);
app.use(
hsts({
maxAge: 15552000 // 180 days in seconds
})
);
app.use(
express.static(path.join(__dirname, 'dist/softrams-racing'), {
etag: false
})
);
app.get('/api/members', (req, res) => {
request('http://localhost:3000/members', (err, response, body) => {
if (response.statusCode <= 500) {
res.send(body);
}
});
});
// TODO: Dropdown!
app.get('/api/teams', (req, res) => {
request('http://localhost:3000/teams', (err, response, body) => {
if (response.statusCode <= 500) {
res.send(body);
}
});
});
// Submit Form!
app.post('/api/members', function(request, response) {
request.post('http://localhost:3000/members', (err, response, body) => {
if (response.statusCode <= 500) {
req.send(body);
}
});
});
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist/softrams-racing/index.html'));
});
app.listen('8000', () => {
console.log('Vrrrum Vrrrum! Server starting!');
});
ANGULAR
addMember(memberForm: Member) {
this.http.post(`${this.api}/addMember`, memberForm).subscribe(
data => {
console.log('POST Request is successful ', data);
},
error => {
console.log('Error', error);
}
);
}
UPDATE:
in my console i see this POST /addMember 404 12.105 ms - 2 and If i go to http://localhost:3000/addMember directly in the browser I see an empty object {} and if I go here http://localhost:3000/ I see this message To access and modify resources, you can use any HTTP method GET POST PUT PATCH DELETE OPTIONS
The issue here is that you are making your POST request to a route which your JSON server does not handle. Change the URL to http://localhost:3000/members, and it should work fine!
(The routes on a json-server correspond to the elements in your db.json file.)
Try to change your code like this:
addMember(memberForm: Member) {
this.http.post(`${this.api}/api/addMember`, memberForm).subscribe(
data => {
console.log('POST Request is successful ', data);
},
error => {
console.log('Error', error);
}
);
}
From the error it is shown that your service is expecting the request at http://localhost:3000/api/addMember but your console.log shows that you are sending post request at http://locatlhost:3000/addMember

Node: Is it possible that http server on request return the content from a request module?

What I want to do is to make a request using the "request" module when server receives a request, and return the content of that "request" back to the client. Is it possible?
const http = require("http");
const request = require("request");
const URL = "???";
const server = http.createServer();
server.on('request', (req, res) => {
// called once for every HTTP request
out_res = res;
make_request((err, res, body) => {
out_res.writeHead(200, {res});
out_res.write(body);
out_res.end();
});
});
function make_request(callback) {
request(URL, (err, res, body) => {
callback(err, res, body);
});
}
module.exports = () => {
server.listen(8080);
console.log('server start');
};
I got an error: ERR_STREAM_WRITE_AFTER_END, I've been a long time without node.js, but my friend asked me about some code and I just rewrite as above.
Ofcourse you can do that
server.on('request', (req, res) => {
request({uri: URL}).pipe(res);
});
Just pipe the response of API call to your router response object.
Here is how I would advise you to write your server code
var server = http.createServer(function(req,res){
if(req.url === '/' || req.url === '/index'){
request({uri: URL}).pipe(res);
}
.... //other conditions
});
server.listen(3000,'127.0.0.1')
Moreover, you can/should consider using express, it's really cool and easy to use to define routes etc

Resources