Theory
વચ્ચે થતું કામ
તમારા Express API પર request પહોંચે ત્યારે તમારો route handler ચાલે એ પહેલાં ઘણી વાર કેટલીક બાબતો કરવી પડે છે: JSON body parse કરવું, બોલાવનારને છૂટ છે કે નહીં તે તપાસવું, request ની નોંધ કરવી. એ બધું દરેક handler માં ઠાંસવાને બદલે Express middleware વાપરે છે, એટલે કે એવાં functions જે request ની પ્રક્રિયાની વચ્ચે ચાલે છે.
Middleware એ Express ના સૌથી મહત્ત્વના વિચારોમાંનો એક છે, અને parsing, static files, cross-origin પ્રવેશ તથા તમારી પોતાની ચકાસણીઓ, બધું એના પર ચાલે છે. Backend નો આ છેલ્લો પાઠ સમજાવે છે કે middleware એટલે શું અને તમે હંમેશા વાપરવાના હો એવા સામાન્ય ટુકડા કયા છે, જેમાં એક એવો પણ છે જ્યાં દરેક full-stack શરૂઆતી ઠોકર ખાય છે: CORS.
Theory
Middleware એટલે શું
Middleware એ એવું function છે જેને (req, res, next) મળે છે અને જે request દરમિયાન, તમારા route handler પહેલાં (કે એની આસપાસ) ચાલે છે. એ request અને response ને વાંચી કે બદલી શકે છે, અને પછી next() બોલાવીને કાબૂ પછીના middleware કે handler ને સોંપે છે (અથવા એ જાતે જ response પૂરો કરી શકે છે).
Middleware ને તમે app.use(...) વડે નોંધો છો. એ ક્રમમાં ચાલે છે અને એવી pipeline બનાવે છે જેમાંથી દરેક request પસાર થાય છે. એનાથી તમે વહેંચાયેલું કામ છૂટું પાડી શકો છો, અને એને વારંવાર લખવાને બદલે એક જ જગ્યાએ, એક જ વાર, અનેક routes માટે કરી શકો છો. Parsing, logging, authentication અને error સંભાળવું, એ બધું સ્વાભાવિક રીતે જ middleware છે.
Practical
Built-in middleware અને એક custom middleware
const express = require('express');
const cors = require('cors');
const app = express();
app.use(express.json()); // built-in: parse JSON bodies -> req.body
app.use(express.static('public')); // built-in: serve files from /public
app.use(cors()); // allow cross-origin requests (Angular -> API)
// custom middleware: log every request, then pass control on
app.use((req, res, next) => {
console.log(req.method, req.url);
next(); // MUST call next() to continue
});This example runs in Gri-Learn on the web, where you can edit it and see the output.
Formula
CORS: full-stack શરૂઆતીની ઠોકર
આ એવી મુશ્કેલી છે જે તમને નડવાની જ છે. FestConnect નું Angular front end એક origin પર ચાલે છે (ધારો કે localhost:4200) અને Express નું API બીજા પર (localhost:3000). સલામતી ખાતર browsers કોઈ page ને જુદા origin પરના API ને બોલાવતાં રોકે છે, જ્યાં સુધી API સ્પષ્ટ છૂટ ન આપે. આ જ CORS છે (Cross-Origin Resource Sharing).
એનું લક્ષણ console માં દેખાતી, રોકાયેલા cross-origin request વિશેની error છે, અને એનો ઉકેલ server પર cors middleware ચાલુ કરવાનો છે (app.use(cors())), જે એવાં headers મોકલે છે જે browser ને જણાવે કે API આ call ને છૂટ આપે છે. લગભગ દરેક full-stack શરૂઆતી એક વાર તો આનો ભેટો કરે જ છે; હવે તમે એને તરત ઓળખી લેશો.
Theory
Environment variables રહસ્યોને code ની બહાર રાખે છે
તમારા backend ને એવી ગોઠવણ જોઈએ છે જે code માં જડી ન દેવાય: database નું connection string, API keys, port. એ બધું source code માં મૂકવું અસલામત પણ છે અને અક્કડ પણ (.NET માં web.config પરથી શીખેલો એ જ પાઠ યાદ કરો).
Node નો રિવાજ છે environment variables, જે .env ફાઇલમાં સચવાય છે અને process.env દ્વારા વંચાય છે (ઘણી વાર dotenv package સાથે). એટલે process.env.DB_URL માં database નું સરનામું રહે છે, જે code ની બહાર અને version control ની બહાર રખાય છે. એનાથી એ જ code તમારા laptop પર અને live server પર જુદી ગોઠવણ સાથે ચાલી શકે છે, અને રહસ્યો બહાર ઢોળાતાં અટકે છે. ગોઠવણ environment માં રાખો, code માં નહીં.
Quiz
localhost:4200 પરનું તમારું Angular app localhost:3000 પરના તમારા Express API ને બોલાવે છે, અને browser એને cross-origin error સાથે રોકે છે. Server પર એનો ઉકેલ શું છે?
- બધો code એક જ ફાઇલમાં લઈ જવો
- CORS middleware ચાલુ કરવું (app.use(cors())), જેથી API cross-origin requests ને છૂટ આપતાં headers મોકલે
- Express છોડીને Angular પર જવું
- Route parameters કાઢી નાખવાં
Show the answer
CORS middleware ચાલુ કરવું (app.use(cors())), જેથી API cross-origin requests ને છૂટ આપતાં headers મોકલે
Browser જુદા જુદા origins વચ્ચેનાં requests (localhost:4200 થી localhost:3000) ને રોકે છે, જ્યાં સુધી API CORS (Cross-Origin Resource Sharing) દ્વારા સંમતિ ન આપે. app.use(cors()) વડે cors middleware ચાલુ કરવાથી API એવાં headers મોકલે છે જે browser ને જણાવે છે કે cross-origin call ને છૂટ છે, અને એથી error ઊકલી જાય છે. વિકલ્પ A browser ની origin ની તપાસને અડતો જ નથી; ફાઇલો ભેગી કરવાથી origins બદલાતાં નથી. વિકલ્પ C નિરર્થક છે: Angular તો call કરનારું front end છે, API ની અવેજી નહીં. વિકલ્પ D સંબંધ વગરનો છે: route parameters ને cross-origin રોકાણ સાથે કશી લેવાદેવા નથી. CORS એ browser ની સલામતીની સગવડ છે, અને server પર cors middleware ચાલુ કરવું એ પ્રમાણભૂત ઉકેલ છે.
Think first
Browsers મુદ્દલ cross-origin requests ને રોકે છે જ કેમ?
CORS શરૂઆતીઓને બહુ સતાવે છે. તો એ ખરેખર કઈ સલામતીની મુશ્કેલીથી બચાવે છે? વિચારીને પછી tap કરો.
Show the answer
એ વપરાશકર્તાઓને એવી દુષ્ટ website ઓથી બચાવે છે જે ચૂપચાપ એવી બીજી sites ને requests મોકલે જ્યાં વપરાશકર્તા login થયેલો હોય; 'same-origin policy' બરાબર એ જ હુમલો અટકાવવા ઘડાઈ છે.
ધારો કે એક tab માં તમે તમારી બેંકમાં login થયેલા છો. Origin ના નિયંત્રણ વગર, બીજા tab માં તમે ખોલેલું કોઈ દુષ્ટ page તમારા login થયેલા સત્રનો ઉપયોગ કરીને ચૂપચાપ તમારી બેંકના API ને requests મોકલી શકે, તમારો data વાંચી શકે કે પૈસા ખસેડી શકે, અને એ પણ તમારી જાણ બહાર, કારણ કે browser એ requests સાથે તમારી બેંકની cookies જોડી દેત.
એ અટકાવવા browsers same-origin policy લાગુ પાડે છે: મૂળ ગોઠવણમાં એક origin (scheme, host અને port) પરનું JavaScript બીજા origin ના responses વાંચી શકતું નથી. એ સલામતીની મૂળ ગોઠવણને લીધે જ port 4200 પરનું તમારું Angular app સીધેસીધું port 3000 પરના તમારા API ને બોલાવી શકતું નથી, કારણ કે browser એ બંનેને જુદા origins ગણે છે અને વાંચવાનું રોકે છે.
CORS એ server માટે સંમતિ આપવાની નિયંત્રિત રીત છે: ચોક્કસ headers મોકલીને (જે cors middleware ઉમેરે છે) API browser ને કહે છે કે 'આ origin પરથી આવતાં requests ને હું છૂટ આપું છું', એટલે તમારા જેવા વાજબી cross-origin calls ને છૂટ મળે છે અને આડેધડ દુષ્ટ calls ને નહીં.
એટલે CORS તમને હેરાન કરવા ઊભું કરેલું અડચણ નથી; એ તો એવી વ્યવસ્થા છે જે તમને વપરાશકર્તાઓની રક્ષા માટેના સલામતીના નિયમને સલામત રીતે હળવો કરવા દે છે. આ સમજાય એટલે ગૂંચવતી error એક લીટીના સ્પષ્ટ ઉકેલમાં ફેરવાઈ જાય છે, અને સાથે web-security નો ખરો સિદ્ધાંત પણ શીખવા મળે છે. રોકાણ એટલે browser વપરાશકર્તાની રક્ષા કરે છે; CORS એટલે server પરવાનગી આપે છે.
Summary
Key takeaways
- Middleware એ (req, res, next) વાળું function છે જે request ની પ્રક્રિયા દરમિયાન ચાલે છે; એને app.use() વડે નોંધો.
- એણે કાબૂ આગળ સોંપવા next() બોલાવવું પડે, નહીં તો એ જાતે response પૂરો કરે; middleware pipeline માં ચાલે છે.
- Built-in: express.json() JSON bodies parse કરે છે (જેથી req.body મળે); express.static() static files પીરસે છે.
- CORS: browsers cross-origin requests (એક port પરના Angular થી બીજા port પરના Express સુધી) ને રોકે છે, જ્યાં સુધી API છૂટ ન આપે; ઉકેલ છે app.use(cors()).
- CORS જે same-origin policy ને હળવી કરે છે, એ દુષ્ટ sites ને તમે login થયેલા હો એવી બીજી sites બોલાવતાં અટકાવવા માટે છે.
- .env ફાઇલમાંનાં environment variables (process.env દ્વારા વંચાતાં) ગોઠવણ અને રહસ્યોને code ની બહાર રાખે છે.
- યાદ રાખવાની કડી: middleware વચ્ચે ચાલે છે; express.json parse કરે, cors cross-origin ને છૂટ આપે, અને .env રહસ્યો સાચવે.