I’m facing an issue with the URL shortening feature in my application. it work fine in localhost, Specifically, valid shortCode entries are sometimes redirecting to incorrect URLs. I suspect there might be an issue with the way the database is handling the shortCode field or how the query logic is retrieving the URLs.
Here’s a quick summary of the problem:
Problem: When a user tries to access a shortened URL (e.g., https://shorty-sigma.vercel.app/73E8YKP), the app redirects to the wrong URL instead of original URL. (NAVIGATING TO SAME WEBSITE/URL THAT GENERATED THE CODE) What I’ve Checked: The shortCode entries in the database appear to be correct. Environment variables seem to be set up correctly since authentication and other features are working fine. The URL shortening process generates and saves shortCode as expected, but the retrieval goes wrong. developing with nextjs deployed to vercel.
1import { GetServerSideProps } from 'next';23import dbConnect from '../utils/dbConnect';45import Url from '../models/Url';678// this to handle the URL redirection based on a shortCode parameter.910export const getServerSideProps: GetServerSideProps = async (context) => {11 try {12 await dbConnect();1314 const { shortCode } = context.params;15 console.log('Fetching URL for shortCode:', shortCode);16 const urlEntry = await Url.findOne({ shortCode }).exec();17 console.log('URL Entry:', urlEntry);1819 // use tenary operator that determines the value of the baseUrl variable 20 // based on the environment in which the application is running. Here's a breakdown of what it does:21 if (urlEntry) {22 const originalUrl = urlEntry.originalUrl.startsWith('http')23 ? urlEntry.originalUrl24 : `http://${urlEntry.originalUrl}`;25 console.log('Redirecting to:', originalUrl);2627 return {28 redirect: {29 destination: originalUrl,30 permanent: false,31 },32 };33 } else {34 console.log('No URL entry found for shortCode:', shortCode);35 return {36 notFound: true,37 };38 }39 } catch (error) {40 console.error('Error in getServerSideProps:', error);41 return {42 notFound: true,43 };44 }45};4647const RedirectPage = () => {48 return null;49};5051export default RedirectPage;5253**pages/api/shorten.ts - Manages the URL shortening process and database interaction.**5455import { NextApiRequest, NextApiResponse } from 'next';5657import { nanoid } from 'nanoid';5859import QRCode from 'qrcode';6061import dbConnect from '../../utils/dbConnect';6263import Url from '../../models/Url';6465export default async function handler(req: NextApiRequest, res: NextApiResponse) {66 await dbConnect();6768 // The code fetches the original URL from the database6970 if (req.method === 'POST') {71 const { originalUrl, customDomain, customUrl } = req.body;7273 if (!originalUrl || typeof originalUrl !== 'string') {74 return res.status(400).json({ error: 'Invalid URL' });75 }7677 try {7879 // he nanoid library is used to generate a short code. 80 // The base URL is determined by checking if the environment is production8182 let shortCode = customUrl || nanoid(7);83 const baseUrl = process.env.NODE_ENV === 'production'84 ? process.env.NEXTAUTH_URL85 : 'http://localhost:3000';8687 const shortUrl = customDomain88 ? `${customDomain}/${shortCode}`89 : `${baseUrl}/${shortCode}`;9091 // generates a QR code for the shortened URL.9293 const qrCode = await QRCode.toDataURL(shortUrl);9495 const newUrl = new Url({96 originalUrl,97 shortUrl,98 shortCode,99 qrCode,100 });101102 await [newUrl.save](https://newurl.save)();103104 res.status(201).json({ message: 'URL shortened successfully', shortUrl, qrCode });105 } catch (error) {106 console.error('Error saving URL:', error);107 res.status(500).json({ message: 'Internal Server Error' });108 }109 } else {110 res.status(405).json({ message: 'Method not allowed' });111 }112}113114 **utils/dbConnect.ts - Handles the database connection logic** 115116import mongoose from 'mongoose';117118const MONGODB_URI: string = process.env.MONGODB_URI as string;119120if (!MONGODB_URI) {121 throw new Error('Please define the MONGODB_URI environment variable inside .env.local');122}123124let cached = (global as any).mongoose;125126if (!cached) {127 cached = (global as any).mongoose = { conn: null, promise: null };128}129130async function dbConnect() {131 if (cached.conn) {132 return cached.conn;133 }134135 if (!cached.promise) {136 const opts = {137 bufferCommands: false,138 };139140 cached.promise = mongoose.connect(MONGODB_URI, opts).then((mongoose) => mongoose);141 }142 cached.conn = await cached.promise;143 return cached.conn;144}145146export default dbConnect;147148**env.local - Environment variables setup (with sensitive information redacted)**149150 MONGODB_URI=mongodb+srv://user:password@cluster0.mongodb.net/myDatabase?retryWrites=true&w=majority151152 NEXTAUTH_URL=https://shorty-sigma.vercel.app/153154 GOOGLE_CLIENT_ID=[1234567890-abcde1234.apps.googleusercontent.com](https://1234567890-abcde1234.apps.googleusercontent.com)155156 GOOGLE_CLIENT_SECRET=ABCDEF1234567890157158 GITHUB_CLIENT_ID=gh1234567890abcdef159160 GITHUB_CLIENT_SECRET=ghabcdef1234567890161162 EMAIL_USER=myemail@example.com163164 EMAIL_PASS=myemailpassword165166 JWT_SECRET=myjwtsecretkey167168 NEXTAUTH_SECRET=myNextAuthSecretKey169170171**NOTE: the env.local values are generated for demonstration purpose except for NEXTAUTH_URL**172173import mongoose, { Schema, Model, Document } from 'mongoose';174175interface IUrl extends Document {176 originalUrl: string;177 shortUrl: string;178 shortCode: string;179 qrCode: string;180 customUrl?: string;181 customDomain?: string;182 userId: Schema.Types.ObjectId;183 createdAt: Date;184}185186const UrlSchema: Schema = new Schema({187 originalUrl: { type: String, required: true },188 shortUrl: { type: String, required: true, unique: true },189 shortCode: { type: String, required: true, unique: true },190 qrCode: { type: String },191 userId: { type: mongoose.Schema.Types.ObjectId, ref: 'User' },192 customDomain: { type: String },193 customUrl: { type: String },194 createdAt: { type: Date, default: [Date.now](https://date.now) }195196}, { timestamps: true });197const Url: Model = mongoose.models.Url || mongoose.model('Url', UrlSchema);198export default Url