Express.js routing: how to prevent reloading of previous page? - javascript

I am new to express (or web development in general) and have a question about routing.
I am creating a web app on Firebase with pure JS, and am using routing on Firebase cloud functions. The routing part looks like below. The purpose is, when URL is in the form of /xxxxxx, it sends the profile html page, and when URL is for of r/xxxxx, it sends the posts html page. Then client-side rendering will be done to populate the additional data to make up a page. Below is the part of the code:
exports.webAPI = functions.https.onRequest(app);
app.get('/:id', (req, res) => {
res.set('Cache-Control', 'public, max-age=86400, s-maxage=86400');
res.status(200).sendFile(path.join(__dirname+'/app/profile.html'));
});
app.get('/r/:post', (req, res) => {
res.set('Cache-Control', 'public, max-age=86400, s-maxage=86400');
res.status(200).sendFile(path.join(__dirname+'/app/post.html'));
});
The issue is: whenever the user clicks on a post and then goes back to the profile page, the whole page is re-rendered. This is understandably very bad for user experience in the world of modern web app.
The question: how do I prevent reloading of previous page, unless there is a meaningful change to it(e.g. new post uploaded?)? Is there a way to do it in Express?
If there is a better version of code to do this, let me know . If I need to look at certain parts of the documentation, please advise. Or, if this is not possible with Express and I should look at something else, do guide me on where to look at.
Thanks!

Install axios package. In my scenario i am trying to register a form. So this all things i need to do for register without refreshing the page.
const register = async (name, email, password, passwordConfirm) => {
try {
const res = await axios({
method: "POST",
url: "your url",
data: {
name,
email,
password,
passwordConfirm
}
});
console.log(res);
if (res.data.status === "success") {
alert("You are registered succesfully");
window.setTimeout(() => {
location.assign("/");
}, 1500);
}
} catch (error) {
alert(error.response.data.message);
console.log(error);
}
};
document.querySelector("#registerform").addEventListener("submit", e => {
e.preventDefault();
const name = document.getElementById("name").value;
const email = document.getElementById("email").value;
const password = document.getElementById("password").value;
const passwordConfirm = document.getElementById("confirmPassword")
.value;
register(name, email, password, passwordConfirm);
});
Note: e.preventdefault plays major role.

Related

Next Js Api routes response helpers (redirect)

I'M trying to create a login functionality in Next js.
Everything is pretty much done but I'm unable to redirect to homepage after login.
I'm using Next js with sanity as headless CMS
This is my login api
export default async function CreateComment(req, res) {
const { email, password , user } = JSON.parse(req.body)
console.log(password , "123")
const Alluser = user.map((item)=>{
return item.email
})
const UserPassword = user.map((item)=>{
return item.password
})
if (Alluser.includes(email) && UserPassword == password){
console.log(email)
}
res.redirect(307, '/').status(200).send('Success')
}
After Login Error in terminal
Response in network #1
Response in network #2
Use the redirect as follows
res.redirect(307, '/');
Redirects to a specified path or URL

The Resource submitted could not be validated: Mailchimp Status 400

I have been trying to make a Simple Newsletter signup Form where I am Taking basic details from the User and sending that data to Mailchimp using API's.
I am facing the problem in sending POST HTTPS Request. Tried reading different answers but not able to solve problems.
Here's the screenshot of the Issue.
Code :
app.post("/", function (req, res) {
const firstName = req.body.fname;
const lastName = req.body.lname;
const email = req.body.email;
const data = {
members: [
{
email_address : email,
status: "subscribed",
merge_fields: {
FIRSTNAME: firstName,
LASTNAME: lastName
}
}
]
};
var jsonDATA = JSON.stringify(data);
const url = "https://us1.api.mailchimp.com/3.0/lists/<My_LIST_ID>/members/"; //Removed List Id for now to post Question.
const options = {
method: "POST",
auth: "pranshukas:MY_API_KEY" //Removed API_KEY to post the Question
}
const request = https.request(url, options, function (response) {
response.on("data", function (data) {
console.log(JSON.parse(data));
})
});
request.write(jsonDATA);
request.end();
});
I also tried using POSTMAN and there I am able to successfully send the Request to the Server and add details. But facing a Problem when I am implementing on my local server.
Please Help me out I know I am making some mistake in making post HTTPS request but stuck where.
Looks like you have some problem with the email address input, The email address field is blank and it should be populated with the email address.
Also, I think you can delete the group name(members) from the URL
const url = "https://us1.api.mailchimp.com/3.0/lists/<My_LIST_ID>/";
As recommendation i think you should add a failure route, in case of failure.
just for example:
You can make two different routes/pages for success and failure.
you can add this inside the const request anonymous function after having this routes.
if(response.statusCode === 200) {
res.sendFile(__dirname + "/success.html");
} else {
res.sendFile(__dirname + "/failure.html");
}

Stripe succesfully creating customer without card details

Complete web/Stripe newbie here. I built an iOS app, but the method of taking payments that I wanted to use isn't allowed on iOS, so I had to set up a website for it.
The website uses HTML/CSS, with a node backend hosted on Heroku. The website is a simple site that takes the name and card details of the user, but there's currently an issue with my implementation.
In app.get(), I create a customer and a setupIntent, and then this gets filled out when the user clicks a button on the site (just an event listener in js on the client-side).
My issue is, when I create a customer it creates an empty customer every time the page is loaded. If I remove this customer, there is no extra customer being added on load, and the correct customer is created, but there is no card attached to the customer's account!
I'm sure this is a basic error on my part, as I rushed through learning web dev in order to get the app to accept payments (we got an unexpected rejection from the App Review team, basically saying our app will never be acccepted as long as it takes card details on the app).
Thanks in advance for any/all help.
Cheers!
Josh
Server-side:
const express = require("express");
const bodyParser = require("body-parser");
const ejs = require("ejs");
require('dotenv').config()
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static("public"));
const Stripe = require('stripe');
const stripe = Stripe(process.env.SECRET_KEY);
app.get('/', async (req, res) => {
var fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
const customer = await stripe.customers.create({
email: fullUrl.split('=')[1] //This gets the email sent in the URL from the app
});
const intent = await stripe.setupIntents.create({
customer: customer.id,
payment_method_types: ['card'],
});
console.log(fullUrl)
console.log(fullUrl.split('=')[1])
res.render('index', { client_secret: intent.client_secret });
})
app.listen(process.env.PORT || 3000);
Client-side:
var stripe = Stripe('livePublicKeyIsHere');
// const firebase = require("firebase");
// require("firebase/firestore");
var elements = stripe.elements();
var cardElement = elements.create('card');
cardElement.mount('#card-element');
var db = firebase.firestore();
var cardholderName = document.getElementById('cardholder-name');
var setupForm = document.getElementById('setup-form');
var clientSecret = setupForm.dataset.secret;
const queryString = window.location.search;
const email = queryString.split('=')[1];
setupForm.addEventListener('submit', function(ev) {
ev.preventDefault();
stripe.confirmCardSetup(
clientSecret, {
payment_method: {
card: cardElement,
billing_details: {
name: cardholderName.value
},
},
}
).then(function(result) {
if (result.error) {
console.log("Error!!!" + result.error.message);
window.alert("There's an error: " + result.error.message);
} else {
console.log("Success!!!");
window.alert("Account created! Download and log into the app in order to continue.");
addUserToFirestore(email)
}
});
});
function addUserToFirestore(email) {
createUserOnFirestore(email);
db.collection("Users").doc(email).collection("Settings").doc("info").set({
cardDetailsAdded: true
})
.then(() => {
console.log("Document successfully written!");
})
.catch((error) => {
console.error("Error writing document: ", error);
});
}
function createUserOnFirestore(email) {
db.collection("Users").doc(email).set({
exists: true
})
.then(() => {
console.log("Document successfully written!");
})
.catch((error) => {
console.error("Error writing document: ", error);
});
}
The reason is because you're using get instead of post. When your user clicks the button, it should fire a POST request to your server to generate a SetupIntent object which you have already done. You also should store a relation mapping between your user and the Customer that is created, so you don't always create a new Customer when user adds a new card, instead you add the new card to existing Customer object.
While using a customer is recommended, ultimately it is optional to provide a customer (API ref). You can also attach a payment method to a customer separately, as long as you do so before using it for a payment.
Note that unless attached to a customer, a payment method is one-time-use only.

How can I email links work on the front end?

I have built some functionality into my API that sends a verification email to a user and then when a get request is made to the route the user then becomes active and can be used to login. In order to make this work on the front end I have used a res.redirect which takes me to the login page.
The problem, however, is that this means that when I want to replicate this journey in postman I then receive a load of html rather than a formatted json response. So my question is, is there a way that we can handle this request so that, depending on where it is called, a different response is sent back? As I do not think an event listener will work in the case of an email.
For context, my application uses nodejs, mongodb and pug templates.
`exports.signup = catchAsync(async (req, res, next) => {
const { token } = req.params;
const { email } = jwt.verify(token, process.env.JWT_SECRET);
const user = await User.findOne({ email });
if (!user || !((await user.signUpId) === token)) {
return next(new AppError('Invalid link', 401));
}
user.ready = true;
user.singUpId = undefined;
await user.save({ validateBeforeSave: false });
const url = `${req.protocol}://${req.get('host')}/me`;
await new Email(user, url).sendWelcome();
await res.redirect('http://localhost:5000/login');
});`

Problem maintaining session data with Vue JS and Sails JS

Session information is not being maintained when APIs invoked via the VueJs.
In the sails backend, login action set the user id to the session. Whereas in the sessionAuth policy I am simply checking for the user id in the req session.
module.exports = async function (req, res, next) {
// User is allowed, proceed to the next policy,
// or if this is the last policy, the controller
const id = req.session.userId;
if (id) {
const user = await User.findOne({ id });
req.user = user;
if (user) {
return next();
}
}
// User is not allowed
// (default res.forbidden() behavior can be overridden in `config/403.js`)
return res.forbidden('You are not permitted to perform this action.');
};
The above policy works perfectly when requests are being made from Postmen. I invoke login action, any action invoked after that does have user id set in the session. But if the same sequence is followed in a web application user id is missing from the session even after the successful login.
Login component
axios.post(`${this.$config.baseUrl}/login`, this.user)
.then(res => {
this.$router.push({ path: "/home" });
})
Component accessing secured data
const response = await axios.get(`${baseUrl}/course`
return { courseList: response.data };
}

Categories