Nextjs api route internal error in production - javascript

All apis are working just fine when serving locally but when i try to deploy the app in vercel/ heroku, the apis give me internal error code 500.
So i tried to make a "test api " called hello, it worked just fine until i tried to open connection with db ( query was working locally but in production it gave me internal error)
Here is my code
const mysql= require("mysql2/promise")
export default async function hello(req, res) {
const db= await mysql.createConnection({
host:"eu-cdbr-west-02.cleardb.net",
user:"########",
password:"####",
database:'####',
port:'3306',
})
const [results] = await db.execute("select * from ##",[])
db.end()
res.json(results)
}
Update: On heroku, the api is taking 10 seconds to respond back

Related

Sendgrid emails won't send when deployed to Vercel

Recently, I decided to try out vercel for a small project and ran into issues using sendgrid with vercel. I've implemented sendgrid into nodejs/express projects before on heroku with no issues, but for some reason Vercel just doesn't work.
Even worse, sendgrid gives no errors whatsoever so its been difficult to troubleshoot. The promise just hangs forever. Everything works fine locally when testing and I've confirmed that env variables are correct and loading.
Here's my code:
const sgMail = require('#sendgrid/mail');
const { magicLinkTemplate } = require('./templates');
const sendEmail = async (msg) => {
sgMail.setApiKey(process.env.SENDGRID_API_KEY);
try {
await sgMail.send(msg)
} catch (error) {
console.error(error);
if (error.response) {
console.error(error.response.body)
}
}
}
I've tried a number of iterations, and failed every time. Has anyone else run into issues using vercel with sendgrid?
Alright, so I believe I solved my own problem.
The issue lies in how vercel handles serverless functions:
If you're on free tier, each request must resolve in 10 seconds (for pro its 60)
Vercel seems to instantly terminate a serverless function once a response is returned, aka side effects that are not finished will cease to run.
Previously, I was running the email sends as a side effect and the api response would return without waiting for sendgrid to fullfil its promise. Below is a watered down version of my original code.
router.post('/', checkUser)
async function checkUser(req, res, next) {
const { email } = req.body;
const magicLink = generateMagicLink()
sendMagicLink(email, magicLink)
res.status(200).json({})
}
The sendMagicLink function is async and would continue to run locally, but in vercel it would cease once a status was returned from the api.
New code looks like this...
router.post('/', checkUser)
async function checkUser(req, res, next) {
const { email } = req.body;
const magicLink = generateMagicLink()
await sendMagicLink(email, magicLink)
res.status(200).json({})
}
Now the serverless function stays alive because it waits for the async process to finish.
This whole thing tripped me up because if you have a persistent server, there would be no issues with the original version. Hope this helps someone!

How to deploy Next JS App with Mongoose(MongoDB) connection on Vercel?

I am facing issue while deploying my next js app on vercel with mongodb connection. I have added env variable also on vercel site where we deploy next js app. Is there something going wrong in the below file ?
next.config.js
module.exports = {
env: {
MONGODB_URI: "mongodb://localhost/tasksdb",
},
};
I have add env variable as well into my next js project
.env.local
MONGODB_URI = "mongodb://localhost/tasksdb"
I establish this mongodb connection from this doc https://mongoosejs.com/. It's provide us to connect with mongodb straightaway .
And this my mongodb connection establish code
import { connect, connection } from "mongoose";
const conn = {
isConnected: false,
};
export async function dbConnect() {
if (conn.isConected) return;
const db = await connect(process.env.MONGODB_URI);
conn.isConnected = db.connections[0].readyState;
// console.log(conn.isConnected);
// console.log(db.connection.db.databaseName)
}
connection.on("connected", () => {
console.log("Mongodb connected to db");
});
connection.on("error", (err) => {
console.error("Mongodb connected to", err.message);
});
Is there something wrong by creating the database this way because in local everything working fine ?
I don't think vercel's servers can comunicate with your localhost. You can try hosting your database in the mongodb cloud
The code seems to be fine, but you can not connect to Vercel using localhost. You can use Serverless Atlas version of MongoDB which is free you can host your database there and then connect using the link they will provide.
See : https://www.mongodb.com/pricing

Redis disconnection crashing node js server as well

After reading many stack overflow erros im still unable to solve this issue. I have setup a redis server to cache the data from my node js server , it works fine as long as the redis server is running but as soon as i close the redis server the node server crashes. i want the server to keep working even if the redis server is down
heres my code
import Product from '../models/productModel.js'
import User from '../models/userModel.js'
import slugify from 'slugify'
import redis from 'redis'
import mongoose from 'mongoose'
//connection to redis
const redisClient = redis.createClient(6379) //cause for error when redis server is down
export const listAll = async (req, res) => {
try {
const products = await Product.find({})
.limit(parseInt(req.params.count))
.populate('category')
.populate('subs')
.sort([['createdAt', 'desc']])
.exec()
if (products !== null) {
redisClient.setex(req.params.count, 60, JSON.stringify(products))
}
res.json(products)
} catch (err) {
console.log(err)
}
}
here im getting an ECONNREFUSED error when im stopping the redis server. Is there a way for my node server to keep going even when the redis server is stopped because redis servver is just a supporting mechanism and if cache data is unavailable ill anyway get data from db
is there a way to check if redisClient is undefined or null that i could set to check if the redis server is down and then later i can use it to make the request appropriately
According to the doc of node-redis Error Handling, have you try this ?
client.on("error", function(err) {
assert(err instanceof Error);
assert(err instanceof AbortError);
assert(err instanceof AggregateError);
// The set and get are aggregated in here
assert.strictEqual(err.errors.length, 2);
assert.strictEqual(err.code, "NR_CLOSED");
});

Caches API not working on VPS Debian server

I have a Vue app running on a VPS Debian server with nginx.
I use the Cache API for caching data and loading it into the app.
When the app was uploaded on my ftp it worked fine, after I deployed it on the server, however,
I receive an error :
Uncaught (in promise) ReferenceError: caches is not defined
The code that runs the cache api is:
const getCachedResource = async (type) => {
const url = `${DATA_URL}${type}.json`
const cache = await caches.open(cacheName);
if (cache) {
const response = await cache.match(url)
if (!response) {
return undefined
}
const jsonResponse = await response.json()
return jsonResponse
}
}
Is there anything I need to enable/fix on the VPS to get it going?
The issue was that the Caches API requires HTTPS. When I added the certificate the issue was fixed.

documentPath is not a valid resource path when deployed to Google App Engine with javascript

Description:
I have a frontend React client that is hosted on Firebase Hosting and a NodeJS Express API that is hosted on Google App Engine. The client needs to send a POST request to a NodeJS Express route, the request need to contain a variable called formid that holds the name of a firebase document. When both the server and client is run locally the formid variable gets sent to the API and it is not empty or undefined. But when the API is deployed and the request is sent to GAE instead I get this error:
UnhandledPromiseRejectionWarning: Error: Value for argument "documentPath" is not a valid resource path. Path must be a non-empty string.
The error appears in the Google Cloud Platform Console. In left hand menu I go to; Operations > Logging > Logs Viewer. But I can also tail the logs to my local console with the command "gcloud app logs tail -s default".
Question: Why does the error appear only when the request is sent to GAE and not when I run them locally?
request.headers.form_id contains the name of the document stored in a collection (which is an autoID) in Google Firestore.
async function postFormQuestionHandler(request, response) {
let form_ref = db.collection("forms").doc(request.headers.form_id);
... other code
Express router that recieves the request, forwards it to postFormQuestionHandler function.
router.post("/question", (req, res) => {
postFormQuestionHandler(req, res);
});
Here is where the request firstly is being sent:
async addQuestionsToFormDb(idToken, fomrid, questionids) {
let result = await questionids.map(async (questionid) => {
let data = {
idToken: idToken,
form_id: formid,
question_id: questionid,
};
return await fetch(`${process.env.REACT_APP_API}/form/question`, {
method: 'POST',
mode: 'cors',
headers: data
});
}
From above code I have also tried using the Axios library but it also produces the same error on when the API is deployed to GAE. I have tried reading the documentation of both Axios (Github Axios Documentation) and Fetch (Firefox MDN web docs) but it have not helped me, am I missunderstanding something? Below is what I tried with Axios:
return await axios.post(`${process.env.REACT_APP_API}/form/question`, {}, {
headers: data,
}
);
Other information
Im using Express v4.17.1 and Node v10.19.0, I am also developing this with WSL 2 on Windows 10 2004.
your request.headers.form_id is either empty string or contain invalid character. I guess it contains slash /. Here is more info https://firebase.google.com/docs/firestore/quotas#collections_documents_and_fields

Categories

Resources