हेल्लो दोस्तों! चलिए आज वेब डेवलपमेंट की एक ऐसी समस्या को जड़ से खत्म करते हैं, जिसने हर वेब डेवलपर को कभी न कभी परेशान जरूर किया है।
अगर आप MERN Stack पर काम कर रहे हैं, या फिर अपने ReactJS frontend को किसी ExpressJS backend API से जोड़ने की कोशिश कर रहे हैं, तो आपने ब्राउज़र के Console में एक चमकीला लाल रंग का error जरूर देखा होगा।
वह एरर कुछ इस तरह दिखता है:
Access to fetch at 'http://localhost:5000/api/users' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
इस एरर को देखकर नए डेवलपर्स अक्सर घबरा जाते हैं। वे सोचते हैं कि उनके API कोड में कोई खराबी है, या फिर उनका डेटाबेस सर्वर काम नहीं कर रहा है। लेकिन असल में, यह कोई बग नहीं है, बल्कि ब्राउज़र का एक बेहद जरूरी सिक्योरिटी फीचर है।
आज के इस मास्टर-क्लास ट्यूटोरियल में, हम बिल्कुल बेसिक से शुरुआत करेंगे और समझेंगे कि CORS क्या है, यह क्यों आता है, और कैसे हम अपने NodeJS और ExpressJS प्रोजेक्ट्स में इस एरर को हमेशा के लिए हल कर सकते हैं। तो चलिए, चाय की चुस्की लेते हैं और इस समस्या का समाधान ढूंढते हैं!
---आखिर यह CORS क्या है? (What is CORS?)
CORS का फुल फॉर्म Cross-Origin Resource Sharing होता है। इसे समझने से पहले हमें ब्राउज़र की एक बहुत ही महत्वपूर्ण सुरक्षा नीति को समझना होगा, जिसे Same-Origin Policy (SOP) कहते हैं।
Same-Origin Policy (SOP) क्या है?
ब्राउज़र बहुत चालाक होते हैं। वे आपकी सुरक्षा का पूरा ध्यान रखते हैं। Same-Origin Policy के नियम के मुताबिक, एक वेबसाइट (Origin A) किसी दूसरी वेबसाइट (Origin B) के API या रिसोर्सेज को बिना अनुमति के एक्सेस नहीं कर सकती।
यहाँ Origin का मतलब तीन चीजों के कॉम्बिनेशन से है:
- Protocol: HTTP या HTTPS
- Domain (Host): localhost, google.com, myapi.com
- Port: 3000, 5000, 8080
अगर इन तीनों में से एक भी चीज़ अलग है, तो ब्राउज़र उसे Cross-Origin मानता है।
उदाहरण के लिए:
http://localhost:3000(आपका React App)http://localhost:5000(आपका Express API)
यहाँ प्रोटोकॉल (http) और डोमेन (localhost) समान हैं, लेकिन पोर्ट (3000 बनाम 5000) अलग हैं। इसलिए, ब्राउज़र इसे एक Cross-Origin रिक्वेस्ट मानता है और सुरक्षा कारणों से इसे ब्लॉक कर देता है। यही कारण है कि आपको CORS error दिखाई देता है।
---CORS काम कैसे करता है? (How CORS Works under the hood)
जब आपका ब्राउज़र किसी दूसरे ओरिजिन पर रिक्वेस्ट भेजता है, तो वह सीधे डेटा नहीं मांगता। ब्राउज़र पहले बैकएंड सर्वर से बातचीत करता है। इसे हम दो कैटेगरी में बांट सकते हैं:
1. Simple Requests
कुछ सामान्य रिक्वेस्ट जैसे GET या POST (बिना किसी कस्टम हेडर के) को सिंपल रिक्वेस्ट कहा जाता है। ब्राउज़र रिक्वेस्ट भेज देता है, लेकिन रिस्पॉन्स को तब तक आपके जावास्क्रिप्ट कोड को नहीं सौंपता जब तक कि सर्वर अपने रिस्पॉन्स में Access-Control-Allow-Origin हेडर न भेजे।
2. Preflight Requests (OPTIONS Method)
अगर आपकी रिक्वेस्ट में कुछ खास चीजें हैं—जैसे कि आपने PUT, DELETE मेथड का इस्तेमाल किया है, या फिर कोई कस्टम हेडर (जैसे Authorization Header या Content-Type: application/json) भेजा है—तो ब्राउज़र मुख्य रिक्वेस्ट भेजने से पहले एक "जांच रिक्वेस्ट" भेजता है।
इस जांच रिक्वेस्ट को Preflight Request कहते हैं, और यह OPTIONS HTTP मेथड का उपयोग करती है।
सर्वर को इस OPTIONS रिक्वेस्ट का जवाब देकर ब्राउज़र को बताना होता है कि "हाँ, मैं इस ओरिजिन से इस तरह के रिक्वेस्ट स्वीकार करने के लिए तैयार हूँ।" अगर सर्वर हरी झंडी देता है, तभी ब्राउज़र असली (Actual) रिक्वेस्ट भेजता है।
---Express JS में CORS Error को हल करने के तरीके
ExpressJS में इस एरर को हल करने के मुख्य रूप से दो तरीके हैं। पहला तरीका है कस्टम मिडलवेयर (Custom Middleware) बनाकर रिस्पॉन्स हेडर्स को मैन्युअली सेट करना, और दूसरा (और सबसे आसान) तरीका है ऑफिशियल cors पैकेज का इस्तेमाल करना।
हम दोनों तरीकों को पूरी कोडिंग के साथ विस्तार से समझेंगे ताकि आपके पास इस समस्या का पूरा ज्ञान हो।
---तरीका १: कस्टम मिडलवेयर के ज़रिए हेडर्स सेट करना (Manual Method)
अगर आप अपने प्रोजेक्ट में कोई बाहरी लाइब्रेरी या पैकेज इंस्टॉल नहीं करना चाहते हैं, तो आप Express के मिडलवेयर फंक्शन का उपयोग करके खुद के कस्टम हेडर्स सेट कर सकते हैं।
ध्यान देने वाली बात ये है कि यह मिडलवेयर आपके सभी रूट हैंडलर्स (Route Handlers) से ऊपर होना चाहिए ताकि हर रिक्वेस्ट पर यह हेडर लागू हो सके।
नीचे दिए गए कोड को ध्यान से देखें। यह एक पूरी तरह से काम करने वाला ExpressJS सर्वर है जिसमें हमने मैन्युअली CORS हेडर्स सेट किए हैं:
const express = require('express');
const app = express();
// JSON डेटा पार्स करने के लिए मिडलवेयर
app.use(express.json());
// कस्टम CORS मिडलवेयर
app.use((req, res, next) => {
// हम केवल अपने React App (localhost:3000) को अनुमति दे रहे हैं
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
// हम कौन-कौन से HTTP Methods की अनुमति देना चाहते हैं
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
// हम क्लाइंट को कौन-कौन से Headers भेजने की अनुमति देते हैं
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With');
// यदि क्लाइंट क्रेडेंशियल्स (Cookies/Sessions) भेजना चाहता है
res.setHeader('Access-Control-Allow-Credentials', 'true');
// Preflight (OPTIONS) रिक्वेस्ट को तुरंत हैंडल करना
if (req.method === 'OPTIONS') {
return res.sendStatus(200);
}
// अगले मिडलवेयर या रूट पर जाने के लिए next() कॉल करें
next();
});
// एक सिंपल टेस्ट API Endpoint
app.get('/api/data', (req, res) => {
res.status(200).json({
success: true,
message: "CORS Error सफलतापूर्वक हल हो गया है!",
data: {
username: "Rahul Kumar",
role: "Senior Developer"
}
});
});
// सर्वर को पोर्ट 5000 पर स्टार्ट करना
const PORT = 5000;
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});
यह कोड कैसे काम करता है?
- res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000'): यह ब्राउज़र को बताता है कि केवल
http://localhost:3000से आने वाली रिक्वेस्ट ही इस सर्वर का डेटा पढ़ सकती हैं। - OPTIONS Request handling: जब ब्राउज़र Preflight रिक्वेस्ट भेजता है, तो हमारा मिडलवेयर तुरंत
200 OKरिस्पॉन्स भेज देता है, जिससे ब्राउज़र संतुष्ट हो जाता है और मुख्य रिक्वेस्ट भेज देता है।
तरीका २: 'cors' NPM पैकेज का उपयोग करना (The Industry Standard)
मैन्युअल तरीका अच्छा है, लेकिन बड़े प्रोडक्शन ऐप्स में अलग-अलग तरह के क्रेडेंशियल्स, मल्टीपल डोमेन्स और सुरक्षा की अन्य चीजों को मैन्युअली संभालना मुश्किल और थकाऊ हो सकता है।
इसीलिए, NodeJS कम्युनिटी में cors नाम का एक बेहद लोकप्रिय और भरोसेमंद पैकेज मौजूद है। चलिए देखते हैं इसका इस्तेमाल कैसे करना है।
Step 1: पैकेज इंस्टॉल करें
अपने टर्मिनल में प्रोजेक्ट डायरेक्टरी के अंदर नीचे दी गई कमांड चलाएं:
npm install cors
Step 2: Express ऐप में इसका इस्तेमाल करें
यहाँ हमने cors पैकेज का उपयोग करके एक पूरा, प्रोडक्शन-रेडी एक्सप्रेस सर्वर तैयार किया है:
const express = require('express');
const cors = require('cors');
const app = express();
app.use(express.json());
// विकल्प A: सभी Origins को अनुमति देना (Development के लिए ठीक है, पर Production के लिए सुरक्षित नहीं है)
// app.use(cors());
// विकल्प B: कस्टम कॉन्फ़िगरेशन (Highly Recommended for Production)
const corsOptions = {
// केवल इस डोमेन को अनुमति दें
origin: 'http://localhost:3000',
// क्रेडेंशियल्स जैसे कुकीज़ या ऑथराइजेशन टोकन की अनुमति देना
credentials: true,
// कौन-कौन से मेथड्स एलाऊ करने हैं
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
// कौन से हेडर्स क्लाइंट भेज सकता है
allowedHeaders: ['Content-Type', 'Authorization'],
// Preflight रिस्पॉन्स को ब्राउज़र में कितने समय तक कैश (Cache) रखना है (सेकंड में)
maxAge: 86400, // 24 hours
// कुछ पुराने ब्राउज़र्स के लिए सक्सेस स्टेटस कोड सेट करना
optionsSuccessStatus: 200
};
// cors मिडलवेयर को अपने ऑप्शंस के साथ लागू करें
app.use(cors(corsOptions));
// एपीआई एंडपॉइंट
app.get('/api/users', (req, res) => {
res.status(200).json([
{ id: 1, name: "Amit Sharma" },
{ id: 2, name: "Priya Patel" }
]);
});
const PORT = 5000;
app.listen(PORT, () => {
console.log(`Server successfully running on port ${PORT}`);
});
---
Dynamic Origins: जब आपके पास मल्टीपल फ्रंटएंड डोमेन्स हों
असली दुनिया में, जब आप कोई बड़ा ऐप बनाते हैं, तो आपके पास सिर्फ एक फ्रंटएंड URL नहीं होता। आपके पास डेवलपमेंट के लिए localhost, टेस्टिंग के लिए एक स्टेजिंग URL (जैसे Vercel या Netlify) और अंत में एक फाइनल प्रोडक्शन डोमेन (जैसे https://mywebapp.com) हो सकता है।
ऐसी स्थिति में आप corsOptions के origin प्रॉपर्टी में एक एरे (Array) या फिर एक कस्टमाइज़्ड फ़ंक्शन पास कर सकते हैं जो डायनेमिकली रिक्वेस्ट के ओरिजिन को चेक करेगा।
चलिए देखते हैं इसे कैसे लिखा जाता है:
const express = require('express');
const cors = require('cors');
const app = express();
// हमारे स्वीकृत डोमेन्स की लिस्ट (Whitelist)
const allowedOrigins = [
'http://localhost:3000',
'https://my-staging-app.vercel.app',
'https://www.mywebapp.com'
];
const corsOptions = {
origin: function (origin, callback) {
// यदि ओरिजिन हमारी लिस्ट में है, या यदि कोई ओरिजिन नहीं है (जैसे Postman या सर्वर-टू-सर्वर रिक्वेस्ट)
if (!origin || allowedOrigins.indexOf(origin) !== -1) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS policy!'));
}
},
credentials: true
};
app.use(cors(corsOptions));
app.get('/api/secure-data', (req, res) => {
res.json({ message: "यह डेटा केवल स्वीकृत डोमेन्स को ही दिखाई देगा!" });
});
app.listen(5000, () => console.log("Server running on port 5000"));
---
CORS एरर से जुड़े कॉमन मिस्टेक्स और उनके सोलूशन्स
दोस्तों, कई बार सब कुछ सही सेट करने के बाद भी CORS एरर आ जाता है। चलिए कुछ ऐसी गलतियों पर नज़र डालते हैं जो अक्सर डेवलपर्स कर बैठते हैं:
१. 'cors' मिडलवेयर को रूट हैंडलर्स के नीचे लिखना
यह सबसे आम गलती है। एक्सप्रेस में मिडलवेयर्स का क्रम (Order) बहुत मायने रखता है। यदि आपने अपने रूट्स को पहले डिफाइन कर दिया और app.use(cors()) को नीचे लिखा, तो रूट्स पर रिक्वेस्ट जाने से पहले CORS हेडर सेट ही नहीं होंगे और ब्राउज़र एरर दे देगा।
समाधान: हमेशा अपने सभी API रूट्स (जैसे app.use('/api', myRouter)) को लिखने से पहले सबसे ऊपर CORS मिडलवेयर को रखें।
२. Credentials इनेबल करने पर Origin को '*' (Wildcard) सेट करना
यदि आपके फ्रंटएंड को कुकीज़ (Cookies) या सेशन क्रेडेंशियल्स की ज़रूरत है, और आपने अपने फ्रंटएंड फेच रिक्वेस्ट में credentials: 'include' सेट किया है, तो बैकएंड पर origin: '*' रखना सख्त मना है। ब्राउज़र इसे तुरंत ब्लॉक कर देगा और कंसोल में एरर फेंक देगा।
समाधान: जब भी credentials: true हो, तो origin में हमेशा एक स्पेसिफिक डोमेन (जैसे 'http://localhost:3000') ही पास करें, कभी भी वाइल्डकार्ड स्टार (*) का उपयोग न करें।
३. प्रोडक्शन में रिवर्स प्रॉक्सी (Nginx / Cloudflare) का इस्तेमाल करना
कई बार आपका कोड बिल्कुल सही होता है, लेकिन जब आप उसे प्रोडक्शन सर्वर जैसे AWS, VPS या Render पर डिप्लॉय करते हैं, तो आपका रिवर्स प्रॉक्सी सर्वर (जैसे Nginx) या Cloudflare भी CORS एरर दे सकता है।
समाधान: सुनिश्चित करें कि यदि आप Nginx का उपयोग कर रहे हैं, तो आपके Nginx कॉन्फ़िगरेशन फ़ाइल में CORS हेडर्स ओवरराइड न हो रहे हों, या फिर आप सीधे Nginx लेवल पर ही CORS हेडर्स को कॉन्फ़िगर कर दें और एक्सप्रेस कोड से हटा दें।
---परफॉरमेंस और सिक्योरिटी के लिए बेस्ट प्रैक्टिसेज (Best Practices)
जब आप प्रोडक्शन लेवल पर काम कर रहे हों, तो केवल एरर को सॉल्व करना ही काफी नहीं होता। सर्वर की परफॉरमेंस और सिक्योरिटी को बनाए रखना भी उतना ही जरूरी है। यहाँ कुछ बेस्ट प्रैक्टिसेज दी गई हैं जिन्हें आपको हमेशा फॉलो करना चाहिए:
- maxAge का उपयोग करें: ब्राउज़र हर बार रिक्वेस्ट भेजने से पहले जो Preflight (OPTIONS) रिक्वेस्ट भेजता है, उससे सर्वर पर लोड बढ़ता है।
maxAgeसेट करने से ब्राउज़र उस रिस्पॉन्स को कैश कर लेता है और बार-बार फालतू रिक्वेस्ट नहीं भेजता। - Production में Wildcard (*) से बचें: कभी भी अपने लाइव प्रोजेक्ट में
origin: '*'न छोड़ें। यह आपके एपीआई को असुरक्षित बनाता है, जिससे कोई भी अनधिकृत वेबसाइट आपके सर्वर से डेटा चुरा सकती है। - केवल आवश्यक Methods की अनुमति दें: अगर आपका एपीआई केवल डेटा पढ़ने के लिए है, तो CORS में केवल
GETमेथड की अनुमति दें।POST,PUT,DELETEको डिसेबल रखें।
संक्षेप में कहें तो... (Toh dosto, humne aaj seekha...)
तो दोस्तों, आज हमने सीखा कि ब्राउज़र का Same-Origin Policy सुरक्षा के लिए कितना आवश्यक है और कैसे यह हमारी सुरक्षा करता है। जब भी हमें अलग-अलग पोर्ट्स या डोमेन्स के बीच डेटा का आदान-प्रदान करना होता है, तो हमें सर्वर साइड पर एक्सप्रेस को यह बताना पड़ता है कि "हाँ, यह फ्रंटएंड हमारा ही है और हम इस पर भरोसा करते हैं।"
हमने मैन्युअल हेडर्स सेट करने का तरीका भी देखा और साथ ही cors पैकेज के जरिए एकदम प्रोफेशनल और सुरक्षित तरीके से इस समस्या का निवारण करना भी सीखा। अब अगली बार जब भी आपके कंसोल में यह एरर चमकेगा, तो आप बिना डरे इसे चुटकियों में सुलझा लेंगे!
कोडिंग करते रहिए, नई चीजें सीखते रहिए, और अगर कोई भी दुविधा हो, तो अपने इस सीनियर डेवलपर दोस्त को याद करना न भूलें। मिलते हैं अगले ट्यूटोरियल में!
---Frequently Asked Questions (FAQs)
Q1: क्या Postman में रिक्वेस्ट भेजने पर भी CORS error आता है?
नहीं, Postman में रिक्वेस्ट भेजने पर CORS error कभी नहीं आता। CORS एक विशुद्ध रूप से "ब्राउज़र-आधारित" सुरक्षा नीति (Browser-side Security Policy) है। चूंकि Postman कोई ब्राउज़र नहीं है, इसलिए वह Same-Origin Policy को लागू नहीं करता। यही कारण है कि कोई भी API Postman में पूरी तरह काम करती है लेकिन ब्राउज़र के कंसोल में एरर देती है।
Q2: क्या मैं फ्रंटएंड साइड (React/Vue) से CORS error को पूरी तरह ठीक कर सकता हूँ?
नहीं, फ्रंटएंड कोड लिखकर आप ब्राउज़र की सुरक्षा नीति को बायपास नहीं कर सकते। CORS का वास्तविक और सही समाधान हमेशा "सर्वर-साइड" (Backend) पर ही होता है। हालांकि, डेवलपमेंट के दौरान आप React में package.json के अंदर "proxy": "http://localhost:5000" सेट करके इसे अस्थायी रूप से हल कर सकते हैं, लेकिन प्रोडक्शन में जाने पर आपको बैकएंड पर ही CORS कॉन्फ़िगर करना होगा।
Q3: Access-Control-Allow-Origin: '*' का क्या नुकसान है?
तारांकन चिह्न (*) का अर्थ है कि इंटरनेट पर मौजूद कोई भी वेबसाइट आपके सर्वर से डेटा का अनुरोध कर सकती है और उसे पढ़ सकती है। यदि आपका एपीआई पब्लिक है (जैसे मौसम की जानकारी या सार्वजनिक ब्लॉग), तो यह ठीक है। लेकिन यदि आपके एपीआई में संवेदनशील यूजर डेटा है, तो '*' सेट करने से कोई भी दुर्भावनापूर्ण वेबसाइट (Malicious Website) आपके यूजर्स के डेटा को स्क्रिप्ट के जरिए चुरा सकती है, जो कि बहुत बड़ा सुरक्षा जोखिम है।

टिप्पणियाँ
एक टिप्पणी भेजें