Browsersync middleware: Redirect from a post request - node.js

We are using browsersync in development. For a payment confirmation, the payment provider posts back to a predefined url.
The problem is, that Browsersync only displays Cannot POST /payment/success.
So I was thinking about writing a middleware that takes the POST request and redirects to the same URL as a GET request. The problem is, I'm not sure if this is possible with browser sync. When I try to call res.redirect('/') it throws an error:
browserSync.init
server:
baseDir: "...."
index: "/statics/master.html"
middleware: [
modRewrite(['!\\.\\w+$ /statics/master.html [L]']),
(req, res, next) ->
res.redirect('/') # this throws a TypeError: res.redirect is not a function
]
Why is res.redirect not defined? I thought browser sync is based on express?
How could I access the body of the post request? req.body returns undefined

browserSync uses Connect for the middleware and doesn't share the same api as Express it seems.
For a redirect you can at least do the following:
res.writeHead(301, {Location: url});
res.end();
Have a look at their documentation for accessing the request body. The section in Middleware regarding body parsing may yield some results for you.

Related

NodeJs - res.redirect changes the content displayed but not the URL

i have a react native frontend and a nodejs backend. In one of my API calls i am getting a redirectHTML from a gateway to display to the users. The redirectHTML obtained is used in react native Webview to get displayed. my problem is the only way to know that the transaction is success or not is from the url. I have tried res.redirect and res.writeHead and both change the content of the screen but the URL still remains the same.
Server side
router.get(
"/pay/authenticate/result",
async(req, res) => {
console.log(req.query)
// res.redirect(302,"/");
res.writeHead(302,{'Location':'https://www.google.com/'});
res.end("");
});
client Side
<WebView
style={{flex:1}}
source={{html:`${authenticateWebViewUrl}`}} //this is the redirectHTML that came from the response
onNavigationStateChange={(navState) => {
console.log(navState)
}}
scalesPageToFit={false}
javaScriptEnabled={true}
/>
res.redirect with 302 will add the temporary redirection, if you want a permanent redirection, prefer HTTP 301. Reference
res.writeHead + res.end does not, on its own, cause the redirection to a new URL.
Edit: Typo req and res.

Redirecting a Node.js/Express request to another server

I got a situation where I need to redirect an HTTP request made to server X to another server Y,
with all of the requests' headers, params, body etc.
I tried:
app.post('/redirect-source', (req, res, next) => {
res.redirect(301, 'http://localhost:4000/redirect-target');
});
But the response I get when reaching this route is:
{"message":"Not Found"}
Although the server and route i'm redirecting to are live and I get an ok response when reaching it directly.
What am I missing?
edit:
I noticed that the target route works on Postman and not from the browser, my guess is because it's a POST request.
How can I configure the redirect to pass as POST/specific type?
Try to change the statusCode to 308.
Take a look at this https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/301
Use the 301 code only as a response for GET or HEAD methods and use the 308 Permanent Redirect for POST methods instead, as the method change is explicitly prohibited with this status.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/308
It turned out that status code 307 is the one that works for POST requests too. Like so:
app.post('/redirect-source', (req, res, next) => {
res.redirect(307, 'http://localhost:4000/redirect-target');
});

Access URL query Params in an Express POST route

I have a NodeJS/Express application.
From an url endpoint titled: localhost:3000/form?someProp=someValue&somethingElse=someOtherValue
This page submits a form to another Express endpoint.
I submit to an Express POST endpoint. I know in a GET endpoint I could access the query params via req.query, but I cannot seem to do that in a POST request.
Is there a way to access the query params from the request in a POST route?
(other than splicing the header.referrer... which I may just have to do)
Here are some code snippets:
If I submit to the first route it works, if I submit to the second... it does not.
router.get('/test',
(req, res) => {
console.log(req.query); // {someProp: someValue, somethingElse: someOtherValue }
}
);
router.post('/test2',
(req, res) => {
console.log(req.query); // returns {}
}
);
So I tried to send a simple request to test it and got everything working without doing anything special (The only thing extra I have is that I'm using body-parser middleware from npm):
app.use(bodyParser.json({limit: '50mb'}));
Then I tried this simple route and got the result query params as you can see in the picture attached.
http://localhost:8080/test?test=1&what=2
Any chance you're sending the other form request from the client in a different way? try looking at the network in chrome and see if you sending what you expecting. Obviously, there is something missing here as it worked for me without doing anything special.

How to get req.body from Facebook's data deletion URL call?

I've implemented the "sign in with Facebook" authorization method for my Express.js Node app. Since the app is hosted in the EU, Facebook requires it to have a data deletion request callback URL.
I've created an endpoint for the data deletion request, but whenever I make Facebook call that endpoint both req.body and req.query are empty - if I've understood correctly the body should contain a signed_request that could be used to e.g. verify the caller.
My CORS settings should be fine and I've tested my endpoint by calling it from Postman. The endpoint is able to receive a POST request with a JSON body without any problem.
So, what am I doing wrong - why does it seem like Facebook is calling my endpoint with a POST request that has an empty body?
My endpoint:
import express from 'express'; // 4.17.1
const router = express.Router();
router.post('/fb_data_deletion', (req, res, next) => {
console.log(req.body); // {}
console.log(req.query); // {}
if (!req.body || !req.body.signed_request) {
console.log('Bad request'); // Ends up here whenever Facebook calls this route
return req.sendStatus(400);
}
// verify request, delete user's data + other code here
});
Turns out Facebook isn't sending a POST request that uses Content-Type application/json but application/x-www-form-urlencoded.
To get the body of Facebook's POST request I had to add the following line to my app.js where the Node server is being set up:
app.use(express.urlencoded());

ExpressJS : res.redirect() not working as expected?

I've been struggling for 2 days on this one, googled and stackoverflowed all I could, but I can't work it out.
I'm building a simple node app (+Express + Mongoose) with a login page that redirects to the home page. Here's my server JS code :
app
.get('/', (req, res) => {
console.log("Here we are : root");
return res.sendfile(__dirname + '/index.html');
})
.get('/login', (req, res) => {
console.log("Here we are : '/login'");
return res.sendfile(__dirname + '/login.html');
})
.post('/credentials', (req, res) => {
console.log("Here we are : '/credentials'");
// Some Mongoose / DB validations
return res.redirect('/');
});
The login page makes a POST request to /credentials, where posted data is verified. This works. I can see "Here we are : '/credentials'" in the Node console.
Then comes the issue : the res.redirect doesn't work properly. I know that it does reach the '/' route, because :
I can see "Here we are : root" in the Node console
The index.html page is being sent back to the browser as a reponse, but not displayed in the window.
Chrome inspector shows the POST request response, I CAN see the HTML code being sent to the browser in the inspector, but the URL remains /login and the login page is still being displayed on screen.
(Edit) The redirection is in Mongoose's callback function, it's not synchronous (as NodeJS should be). I have just removed Mongoose validation stuff for clarity.
I have tried adding res.end(), doesn't work
I have tried
req.method = 'get';
res.redirect('/');
and
res.writeHead(302, {location: '/'});
res.end();
Doesn't work
What am I doing wrong? How can I actually leave the '/login' page, redirect the browser to '/' and display the HTML code that it received?
Thanks a million for your help in advance :)
The problem might not lie with the backend, but with the frontend. If you are using AJAX to send the POST request, it is specifically designed to not change your url.
Use window.location.href after AJAX's request has completed (in the .done()) to update the URL with the desired path, or use JQuery: $('body').replaceWith(data) when you receive the HTML back from the request.
If you are using an asynchronous request to backend and then redirecting in backend, it will redirect in backend (i.e. it will create a new get request to that URL), but won't change the URL in front end.
To make it work you need to:
use window.location.href = "/url"
change your async request (in front end) to simple anchor tag (<a></a>)
It's almost certain that you are making an async call to check Mongoose but you haven't structured the code so that the redirect only happens after the async call returns a result.
In javascript, the POST would look like something this:
function validateCredentials(user, callback){
// takes whatever you need to validate the visitor as `user`
// uses the `callback` when the results return from Mongoose
}
app.post('/credentials', function(req, res){
console.log("Here was are: '/credentials'";
validateCredentials(userdata, function(err, data){
if (err) {
// handle error and redirect to credentials,
// display an error page, or whatever you want to do here...
}
// if no error, redirect
res.redirect('/');
};
};
You can also see questions like Async call in node.js vs. mongoose for parallel/related problems...
I've been working on implementing nodemailer into my NextJS app with Express. Was having this issue and came across this. I had event.preventDefault() in my function that was firing the form to submit and that was preventing the redirect as well, I took it off and it was redirecting accordingly.
Add the following in your get / route :
res.setHeader("Content-Type", "text/html")
Your browser will render file instead of downloading it

Resources