NODEJS sending raw request issue - node.js

I have an app and I would like to use it as a proxy. Code looks like this
I am using request npm.
app.all('*', function(req, res){
console.log(req.url); //lower case
console.log(req.url.substr(0, 5));
var alteredRequest;
if (req.url.substr(0,5) == '/pro/') {
var requestedURL = req.url.substr(5);
console.log(requestedURL);
if( (requestedURL.substr(0, 7) != 'http://') || (requestedURL.substr(0, 8) != 'https://') ){
alteredRequest = "http://" + requestedURL;
}
request(alteredRequest, function(error, response, body){
console.log('error: ', error); // Print the error if one occurred
console.log('statusCode: ', response && response.statusCode); // Print the response status code if a response was received
res.send(response);
})
}
})
When I call res.send(response) at the end I get the response as a body, and all the headers exc are taken to the html body logged to the screen. Rather than that, I would like to send it as a real response with all the headers and cookies. How do I achieve it? thank you for helping.
To do more demonstration, the response (from google.com) starts like this, but it's on the screen! not the real headers and statusCode:
{"statusCode":200,"body":"<!doctype html><html itemscope=\"\" itemtype=\"http://schema.org/WebPage\" lang=\"tr\"><head><meta content=\"text/html; charset=UTF-8\" http-equiv=\"Content-Type\"><meta content=\"/images/branding/googleg/1x/googleg_standard_color_128dp.png\" itemprop=\"image\"><title>Google</title><script nonce=\"fzz0lJtfXqp5SuC6mvodsw==\">(function(){window.google=

it's a really bad way to do redirects. You should be using
res.redirect and req.protocol to do that
if (req.url.substr(0,5) == '/pro/') is perhaps the most hideous way of catching a route I've ever seen. This is what app.get('/', ...) is designed for.
But to answer your question, here's a working example
const express = require("express");
const request = require("request");
const app = express();
app.all('*', (req, res) => {
const newUrl = 'http://www.google.com'; //replace with your url altering code
return request(newUrl)
.on('response', function(response) {
console.log(response.statusCode) // 200
console.log(response.headers['content-type'])
})
.on('error', function(err) {
console.log(err)
})
.pipe(res);
});
app.listen(9000);

Related

Express.JS Get Status Code from POST Request

I am needing to find a way to get a response as a result of a https post request. So far from what I hae found that is only provided in the call back function, which does not include the result after data is written to the request and is ended as shown below:
**Note: the code below would be wrapped inside a "app.post" method.
const https = require("https");
var url = "https://someurl.com";
var options = {option1: "some option"}
var jsonData = {data1: "some data"};
const request = https.request(url, options, function (repsonse) {
// HERE THE STATUS CODE ONLY CAPTURES IF THE RESOURCE WAS AVAILABLE
// NOT IF THE REQUEST WAS SUCCESSFUL
console.log(response.statusCode);
});
request.write(jsonData);
request.end();
After the "request.end()" code i need to be able to get the status code returned from the request to determine if the actual request was successful. I would want to do something like this:
if (response.statusCode !== 200) {
res.sendFile(__dirname + "/failure.html");
}
else {
res.sendFile(__dirname + "/success.html");
}
The if statement should run after request.end() to determine if the actual request was successful. This is standard for using API frameworks such as Flask-Python, but I can't seem to find a way to catch this in express.js. Any help would be appreciated.
https.request works asynchronously. Whether the request is successful or not cannot be determined synchronously after the request.end(), but only in the callback function (where you can evaluate response.statusCode) or in the error event (if the request could not be made at all, for example because the server was unreachable).
const request = https.request(url, options, function (response) {
console.log(response.statusCode);
if (response.statusCode !== 200)
res.sendFile(__dirname + "/failure.html");
else
res.sendFile(__dirname + "/success.html");
});
request.on("error", function(err) {
console.error(err);
res.sendFile(__dirname + "/failure.html");
});
request.write(jsonData);
request.end();

Node and Twilio integration

I have written a programmable SMS feature using Twilio in nodejs. I have a message that has options to select and when user sends back any response I want to send an automated response using twilio.
I have completed all except after processing the response from user my automated response is not being delivered to user.
I keep getting above thing from my twilio dashboard.
Here is my response handler code..
app.post('/ui/sms',function(req, res) {
//req.headers['Content-type'] = 'text/xml';
//req.headers['Accept'] = 'text/xml';
try {
console.log('Processing Response', req.headers);
const MessagingResponse = require('twilio').twiml.MessagingResponse;
const twiml = new MessagingResponse();
const fromTwilio = isFromTwilio(req);
console.log('isFromTwilio: ', fromTwilio);
if (fromTwilio) {
let msg = req.body.Body||'';
if (msg.indexOf('1')>-1) {
twiml.message('Thanks for confirming your appointment.');
} else if (msg.indexOf('2')>-1) {
twiml.message('Please call 408-xxx-xxxx to reschedule.');
} else if (msg.indexOf('3')>-1) {
twiml.message('We will call you to follow up.');
} else {
twiml.message(
'Unknown option, please call 408-xxx-xxxx to talk with us.'
);
}
res.writeHead(200, { 'Content-Type': 'text/xml' });
res.end(twiml.toString());
}
else {
// we don't expect these
res.status(500).json({ error: 'Cannot process your request.' });
}
/*processSMSResponse(req, function(response) {
res.json(response);
});*/
} catch(e) {
res.json(e);
}
});
function isFromTwilio(req) {
console.log('REQ HEADER:::::::::\n', req);
// Get twilio-node from twilio.com/docs/libraries/node
const client = require('twilio');
// Your Auth Token from twilio.com/console
const authToken = 'xxxxxxxxxxxxxxxxx';
// The Twilio request URL
//const url = 'https://mycompany.com/myapp.php?foo=1&bar=2';
const url = 'https://xxxx.com/ui/sms';
var reqUrl = 'https://xxxx.com/ui/sms'
// The post variables in Twilio's request
//const params = {
//CallSid: 'CA1234567890ABCDE',
//Caller: '+14158675310',
//Digits: '1234',
//From: '+14158675310',
//To: '+18005551212',
//};
const params = req.body;
console.log('post params: ', params);
// The X-Twilio-Signature header attached to the request
try{
Object.keys(params).sort().forEach(function(key) {
reqUrl = reqUrl + key + params[key];
});
var twilioSignature = crypto.createHmac('sha1', authToken).update(Buffer.from(reqUrl, 'utf-8')).digest('base64');
//const twilioSignature = req.header('HTTP_X_TWILIO_SIGNATURE');
console.log('twilioSignature: ', twilioSignature);
} catch(e){
console.log(e);
}
return client.validateRequest(
authToken,
twilioSignature,
url,
params
);
}
I have explicitly tried setting headers but no use. I'm clue less on what twilio expects from me or how to modify headers.
{
"status": "Error",
"error": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><Response><Message>Please call 408-xxx-xxxx to reschedule.</Message></Response>"
}
I see this as body in Twilio console and it has the response that I need but could not send as a message..
Twilio Developer Evangelist here.
From looking at your code and trying it myself I can't see anything generally wrong with it. There are two potential failing points here though:
1) I can't see your isFromTwilio function. If that one fails it might cause an error and then return JSON instead of XML on your error handler. I don't know why it would reply with the TwiML in that JSON though.
2) The other behavior I could reproduce (except that the TwiML is not being sent in the response body) is when I don't include body-parser in the middleware chain. This will cause req.body to be undefined and therefore req.body.Body will throw an error that is then being caught and JSON is being returned.
Do you have body-parser included and properly included as a middleware? You can either do it this way:
const { urlencoded } = require('body-parser');
app.use(urlencoded({ extended: false });
or if you only want to use it for this one endpoint you can add urlencoded({ extended: false }) as an argument before your request handler:
app.post('/ui/sms', urlencoded({ extended: false }), function(req, res) {
I hope this helps.
Cheers,
Dominik

How to make GET request inside a GET request in NodeJS using Express

Basically, I'm trying to get Access Token from Facebook in my callBack GET method. Below is my code.
getAccessToken is not called at all. What's the right way to implement it?
app.get('/fbcallback', function(req, res) {
var code = req.query.code;
var getAccessToken = 'https://graph.facebook.com/v2.12/oauth/access_token?'+
'client_id='+client_id+
'&redirect_uri='+redirect_uri+
'&client_secret='+client_secret+
'&code='+code;
app.use(getAccessToken, function(req, res) {
console.log('Token Call');
});
});
You should not use app.use inside get the call.
You must be trying to do something like below. Inside get call make another get call for getting token.
var request = require('request');
app.get('/fbcallback', function (req, res) {
var code = req.query.code;
var getAccessToken = 'https://graph.facebook.com/v2.12/oauth/access_token?' +
'client_id=' + client_id +
'&redirect_uri=' + redirect_uri +
'&client_secret=' + client_secret +
'&code=' + code;
request(getAccessToken, function (error, response, body) {
console.log('error:', error); // Print the error if one occurred
console.log('statusCode:', response && response.statusCode); // Print the response status code if a response was received
console.log('body:', body); // Print the HTML for the Google homepage.
});
});

Changing the header of the response on NodeJS using request

I have the following problem:
I want to get a static file from another server, and give it back to the user with another content-type header.
The following code works just fine, but I can't figure out a way to change the response header, though.
const request = require('request');
app.get('video', function (req, res) {
request.get('http://anotherurl.com/video-sample.mp4').pipe(res);
});
I tried to do this thing more manually, but the response was very slow.
app.get('video', function (req, res) {
request.get('http://anotherurl.com/video-sample.mp4', function(error, response, body) {
// ...
res.setHeader('content-type', 'image/png');
res.send(new Buffer(body));
});
});
Can you guys help me with that?
Thanks
Just set the response header when the 'response' event fires.
app.get('video', (req, res) => {
request.get('http://anotherurl.com/video-sample.mp4')
.on('response', response => {
res.setHeader('Content-Type', 'image/png');
// pipe response to res
// since response is an http.IncomingMessage
response.pipe(res);
});
});

Edit response headers before piping

I have a small proxy for certain requests in Express. Using the request library, I have fairly concise code:
app.use('/api', function(req, res) {
var url = rewriteUrl(req.url);
var newReq = request(url, function(error) {
if (error) {
logError(error);
}
});
req.pipe(newReq).pipe(res);
});
My problem is that the response from the API server contains a bunch of unwanted headers that I want to remove. How can I remove the headers from the response of newReq before piping it to res?
mscdex's answer did work for me, but I found a way that I think is slightly cleaner. In my original code, I had this line:
req.pipe(newReq).pipe(res);
I replaced that with these lines:
req.pipe(newReq).on('response', function(res) {
delete res.headers['user-agent'];
// ...
}).pipe(res);
With the request module, there currently isn't a way (AFAIK) to have a callback and not buffer the server response. So here is how you might do it with the built-in http.request:
app.use('/api', function(req, res) {
var url = rewriteUrl(req.url);
var newReq = http.request(url, function(newRes) {
var headers = newRes.headers;
// modify `headers` here ...
res.writeHead(newRes.statusCode, headers);
newRes.pipe(res);
}).on('error', function(err) {
res.statusCode = 500;
res.end();
});
req.pipe(newReq);
});
It is easy with request.
request("https://example.com/image.png")
.on("response", remoteRes => {
// You can add/remove/modify headers here
remoteRes.headers["content-disposition"] = "attachment; filename=awesome.png";
})
.pipe(res);
There is more elegant way to modify/remove headers by setting a pipe filter as follows:
const req = request.get(url);
req.pipefilter = function(response, dest) {
// remove headers
for(const h in response.headers) {
dest.removeHeader(h);
}
// or modify
dest.setHeader('Content-Type', 'text/html')
}
req.pipe(resp)

Resources