Change URL after POST using ExpressJS - node.js

I use expressJS as my NodeJS server. The user sends me his login info through a POST and after checking the credentials I render a page:
router.post("/login", function (req: Request, res: Response, next) {
if(credentialsOK){
res.render('main');
}
});
The problem is that the URL becomes http://myaddress/login and I would like to remove the /login of the address. I don't want to use redirect as I want to send local variables through the render.
How can I change the URL?

You can still pass your local variables through res.redirect.
router.post("/login", function (req: Request, res: Response, next) {
if(credentialsOK){
req.session.localVar = yourLocalVar;
res.redirect('/main');
}
})
Then in main router:
router.get("/main", function (req: Request, res: Response, next) {
var yourLocalVar = req.session.localVar;
res.render('main');
})

You cannot change the URL from the server side, but you can change the URL
by using the javascript method window.history.pushState("", "", '/');
<script>
window.history.pushState("", "", '/');
</script>

Related

Express route not found on redirect but route exists

So in my express server I have redirection to a route /chat like this
if (!user) {
res.json(info);
} else {
req.logIn(user, function() {
res.redirect('/chat');
})
}
I' m registring my route like this
app.use('/chat', require('./routes/chat'));
and in my routes/chat file
import * as express from 'express';
const router = express.Router();
// Chat Page
router.get('/chat', (req: express.Request, res: express.Response) => res.render('chat'));
module.exports = router;
What I want to do is for it to redirect to the route which display React component but it returns GET http://localhost:3000/chat 404 (Not Found) Error: Request failed with status code 404
If I just paste the path http://localhost:3000/chat and go the page my component shows up.
So I'm not really sure what to do in this situation and how to fix it?
try
router.get('/', (req: express.Request, res: express.Response) => res.render('chat'));
You have already define /chat path.
By app.use() you can define an application-level middleware to an instance of the app object.
So, you define a middleware on /chat route in chat.js
app.use('/chat', require('./routes/chat'));
Now in chat.js you can do this:
router.get('/', (req: express.Request, res: express.Response) => res.render('chat'));
it resolved as /chat.
even if you want to define another route as /chat/room you can do this in chat.js
router.get('/room', (req: express.Request, res: express.Response) => res.render('chat'));

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);
})
}

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

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();
});

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

Connect/Express per request middleware is failing somewhere

I'm trying to do a very simple Basic Auth middleware for Express on Node.js as demonstrated here: http://node-js.ru/3-writing-express-middleware
I have my middleware function:
var basicAuth = function(request, response, next) {
if (request.headers.authorization && request.headers.authorization.search('Basic ') === 0) {
// Get the username and password
var requestHeader = new Buffer(
request.headers.authorization.split(' ')[1], 'base64').toString();
requestHeader = requestHeader.split(":");
var username = requestHeader[0];
var password = requestHeader[1];
// This is an async that queries the database for the correct credentials
authenticateUser(username, password, function(authenticated) {
if (authenticated) {
next();
} else {
response.send('Authentication required', 401);
}
});
} else {
response.send('Authentication required', 401);
}
};
And I have my route:
app.get('/user/', basicAuth, function(request, response) {
response.writeHead(200);
response.end('Okay');
});
If I try to curl this request I get:
curl -X GET http://localhost/user/ --user user:password
Cannot GET /user/
This works totally cool when I add the middleware while calling createServer(), but when I do it per-request like I am in this route, it just dies quietly server-side. Unfortunately, since not all requests require authentication, I can't make this a global middleware.
I've tried flipping off Express and just using Connect and I get the same result, so I assume it's something in there. Has anybody experienced this before?
Edit: I should also mention that I've logged the relevant code exhaustively and next is being called, but it just appears to go nowhere.
Edit 2: For the record, an "empty" middleware also fails silently:
var func = function(request, response, next) {
next();
};
app.get('/user', func, function(request, response) {
response.writeHead(200);
response.end('Okay');
});
This also has the same result.
function(request, response, callback) {
vs
next();
Your supposed to either change callback to next or vica versa.
I found this link.
Express middleware: Basic HTTP Authentication
The author seems to be doing the same thing as you did, except he has a return after the next().

Resources