This route redirect is doing exactly what I want in Chrome and Firefox, but for some reason, it is not working in Safari in the production environment:
var express = require('express');
var router = express.Router();
var pool = require('../modules/pg-pool');
router.get('/', async (req, res) => {
var client = await pool.connect();
try {
var stripeConnectState = req.query.state;
var stripeConnectVendorIdResult = await client.query('SELECT vendor_id ' +
'FROM users_vendors ' +
'WHERE stripe_connect_state=$1;',
[stripeConnectState])
client.release();
if (stripeConnectVendorIdResult.rows[0] && stripeConnectVendorIdResult.rows[0].vendor_id) {
var stripeConnectVendorId = stripeConnectVendorIdResult.rows[0].vendor_id;
}
if (stripeConnectVendorId) {
var redirectUrl = [req.protocol, '://', req.get('Host'), '/#/account/vendor/details/', stripeConnectVendorId, '?', req.originalUrl.split("?").pop()].join('');
res.redirect(redirectUrl);
} else {
console.log('There was no vendor id to match the stripe state received');
res.sendStatus(403);
}
} catch (e) {
console.log('Error vendor id GET SQL query task', e);
res.sendStatus(500);
}
});
module.exports = router;
The craziest part to me is that when I I tested locally in Safari, it worked! For some reason, when I deploy to Heroku, it no longer works in production for Safari.
When I test locally, it is redirecting to
http://localhost:5000/#/account/vendor/details/7?state=XXXXXXXXXXXXXXXXXXXXXXXX&scope=read_write&code=ac_XXXXXXXXXXXXXXXXXX
But in production, it is redirecting to the base url
https://www.fairlywed.com/
without the incredibly important query parameters sent along by Stripe. This almost seems like I have a race condition on my hands that never triggers in Chrome or Firefox, but always triggers in Safari.
I'm also wondering if my use of angular-ui-router or the fact that stripe is directing to my site might be involved, but none of those really make a whole lot of sense to me. I might just be grasping at straws at this point.
I found a band-aid fix, but I'm still not sure why this is happening. On production, the req.protocol
was coming in as http
which is handled by another part of my code:
function redirectChecker (req, res, next) {
if (env === 'production') {
if (req.headers['x-forwarded-proto'] !== 'https') {
var urlAfterConversion = ['https://', req.get('Host'), req.url].join('');
return res.redirect(urlAfterConversion);
}
}
return next();
};
For some reason on Safari, that redirect doesn't work (maybe Safari doesn't accept a redirect followed by a redirect?)
So it failed and redirected to my landing page. I'm still not sure why it solved the problem, but this code is working:
if (stripeConnectVendorId) {
var env = process.env.NODE_ENV || 'development';
var redirectUrl = [req.protocol, '://', req.get('Host'), '/#/account/vendor/details/', stripeConnectVendorId, '?', req.originalUrl.split("?").pop()].join('');
if (env === 'production') {
redirectUrl = 'https:' + redirectUrl.split(':')[1];
}
res.redirect(redirectUrl);
} else {
console.log('There was no vendor id to match the stripe state received');
res.sendStatus(403);
}