How to res.send to a new URL in Node.js/Express? - node.js

Given a GET request to URL X, how should you define res.send such that it provides a response to a completely separate URL Y?
i.e.
app.get('/', function (req, res) {
res.send to a new URL external of the app ('Success')
});
Thanks and apologies in advance for ignorance on the topic!

You want to redirect the request by setting the status code and providing a location header. 302 indicates a temporary redirect, 301 is a permanent redirect.
app.get('/', function (req, res) {
res.statusCode = 302;
res.setHeader("Location", "http://www.url.com/page");
res.end();
});

You can only send response to the request source, which is the client. There is no such thing as sending response to another "external-url" (or another server).
However, you CAN make a request to another server, wait for it's response, and respond to our client.
app.get('/', (req, res) => {
var requestOptions = {
hostname: 'serverB.com', // url or ip address
port: 8080, // default to 80 if not provided
path: '/take-request',
method: 'POST' // HTTP Method
};
var externalRequest = http.request(requestOptions, (externalResponse) => {
// ServerB done responding
externalResponse.on('end', () => {
// Response to client
res.end('data was send to serverB');
});
});
// Free to send anthing to serverB
externalRequest.write(req.data);
externalRequest.end();
});

Related

How to redirect a get request to another post request in express js?

I want to redirect a get request to another server post. i don't know how to do that. the following is my code.
server 1: get method
app.get('/sampleTestApp', function (req, res) {
body={uid:'test'}
// Want to redirect here to server 2 'login/callback' url with body object
}
server 2: post method
app.post('/login/callback', function (req, res) {
// success process..
}
You can do something like
app.get('/sampleTestApp', function (req, res) {
axios.post(url:'server2/post', data :body={uid:'test'},function(response) {
res.send(response);
})
}

Pass value from http.request or superagent to http.createServer NodeJs

I am not sure what the issue is but I think I have to make this async or promise based (idk how). I simply want to pass the callback to http server on res.end.
Can some one help please?
HTTP Request or SuperAgent passes the value to the function below. How to send this to http.createserver ?
function receiveCallback(link) {
console.log(link);
//this works fine, echos the LINK we want to 302 to
}
How to pass link to http server?
http.createServer(function (req, res) {
res.writeHead(302, {'Location': link});
res.end();
}).listen('8080');
Ex. User opens domain.com/test?somevar
somevar is sent to superagent which then produces a link
How to 302 the user to the link
If your superagent is making its own request every time the server gets a request, it would look something like this:
const http = require('http');
const url = require('url');
const request = require('superagent');
http.createServer((req, res) => {
const queryParams = url.parse(req.url, true).query;
request
.get('/get/my/link')
.send({ somevar: queryParams.somevar })
.end((err, response) => {
if (err)
throw err;
const link = response.body.link;
res.writeHead(302, { 'Location': link });
res.end();
});
}).listen('8080');

Node.js with Express: how to redirect a POST request

I want to redirect from one URL request to another 'POST' request, like this:
var app = require('express')();
app.get('/', function(req, res) {
res.redirect('/test');
});
app.post('/test', function(req, res) {
res.send('/test page');
});
app.listen(3000, function() {
console.log('listenning on port:3000');
});
However, I can't redirect to '/test' page because it is a POST request. So what should I do to make the redirection work, keeping the '/test' request POST?
You can do this:
app.post('/', function(req, res) {
res.redirect(307, '/test');
});
Which will preserve the send method.
For reference, the 307 http code spec is:
307 Temporary Redirect (since HTTP/1.1) In this occasion, the request
should be repeated with another URI, but future requests can still use
the original URI.2 In contrast to 303, the request method should not
be changed when reissuing the original request. For instance, a POST
request must be repeated using another POST request.
For more info, see: http://www.alanflavell.org.uk/www/post-redirect.html
Keep in mind the middleware architecture: Each handler may manipulate the context, and either respond - or - call next().
By this premise, the express router is basically a middleware function you may use after "correcting" the url.
(BTW, the request app is also a function, although I'm not sure if I recommend going back so early in the chain)
Here's a kind'a example:
const router = new require('express').Router()
const user = require('../model/user')
//assume user implements:
// user.byId(id) -> Promise<user>
// user.byMail(email) -> Promise<user>
const reqUser = userPromise => (req, res, next) =>
req.user
? next()
: userPromise(req)
.then(user => { req.user = user })
.then(next, next)
//assume the sever that uses this router has a
//standard (err, req, res, next) handler in the end of the chain...
const byId = reqUser( req => user.byId(req.params.id) )
const byMail = reqUser( req => user.byMail(req.params.mail) )
router.post('/by-id/:id/friends',
byId,
(req, res) => res.render('user-friends', req.user)
)
router.post('/by-email/:email/friends',
byMail,
(req, res, next) => {
req.url = `/by-id/${req.user.id}/friends`
next()
},
router
)
The only difference between 307 and 302 is that 307 guarantees that the method and the body will not be changed when the redirected request is made.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/307
I believe the question is that the node server is receiving a POST request but needs to redirect it to a different server as GET request. I recently had to deal with something similar. Here is how I solved it:
var proxy = require('express-http-proxy');
app.use('incomin/url', proxy('forwarding:server', {
//The proxyRqDecorator allows us to change a few things including the request type.
proxyReqOptDecorator: (proxyReqOpts, srcReq) => {
proxyReqOpts.method = 'GET';
return proxyReqOpts;
},
//The proxyReqPathResolver takes the Given URL and updates it to the forward path
proxyReqPathResolver: function (req) {
return new Promise( (resolve, reject) => {
setTimeout( () =>{
var value = req.body.key;
var resolvedPathValue = 'forwarding/url' + value;
console.log(`Inside forward path. The resolved path is ${resolvedPathValue}`);
resolve(resolvedPathValue);
}, 200);
});
}
}));
Keep in mind that the above proxyReqPathResolver is setup async. The synchronous vesrion and more info on express-http-proxy are described here:
https://www.npmjs.com/package/express-http-proxy

Check if request is in state of re-direct

There is a way with express check if the request is in status redirect (302) ,I use the( req,res ) I use the following ?
var http = require('http'),
httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer({});
proxy.on('proxyReq', function(proxyReq, req, res, options) {
proxyReq.setHeader('X-Special-Proxy-Header', 'foobar');
});
proxy.on('proxyRes', function (proxyRes, req, res) {
console.log('RAW Response from the target', JSON.stringify(proxyRes.headers, true, 2));
});
https://github.com/nodejitsu/node-http-proxy
Maybe I don't understand the question, but you can easily do the following:
proxy.on('proxyRes', function(proxyRes, req, res) {
if (proxyRes.statusCode === 301 || proxyRes.statusCode === 302) {
proxyRes.headers['location'] = fixUrl(proxyRes.headers['location']);
}
});
Where fixUrl() does any necessary transform on the location response header.
You can listen for proxyRes event and check its status code (status code for redirection is 30x). ProxyRes is a raw response from your target, so you should be able to catch and modify the response headers before the proxy send this response to the client.
Alternatively, you can also set the proxy options that handle 30x redirects. Either setting the autoRewrite to true or explicitly state the location in the hostRewrite and protocolRewrite should do the trick. https://github.com/nodejitsu/node-http-proxy#options

NodeJS - Reverse Proxy with Route Changing

I'm currently using NodeJS/Express as a simple domain router running on my VPS on port 80. My routes.coffee looks something like this:
request = require("request")
module.exports = (app) ->
#404, 503, error
app.get "/404", (req, res, next) ->
res.send "404. Sowway. :("
app.get "/error", (req, res, next) ->
res.send "STOP SENDING ERRORS! It ain't cool, yo."
#Domain Redirects
app.all '/*', (req, res, next) ->
hostname = req.headers.host.split(":")[0]
#Website1.com
if hostname == 'website1.com'
res.status 301
res.redirect 'http://facebook.com/website1'
#Example2.com
else if hostname == 'example2.com'
pathToGo = (req.url).replace('www.','').replace('http://example2.com','')
request('http://localhost:8020'+pathToGo).pipe(res)
#Other
else
res.redirect '/404'
As you can see in Example2.com, I'm attempting to reverse proxy to another node instance on a different port. Overall it works perfectly, except for one issue. If the route on the other node instance changes (Redirects from example2.com/page1.html to example2.com/post5), the URL in the address bar doesn't change. Would anyone happen to have a nice workaround for this? Or maybe a better way to reverse proxy? Thanks!
In order to redirect the client, you should set the http-status-code to 3xx and send a location header.
I'm not familiar with request module but I believe it follows redirects by default.
On the other hand, you're piping the proxy-request's response to client's response object, discarding the headers and the status code. That's why the clients don't get redirected.
Here is a simple reverse HTTP proxy using the built-in HTTP client. It's written in javascript but you can easily translate it to coffeescript and use request module if you want.
var http = require('http');
var url = require('url');
var server = http.createServer(function (req, res) {
parsedUrl = url.parse(req.url);
var headersCopy = {};
// create a copy of request headers
for (attr in req.headers) {
if (!req.headers.hasOwnProperty(attr)) continue;
headersCopy[attr] = req.headers[attr];
}
// set request host header
if (headersCopy.host) headersCopy.host = 'localhost:8020';
var options = {
host: 'localhost:8020',
method: req.method,
path: parsedUrl.path,
headers: headersCopy
};
var clientRequest = http.request(options);
clientRequest.on('response', function (clientResponse) {
res.statusCode = clientResponse.statusCode;
for (header in clientResponse.headers) {
if (!clientResponse.headers.hasOwnProperty(header)) continue;
res.setHeader(header, clientResponse.headers[header]);
}
clientResponse.pipe(res);
});
req.pipe(clientRequest);
});
server.listen(80);
// drop root privileges
server.on('listening', function () {
process.setgid && process.setgid('nobody');
process.setuid && process.setuid('nobody');
});

Resources