← कोर्सच्या मुख्य पानाकडे परत

📐 17 धडे आकृत्यांमध्ये

भाग 1: counter (हिरवट-निळा, 1–6) · भाग 2: ते चालवणे (नारिंगी, 7–12) · भाग 3: पूर्ण नकाशे (13–16) · भाग 4: production APIs (जांभळा, 17). प्रत्येक आकृती खरी गोष्ट आहे — भागांसह चिठ्ठी, फाइल कपाट, validation ची गाळणी, counter चा छेद, पास, पावत्या, पाने — आणि धडे 1–12 खाली एक lab: चिठ्ठी द्या, क्रियापद दोनदा पाठवा, फॉर्म मोडा, पास दाखवा, रांग गाठा. वर्तुळातले आकडे 1 → 2 → 3 या क्रमाने पहा.

1 🏢 API का

फ्रंट ऑफिस — कोणीही दप्तरखान्यात भटकत नाही; तुम्ही काउंटरवर, प्रमाणित चिठ्ठीवर विचारता.

🧒 सोप्या शब्दांत

कल्पना करा, प्रत्येक पालक शाळेच्या records खोलीत शिरून स्वतःच कपाटातून files काढतो. लवकरच files हरवतात आणि कोणी काय नेले ते कोणालाच कळत नाही. म्हणून शाळा front office उघडते: तुम्ही counter वरच्या clerk ला slip देता, आणि records ला फक्त clerk हात लावतो. API म्हणजे computer programs साठीचा असाच counter.

📖 नवे शब्दAPI — असा counter जिथे एक program दुसऱ्याकडे ठरलेल्या पद्धतीने काहीतरी मागतोrequest — तुम्ही देता ती slip: तुम्हाला काय हवे आहेresponse — counter परत देतो ते शिक्का मारलेले उत्तरcontract — वचन: तीच slip दिली की नेहमी त्याच प्रकारचे उत्तर मिळते
1🚪 थेट archive मध्ये — counter नाहीचapp A (CSV)app B (XML)archiveफाइल्स थेट वाचतेस्वतःचा format, स्वतःचे bugs💥 खण हलवलेकोणी काय घेतले याची नोंद नाहीप्रत्येक integration हाताने बांधलेले, नाजूक — एक स्तंभ बदला आणि दोन apps मोडतातकाय वाचले, बदलले, कोणी — कोणालाच माहीत नाही2🏢 फ्रंट ऑफिस — एक counter, एक चिठ्ठी, एक शिक्काकोणतेही app1GET /v1/students/2Accept: application/jsonचिठ्ठी (request)🧑‍💼कारकूनतपासतो · आणतो2archiveदुसरे कोणीहात लावत नाही3200 OK{"id":2,"name":"Katrina"}शिक्का मारलेले उत्तर3📜 एक करार — त्याच चिठ्ठीला तसेच उत्तर, कोणत्याही app कडून, कोणत्याही भाषेत🐍 Pythonurllib.request.urlopen(url)🟨 JavaScriptfetch("/v1/students/2")💻 curlcurl -s :8080/v1/students/2काउंटर/v1/students/{id}एक करारapi/openapi.yaml200 OK — तोच आकार{"id":2,"name":"Katrina",…}$ python3 api/school_api.pyserving :8080/v1/…$ bash api/smoke_test.sh12 checks 🎉ऑफिस आपले खण हलवू शकते (नवा database, नवी भाषा) आणि एकही चिठ्ठी बदलत नाही — हाच सगळा मुद्दा
⏪ आधी

प्रत्येक app थेट archive मध्ये जाऊन files वाचायचे, त्यामुळे एक column हलला की दोन apps बिघडायचे आणि कोणी काय बदलले ते कोणालाच कळायचे नाही.

💡 काय

API म्हणजे front office: एक counter, जिथे कोणतेही app ठरलेली slip देते आणि शिक्का मारलेले उत्तर परत घेते.

⚙️ कसे

App GET /v1/students/2 पाठवते, clerk तपासून archive मधून आणतो आणि विद्यार्थ्याची माहिती JSON मध्ये 200 OK सह परत देतो.

🎯 का

Counter मागे archive बदलू शकते, पण प्रत्येक caller साठी contract तोच राहतो: तीच slip दिली की त्याच प्रकारचे उत्तर मिळते.

🚀 पुढे

पुढे तुम्ही slip ओळ-ओळ वाचाल: method, path, headers, body आणि शिक्क्यावरचा status code (lesson 2).

🧪 Try it here — तीच चिठ्ठी तीन भाषांतून पाठवा आणि तेच शिक्का मारलेले उत्तर वाचा

संपूर्ण धडा 01 वाचा →

2 📨 HTTP ची रचना

विनंतीची चिठ्ठी आणि कारकुनाचा शिक्का — method, path, headers, body, status code.

🧒 सोप्या शब्दांत

शाळेच्या office मधल्या slip वर ठरलेले रकाने असतात: काय करायचे, कोणती file, तुम्ही कोण, आणि भरलेला form. Clerk त्यावर एक आकडा शिक्क्यासारखा मारून परत देतो, जसे 200 म्हणजे झाले, 404 म्हणजे अशी file नाही. HTTP म्हणजे त्या slip ची रचना, म्हणून कुठलाही program ती भरू शकतो आणि शिक्का वाचू शकतो.

📖 नवे शब्दmethod — slip वरचा क्रियेचा शब्द, जसे GET (वाचा) किंवा POST (जोडा)path — तुम्हाला कोणती गोष्ट हवी, जसे /v1/students/2header — slip वरच्या छोट्या नोंदी: तुम्ही कोण, कोणता format वाचू शकताbody — काही जोडताना किंवा बदलताना slip सोबत पाठवलेला भरलेला formstatus code — उत्तरावरचा आकडा: 200 ठीक, 404 सापडले नाही, 500 आमची चूक
1📨 request चिठ्ठी — प्रत्येक भागाचे कामGET /v1/students/2 HTTP/1.1Host: 127.0.0.1:8080Accept: application/jsonX-API-Key: hall-pass-123{"grade": "A"} (फक्त PUT/POST/PATCH)← method + path + version← कोणते ऑफिस← तुम्ही कोणता आकार वाचू शकता← कोण विचारतोय (L06)← रिकामी ओळ← body: फॉर्म (L04)method म्हणजे क्रियापद (L03) · path म्हणजे नाम · headers म्हणजे बारीक अक्षरे · body म्हणजे फॉर्महे सगळे TCP stream वरचा मजकूर — Networking शाळा ते हाताने टाइप करते2📮 शिक्का मारलेले उत्तर — status, headers, bodyHTTP/1.1 200 OKContent-Type: application/jsonETag: "0e9a4c"X-Request-Id: 7f3c2a{"id": 2, "name": "Katrina", "class": "3A"}← शिक्का← body काय आहे← या प्रतीची आवृत्ती (L10)← trace id (L12)← उत्तर200 GET /v1/students/2 1 ms 7f3c2a ← प्रत्येक चिठ्ठीला एक log ओळ3🔖 शिक्के — पाच कुटुंबे, एका नजरेत2xxझाले ✓200 · 201 created · 204 body नाही3xxतिकडे जा301 moved · 304 not modified4xxतुमची चिठ्ठी चुकीची400 · 401 · 403 · 404 · 409 · 4295xxआमचे ऑफिस मोडले500 · 502 · 503 · 5044xx: चिठ्ठी दुरुस्त करा, आंधळेपणाने retry नको · 5xx: नंतर backoff ने retry (L07) · 429: तुम्ही रांगेत, किती वेळ ते Retry-After सांगते (L10)
⏪ आधी

सामायिक slip रचनेशिवाय प्रत्येक app ला काय हवे, ते कोण आहे आणि काय वाचू शकते हे सांगण्याची स्वतःची पद्धत शोधावी लागली असती.

💡 काय

HTTP request म्हणजे method, path, headers आणि body असलेली text slip; उत्तर म्हणजे status code, headers आणि body.

⚙️ कसे

GET /v1/students/2 HTTP/1.1 हे Host आणि Accept headers सह जाते; परत 200 OK, Content-Type, ETag आणि JSON body येते.

🎯 का

Slip आणि शिक्क्याची प्रत्येक ओळ वाचता आली की API चा bug अंदाजाने नाही, तर डोळ्यांनी दिसतो.

🚀 पुढे

Method पुढे REST चे क्रियापद बनते (lesson 3), body म्हणजे form (lesson 4), आणि X-API-Key म्हणजे auth (lesson 6).

🧪 Try it here — चिठ्ठी बांधा, bytes पहा — मग शिक्का निवडा आणि वाचा

संपूर्ण धडा 02 वाचा →

3 🗄️ REST resources

फाइलिंग कपाटांतली नामे — संग्रह, ids, आणि पुन्हा-पुन्हा करायला सुरक्षित क्रियापदे.

🧒 सोप्या शब्दांत

Office मध्ये students नावाचे एक कपाट आहे, प्रत्येक विद्यार्थ्यासाठी एक drawer. तुम्ही 'कृपया getStudent नंबर 2' असे म्हणत नाही; तुम्ही /students/2 या drawer कडे बोट दाखवता आणि काय करायचे ते सांगता: वाचा, पूर्ण बदला, थोडे बदला किंवा काढून टाका. REST म्हणजे गोष्टींना नामाने ओळखणे आणि थोडेच ठरलेले क्रियाशब्द वापरणे, म्हणून प्रत्येक counter ओळखीचा वाटतो.

📖 नवे शब्दresource — API सांभाळते ती एक गोष्ट, जसे एक विद्यार्थीcollection — त्या सगळ्यांचे पूर्ण कपाट, जसे /studentsGET — फक्त वाचणे: दोनदा विचारले तरी काहीच बदलत नाहीPUT vs PATCH — PUT पूर्ण drawer बदलतो; PATCH फक्त एक भाग बदलतो
1🗄️ फाइल कपाटातली नामे — collection, तिचे खण/students — कपाट (collection)/students/1 · Aishwarya/students/2 · Katrina/students/3 · Dipikaकपाटावर:GETयादीPOSTखण जोडाएका खणावर /students/2:GETवाचाPUTसगळे बदलाPATCHभाग बदलाDELETEकाढाcollection अनेकवचनी · id एक खण निवडते · क्रियापद म्हणजे HTTP method, URL मधला शब्द कधीच नाही2🧭 नामे एकात एक — path मध्ये क्रियापद कधीच नाही/classes/3A/students/23A चे विद्यार्थी · मग त्यातला एक/getStudent?id=2✗ URL मध्ये क्रियापद/students/2/promote✗ कृती नाम म्हणूनPATCH /students/2 {"class":"3B"}✓ क्रियापद म्हणजे methodfilters, sorting आणि paging query string वर (L08): /students?class=3A3🔁 पुन्हा करायला सुरक्षित? — दोनदा केल्यावर काय होते ते क्रियापद सांगतेक्रियापदसुरक्षित (काहीच बदलत नाही)idempotent (दोनदा = एकदा)दोनदा पाठवा →GET✓✓200, 200 — तेच उत्तरPUT✗✓200, 200 — तीच अंतिम स्थितीDELETE✗✓204, मग 404 (किंवा 204) — अजूनही गेलेलेPATCH✗अवलंबूनमूल्य ठरवा: ✓ · "+1": ✗POST✗✗201, 201 — दोन Zoya नोंदल्या 💥म्हणूनच धडा 07 POST ला पावती क्रमांक देतो (Idempotency-Key) — आणि म्हणूनच retries फक्त ✓ ओळींवर सुरक्षित
⏪ आधी

/getStudent?id=2 सारख्या URLs मध्ये path मध्येच क्रियापद असायचे, म्हणून प्रत्येक API ची भाषा वेगळी आणि clients ना प्रत्येक पाठ करावी लागायची.

💡 काय

REST data ला कपाटातील नामे मानते: /students हा collection, /students/2 हा एक drawer, आणि HTTP methods ही क्रियापदे.

⚙️ कसे

GET /students यादी देते आणि POST नवीन जोडते; /students/2 वर GET वाचते, PUT पूर्ण बदलते, PATCH काही भाग बदलते आणि DELETE काढून टाकते.

🎯 का

थोड्याच, अंदाज करता येणाऱ्या URLs आणि क्रियापदांमुळे नवीन developer docs वाचण्याआधीच API चा आकार ओळखू शकतो.

🚀 पुढे

पुढे प्रत्येक drawer मधील माहितीला JSON schema चा ठरलेला form मिळतो (lesson 4), आणि lesson 13 मध्ये सातही methods येतात.

🧪 Try it here — क्रियापद आणि खण निवडा, दोनदा पाठवा, दोनदा काय होते ते पहा

संपूर्ण धडा 03 वाचा →

4 📋 JSON & schemas

प्रमाणित फॉर्म — प्रत्येक चिठ्ठीसाठी एकच आकार, OpenAPI कॅटलॉगमध्ये छापलेला.

🧒 सोप्या शब्दांत

प्रवेश form मध्ये ठरलेले रकाने असतात: नाव भरलेच पाहिजे, class 3A किंवा 3B च हवा, grade ऐच्छिक. File करण्याआधी clerk प्रत्येक रकाना तपासतो, आणि काही चुकले तर सगळ्या चुकांची यादी एकदमच देऊन form परत करतो. JSON म्हणजे form लिहिण्याची पद्धत; schema म्हणजे नियमांचा कागद: कोणते रकाने हवेत आणि त्यात काय चालते.

📖 नवे शब्दJSON — data नाव आणि किंमत अशा जोड्यांत लिहिण्याची सोपी text पद्धत: {"name": "Zoya"}schema — नियमांचा कागद: कोणते fields हवेत, कोणत्या प्रकारचे, कोणत्या किमती चालतातvalidation — काहीही save करण्याआधी form नियमांनुसार तपासणे400 — 'तुमच्या form मध्ये चुका आहेत' हा शिक्का, प्रत्येक चुकीच्या यादीसहOpenAPI — API च्या प्रत्येक slip आणि उत्तराचे वर्णन करणारी छापील यादी
1📋 प्रमाणित फॉर्म — प्रत्येक चिठ्ठीला एक आकार{ "name": "Zoya", "class": "3B", "grade": "A" }← आवश्यक · रिकामी नसलेली string← enum: 3A | 3B← ऐच्छिक · default "C"✅ validate()आवश्यक? योग्य प्रकार?परवानगी असलेले मूल्य?storage ला हात लावण्याआधी201 Created400 validation_failedapi/school_api.py validate_student(): सभ्यपणे नकार देणाऱ्या नऊ ओळी2❌ 400 — नकार प्रत्येक समस्या एकाच वेळी सांगतो{ "error": { "code": "validation_failed", "message": "2 problems with the form", "problems": [ {"field": "name", "problem": "required"}, {"field": "class", "problem": "must be 3A or 3B"} ] } }code: machines साठीmessage: माणसांसाठीproblems: प्रत्येक fieldला एक, सगळ्या एकदम —प्रत्येक चुकीला एक फेरीनाहीप्रत्येक route वर तोच error आकार (L07) — client handler एकदाच लिहितोचुकीच्या फॉर्मसाठी 422 की 400: एक निवडा आणि catalogue मध्ये छापा3📚 OpenAPI — प्रत्येक फॉर्म आणि प्रत्येक शिक्क्याचा छापील catalogueopenapi: 3.0.3paths: /v1/students/{id}: get: … responses: 200, 404components: schemas: Student: {name, class, grade} Error: {code, message, problems}api/openapi.yaml📖 rendered docsमाणसे वाचतात🐍 generated clientsसाधने code लिहितात🧪 contract tests + mockssmoke_test.sh ते तपासते (L12)एक फाइल, तीन वाचक · फॉर्म आधी इथे बदला, मग code —catalogue म्हणजे करार, code म्हणजे त्याची एक अंमलबजावणी
⏪ आधी

ठरलेल्या form शिवाय नाव नसलेले किंवा चुकीचा class असलेले data storage मध्ये शिरते आणि खूप नंतर गोष्टी बिघडवते.

💡 काय

Schema म्हणजे ठरलेला form: कोणते JSON fields आवश्यक, त्यांचे types आणि चालणाऱ्या किमती, हे सर्व OpenAPI catalogue मध्ये छापलेले.

⚙️ कसे

validate_student() storage आधी आवश्यक fields, types आणि 3A | 3B enum तपासते, मग 201 Created किंवा 400 validation_failed देते.

🎯 का

सर्व चुका एकाच वेळी सांगणाऱ्या 400 मुळे caller एकाच प्रयत्नात संपूर्ण form दुरुस्त करतो आणि तुमचे storage स्वच्छ राहते.

🚀 पुढे

हाच schema lesson 5 मधला चालणारा counter चालवतो आणि lesson 12 मध्ये docs, clients आणि contract tests तयार करतो.

🧪 Try it here — फॉर्म भरा आणि validate() ला सभ्यपणे नकार देऊ द्या

संपूर्ण धडा 04 वाचा →

5 🔬 API बांधा

Python च्या ~340 प्रामाणिक ओळींतले काउंटर — routes, validation, storage, plumbing.

🧒 सोप्या शब्दांत

Office counter च्या मागे पाहिले तर चार टेबल दिसतात: एक प्रत्येक slip योग्य व्यक्तीकडे पाठवतो, एक pass आणि form तपासतो, एक files सांभाळतो, आणि एक प्रत्येक उत्तरावर शिक्का मारून नोंद ठेवतो. हा धडा हे चारही साध्या Python च्या काहीशे ओळींत बांधतो, म्हणून पुढे प्रत्येक framework याच चार टेबलांचा shortcut वाटतो.

📖 नवे शब्दroute — /v1/students सारखा path तो हाताळणाऱ्या code शी जोडणारा नियमhandler — एका प्रकारच्या slip चे काम करणारे functionstorage — records जिथे राहतात: इथे साधी dictionary, पुढे databaseframework — FastAPI किंवा Express सारखा तयार संच, जो हीच टेबलं तुमच्यासाठी मांडतो
1🔬 counter चा छेद — चार थर, ~340 ओळी, dependencies शून्य1 🧭 routes — नामे → handlers/v1/students → do_GET / do_POST · /v1/students/{id} → do_GET / do_PUT / do_PATCH / do_DELETE2 ✅ validation + authvalidate_student(body) · authorized(headers) — काही काम करण्याआधी सभ्य नकार3 🗄️ storageSTUDENTS = {1: {"name": "Aishwarya", …}} — आज एक dict; Database शाळा ते टिकाऊ करते4 🔧 plumbingsend(status, body, headers) · error(code, message, hint) · X-Request-Id · एक log ओळ · ETag · rate bucketapi/school_api.py — एकदा वरून खाली वाचा; प्रत्येक framework (FastAPI, Express, Spring) नेमके हेच चार automate करते2🚶 एक चिठ्ठी थरांतून चालतेवाचाrouteauthvalidatestoragesendlogPOST /v1/students → ~1 ms मध्ये 201 · चुकीची key auth वर थांबते (401) · चुकीचा फॉर्म validate वर (400)प्रत्येक थांबा तोच error आकार परत देतो · काहीही झाले तरी log ओळ लिहिली जातेrequest id आत → request id बाहेर: trace (L12)3🧰 frameworks तेच चार automate करतातframeworkroutesvalidationplumbingFastAPI (Python)@app.getpydantic modelsआतचExpress (Node)app.get()zod / joimiddlewareSpring (Java)@GetMapping@Validfiltersहा repodo_GETvalidate_studentsend()आकार इथे शिका, मग framework ला ते तुमच्यासाठी टाइप करू द्या
⏪ आधी

Frameworks जादूसारखे वाटतात, म्हणून request अयशस्वी झाली की कोणता लपलेला थर तपासायचा ते कळत नाही.

💡 काय

शून्य dependencies असलेल्या साध्या Python च्या ~235 ओळींमधला चालणारा counter: routes, validation आणि auth, storage, आणि plumbing.

⚙️ कसे

Slip route नुसार do_GET किंवा do_POST कडे जाते, validate_student() आणि authorized() पार करते, STUDENTS dict वापरते आणि send() ने बाहेर पडते.

🎯 का

प्रत्येक framework (FastAPI, Express, Spring) नेमके हेच चार थर automate करतो, म्हणून ही एक file एकदा वाचली की सगळे समजतात.

🚀 पुढे

Database school STUDENTS dict ला टिकाऊ बनवते, आणि पुढचे lessons याच file मध्ये खरे auth, errors आणि paging जोडतात.

🧪 Try it here — चिठ्ठी निवडा आणि चार थरांतून चालवा, एका वेळी एक थांबा

संपूर्ण धडा 05 वाचा →

6 🪪 Auth

काउंटरवरचे हॉल पास — API keys, bearer tokens, OAuth, आणि कोण लिहू शकतो.

🧒 सोप्या शब्दांत

Notice board कोणीही वाचू शकतो, पण record बदलायचा असेल तर counter वर hall pass दाखवावा लागतो. Pass नसेल तर clerk विचारतो 'तुम्ही कोण?' (401). Pass आहे पण याची परवानगी नाही, तर clerk म्हणतो 'मी तुम्हाला ओळखतो, पण नाही' (403). Auth म्हणजे विचारणारा कोण आणि त्याला काय करण्याची परवानगी आहे हे counter ला कळण्याची पद्धत.

📖 नवे शब्दauthentication — तुम्ही कोण आहात हे सिद्ध करणेauthorization — तुम्हाला काय करण्याची परवानगी आहे ते ठरवणेAPI key — एखाद्या program ला दिलेला लांब गुप्त pass401 — pass नाही, किंवा counter ओळखत नाही: तुम्ही कोण?403 — तुम्ही कोण ते माहीत आहे, पण हे करण्याची परवानगी नाही
1🪪 दोन खिडक्या — वाचन उघडे, लिहायला पास हवा🔓 वाचन — GETइथे पास लागत नाहीसार्वजनिक data,rate-limited (L10)🪪 लिहिणे — POST/PUT/DELETEपास दाखवा:X-API-Key: hall-pass-123validation आधी तपासलेलापास नाही401 unauthorized — तुम्ही कोण?चुकीचा पास403 forbidden — तुम्हाला ओळखतो, आणि नाहीhall-pass-123201 created ✓2🎫 तीन प्रकारचे पास🔑 API keymachine → machine, दीर्घायुषीX-API-Key: … · सगळ्यात साधा · URL पासून दूर ठेवा🎟️ bearer token / JWTuser चा सही केलेला पास, संपतोAuthorization: Bearer eyJ… · सहीने तपासलेला🤝 OAuth 2 / OIDCसोपवलेला: "हे app माझे calendar वाचू शकते"AWS / CI/CD चा badge · scopes · refresh tokensधडा 14 सातही पद्धती आणि OAuth grant प्रकार काढतो3🎯 least privilege — आणि JWT म्हणजे नेमके कायप्रत्येक app ला एक key, तिच्या कामापुरती (read / write) · फिरवा · URL किंवा log मध्ये कधीच नाहीफुटलेली read key वाचते; फुटलेली admin key शाळा पुन्हा लिहितेJWT म्हणजे टिंबांनी जोडलेले तीन base64 तुकडे:header{"alg":"HS256"}.payload{"sub":"katrina","exp":1780000000,"scope":"read"}.सहीHMAC(header.payload, secret)counter गुपिताने सही तपासतो आणि exp पाहतो — प्रत्येक request ला database lookup नाही · payload कोणीही वाचू शकते: त्यात गुपिते कधीच नको
⏪ आधी

Pass तपासणी नसेल तर counter पर्यंत पोहोचणारा कोणीही विद्यार्थी जोडू, बदलू किंवा काढू शकला असता.

💡 काय

Auth म्हणजे hall pass: GET ने वाचणे मोकळे असते, पण POST, PUT किंवा DELETE ने लिहिताना वैध pass दाखवावा लागतो.

⚙️ कसे

Counter validation आधी X-API-Key तपासतो: pass नसेल तर 401, चुकीचा pass असेल तर 403, आणि hall-pass-123 ला 201 created मिळते.

🎯 का

कोणी काय लिहिले ते कळते आणि बाकीच्यांना नकार देता येतो, आणि 401 व 403 मधला फरक caller ला नेमकी चूक सांगतो.

🚀 पुढे

खऱ्या teams मध्ये API keys पुढे bearer tokens, JWT आणि OAuth 2 / OIDC बनतात, आणि lesson 14 मध्ये प्रत्येक पद्धत येते.

🧪 Try it here — लिहिण्याच्या खिडकीवर पास दाखवा — आणि JWT decode करा

संपूर्ण धडा 06 वाचा →

7 ⚠️ चुका & idempotency

कारणासह नम्र नकार — आणि पावती क्रमांक, म्हणजे पुन्हा-प्रयत्न कधीच दुहेरी नोंद करत नाहीत.

🧒 सोप्या शब्दांत

Office एखादी slip स्वीकारू शकत नसेल तर प्रत्येक वेळी त्याच नम्र पद्धतीने सांगते: एक छोटा code, एक संदेश आणि पुढे काय करायचे याची सूचना. आणि form दिला पण उत्तरच आले नाही, तर तुम्ही तोच पावती नंबर घालून तो परत पाठवता, म्हणजे office तो एकदाच file करते. तो पावती नंबर म्हणजे Idempotency-Key.

📖 नवे शब्दerror code — not_found सारखा ठरलेला शब्द, जो programs तपासू शकतात4xx — तुमच्या slip मध्ये अडचण आहे: पुन्हा पाठवण्याआधी ती दुरुस्त करा5xx — office चीच चूक: थोड्या वेळाने पुन्हा करा, दर वेळी थोडे जास्त थांबूनIdempotency-Key — पावती नंबर, ज्यामुळे पुन्हा आलेली slip एकदाच file होते
1⚠️ एकच error shape, नेहमी{ "error": { "code": "not_found", "message": "no student 9", "hint": "GET /v1/students lists them", "problems": [] } }code: स्थिर शब्दज्यावर switch करताmessage: दाखवायलाhint: पुढे काय करायचेproblems: प्रत्येक field ला (L04)4xxचिठ्ठी दुरुस्त करा — आंधळेपणाने retry नको5xxआमची चूक — नंतर retry, backoff नेप्रत्येक route, प्रत्येक अपयश: तोच आकार — client एक handler, एकदाच लिहितो2🧾 Idempotency-Key — पावती क्रमांकclientकाउंटरPOST /v1/students + Idempotency-Key: abc123201 Created — Zoya एकदा नोंदली✗ network उत्तर पाडतेretry: तीच चिठ्ठी, तीच key201 (जपलेले उत्तर) + Idempotent-Replay: trueएक Zoya, दोन नाही — key म्हणजे पावती क्रमांकत्याच key सह वेगळा body → 409 conflict · keys ~24 h जगतात · api/school_api.py त्या dict मध्ये ठेवते3🔁 retry चे ठोकताळे — backoff आणि jitter सहतुम्हाला मिळालेकरा429 · 502 · 503 · 504 · timeoutretry — Retry-After किंवा backoff नंतर500एकदा retry, मग alarm400 · 401 · 403 · 404 · 409थांबा — चिठ्ठी दुरुस्त कराkey शिवाय POSTकधीच retry नको — दोनदा नोंद होईलbackoff 1 s, 2 s, 4 s … + jitter1 s ± jitter2 s ± jitter4 s ± jitterjitter हजार retry करणाऱ्या clients ना पसरवते म्हणजे तेसगळे एकाच सेकंदाला टकटक करत नाहीत · request id दोन्ही बाजूंनी log करा
⏪ आधी

प्रत्येक route वेगळ्या प्रकारे fail व्हायचा, आणि उत्तर हरवल्यावर पुन्हा पाठवलेला POST तोच विद्यार्थी दोनदा नोंदवू शकायचा.

💡 काय

प्रत्येक failure साठी एकच error आकार (code, message, hint, problems), आणि पावती क्रमांकासारखी काम करणारी Idempotency-Key.

⚙️ कसे

POST /v1/students सोबत Idempotency-Key: abc123 जाते; उत्तर हरवले तर त्याच key ने पुन्हा पाठवल्यावर जतन केलेले 201 उत्तर परत येते.

🎯 का

Clients एकदाच एक error handler लिहितात, 4xx म्हणजे slip दुरुस्त करा आणि 5xx म्हणजे नंतर retry करा हे कळते, आणि दुहेरी नोंद होत नाही.

🚀 पुढे

Backoff सह retry ची सवय lesson 10 मधल्या सभ्य client मध्ये वाढते, आणि कोणते methods idempotent आहेत ते lesson 13 दाखवतो.

🧪 Try it here — पावती क्रमांकासह आणि त्याशिवाय Zoya नोंदवा, उत्तर पाडा, retry करा

संपूर्ण धडा 07 वाचा →

8 📚 Pagination & filtering

'पुढचे 20, कृपया' — cursors, filters आणि sorting, कोणालाही न गमावता.

🧒 सोप्या शब्दांत

ग्रंथपाल सगळी cards एकदम देत नाही; तुम्ही पुढची 20 मागता. 'मी पाहिलेल्या शेवटच्या नंतरची' असे सांगणारी खूण असेल तर, तुम्ही वाचत असताना नवीन विद्यार्थी आला तरी कोणी सुटत नाही किंवा दोनदा दिसत नाही. त्या खुणेला cursor म्हणतात, आणि छोट्या पानांत मागणे म्हणजे pagination.

📖 नवे शब्दpagination — लांब यादी छोट्या पानांत देणेlimit — एका पानात किती items पाठवायचेcursor — खूण: 'याच्या नंतरचे द्या'offset — 'पहिले N सोडा': यादी बदलली तर items दोनदा येऊ शकतात किंवा सुटू शकतातfilter — फक्त जुळणारे items मागणे, जसे class 3A
1📚 "पुढचे दोन, please" — cursor ने चालणे1 Aishwarya2 Katrina3 Dipika4 Meera5 RohanGET /v1/students?limit=2items: [1, 2] · next_cursor: 2…?limit=2&cursor=2items: [3, 4] · next_cursor: 4…?limit=2&cursor=4items: [5] · next_cursor: null"मी पाहिलेल्या शेवटच्यानंतर": inserts मध्येही स्थिर, जलद (id वर index)null म्हणजे शेवट — client पाने कधीच मोजत नाही2📄 offset विरुद्ध 🔖 cursor — scroll मध्येच एक ओळ येतेoffset ("पान 2 = 2 वगळा")12✚345पान 2 = [✚, 3] → 3 दोनदा, 4 नंतरcursor ("id 2 नंतर")12✚3452 नंतर = [3, 4] ✓ कोणीच हरवले नाहीoffsetcursorinserts मध्ये स्थिर✗✓खोल पानेहळूजलदपान 7 वर उडी✓✗खरे APIs cursor म्हणून अपारदर्शक token देतात — default निवड3🧭 गाळा, मग लावा, मग पाने — नेहमी याच क्रमानेGET /v1/students?class=3A&sort=name&limit=2सगळे 5AishwaryaKatrinaDipikaMeeraRohanclass=3AAishwaryaKatrinaDipikasort=nameAishwaryaDipikaKatrinalimit=2AishwaryaDipikaआधी पाने केली तर filterपान रिकामे करते · शेवटी sortकेले तर पाने हलतात · cursor नेतोच filter आणि sort वाहून न्यावाpython3 api/client.py null पर्यंत cursor चालते — वाचा, मग क्रम मुद्दाम मोडा
⏪ आधी

शाळा वाढली की सर्व विद्यार्थी एकदम मागणे मंद होते, आणि नवीन rows आल्यावर page numbers मुळे rows सुटतात किंवा दोनदा येतात.

💡 काय

Pagination निकाल थोडे-थोडे, filters आणि sorting सह देते; cursor म्हणजे मी शेवटचा पाहिलेल्या नंतरचे.

⚙️ कसे

GET /v1/students?limit=2 items [1, 2] आणि next_cursor 2 देते; मग cursor=2 ने [3, 4] मिळतात, आणि next_cursor null म्हणजे शेवट.

🎯 का

नवीन rows आल्या तरी cursor स्थिर राहतो, त्यामुळे कोणी सुटत नाही किंवा दोनदा दिसत नाही, आणि id वरच्या index मुळे शोध जलद होतो.

🚀 पुढे

Apps मधल्या लांब याद्या नेमक्या अशाच scroll होतात, आणि पुढचा lesson हे clients न मोडता उत्तरे कशी वाढवायची ते दाखवतो.

🧪 Try it here — cursor ने यादी चाला — मग scroll मध्येच विद्यार्थी घाला आणि offset शी तुलना करा

संपूर्ण धडा 08 वाचा →

9 🔢 Versioning

जुने फॉर्म न फेकता नवे फॉर्म — additive बदल, deprecation, sunset.

🧒 सोप्या शब्दांत

शाळा आपल्या form मध्ये 'house' हा नवीन रकाना जोडते. जुने forms तरीही चालतात, कारण ज्यांना तो नको ते त्याकडे दुर्लक्ष करतात. पण रकान्याचे नाव बदलले तर सगळ्यांचे जुने forms बिघडतील, म्हणून शाळा नवीन form नंबर v2 छापते आणि काही काळ v1 पण स्वीकारत राहते. Versioning म्हणजे कालच्या callers ना न बिघडवता API बदलणे.

📖 नवे शब्दadditive change — असे नवीन काही जोडणे, ज्याकडे जुने callers सुरक्षितपणे दुर्लक्ष करू शकतातbreaking change — जुने callers ज्यावर अवलंबून आहेत त्याचे नाव बदलणे किंवा ते काढणे/v2 — path मधला नवीन version नंबर, /v1 सोबतच चालणाराdeprecation — हे जुने version जाणार आहे अशी सूचनाsunset — जुने version खरोखर बंद होण्याची तारीख
1➕ जोडणे = सुरक्षित — जुने clients नव्याकडे दुर्लक्ष करतात{ "id": 2, "name": "Katrina", "class": "3A", "house": "red" }/v1 — तोच pathजुना clientname, class वाचतो ✓house कडे पाहतच नाहीसुरक्षित: field जोडा · endpoint जोडा · clients दुर्लक्ष करतील असे enum मूल्य जोडाऐच्छिक parameter जोडा · नियम सैल करावचन: काल चालणारी चिठ्ठी आजही चालते2💥 मोडणारे → नवा फॉर्म क्रमांक: /v2{ "id": 2, "name": "Katrina", "className": "3A" }"class" चे नाव बदललेजुना client✗ student["class"] → KeyError/v1/studentsजुना फॉर्म देत राहते/v2/studentsनवा फॉर्म — शेजारी शेजारीमोडणारे: field चे नाव बदलणे / काढणे · type बदलणे · नियम कडक करणे · error code बदलणे3🗓️ फॉर्म सभ्यपणे निवृत्त — headers, एक तारीख, आणि आकडेHTTP/1.1 200 OKDeprecation: trueSunset: Sat, 28 Feb 2027 00:00:00 GMTLink: </v2/students>; rel="successor-version"दिवसाला v1 चिठ्ठ्याSepOctNovDecJanFeb1 जाहीर करा: headers + टीप2 प्रत्येक आवृत्तीचा वापर पहा3 v1 तेव्हाच काढा जेव्हाcounter ला v1 चिठ्ठ्या दिसत नाहीत4 तोपर्यंत दोन्ही चालवाजुनी आणि नवी चिठ्ठी शेजारी दाखवणारी migration टीप header पेक्षा मोलाची · आवृत्ती path मध्ये (/v2) किंवा header मध्ये — एक निवडा
⏪ आधी

class चे className असे field चे नाव बदलले की प्रत्येक जुना client रातोरात KeyError ने मोडतो.

💡 काय

Versioning मुळे API वाढू शकते: भर घालणारे बदल /v1 मध्येच राहतात, आणि मोडणाऱ्या बदलांना /v2 हा नवा form क्रमांक शेजारी मिळतो.

⚙️ कसे

house field जोडणे सुरक्षित, कारण जुने clients त्याकडे दुर्लक्ष करतात; class चे नाव बदलणे /v2/students मध्ये जाते आणि /v1/students चालूच राहते.

🎯 का

वचन टिकते: काल चाललेली slip आजही चालते, म्हणून clients आपल्या सोयीने upgrade करू शकतात.

🚀 पुढे

जुन्या versions ना deprecation सूचना आणि sunset तारीख मिळते, आणि lesson 12 चे contract tests चुकून झालेले मोडणारे बदल पकडतात.

🧪 Try it here — फॉर्ममध्ये बदल सुचवा — जोडणारा की मोडणारा?

संपूर्ण धडा 09 वाचा →

10 ⏱️ Rate limits & caching

काउंटरवरची रांग — 429, Retry-After, ETags, timeouts आणि backoff.

🧒 सोप्या शब्दांत

एकाच app ने एकदम 100 slips पाठवल्या तर बाकी सगळ्यांना थांबावे लागते. म्हणून प्रत्येक app ला दर 10 सेकंदाला 20 tokens ची बादली मिळते; 21 वी slip ऐकते 'कृपया थांबा' (429). आणि तुमच्याकडे notice ची प्रत आधीच असेल, तर तुम्ही विचारता 'ती बदलली का?', आणि office पूर्ण notice पुन्हा देण्याऐवजी फक्त 'नाही, तुमची प्रत ठीक आहे' (304) म्हणू शकते.

📖 नवे शब्दrate limit — एक caller ठराविक वेळेत किती requests पाठवू शकतो याची मर्यादा429 — 'खूप झाले, थोडे थांबा' असा शिक्काRetry-After — पुन्हा प्रयत्न करण्याआधी किती सेकंद थांबायचेETag — तुमच्या प्रतीवरचा version tag, ती बदलली का हे विचारण्यासाठीbackoff — प्रत्येक अपयशी प्रयत्नानंतर जास्त थांबणे: 1, 2, मग 4 सेकंद
1⏱️ counter वरची रांग — 10 सेकंदांत 20 चिठ्ठ्याबादली: 20 tokens, दर 10 s ने भरतेचिठ्ठी 21 →429 rate_limitedRetry-After: 10😌 सभ्य clienttimeout = 3 s — कोणीच कायम थांबत नाहीफक्त 429 / 5xx वर retry · backoff 1, 2, 4 s + jitter · मग सोडाप्रत्येक app ला एक key, म्हणजे एक गोंगाटी app बाकीच्यांना उपाशी ठेवू शकत नाहीapi/school_api.py: प्रत्येक key ला बादल्यांचा dict — बारा ओळी2🧾 ETag — "माझी प्रत अजून चांगली आहे?"clientकाउंटरGET /v1/students/2200 + ETag: "0e9a" + Cache-Control: private, max-age=3030 s: client counter ला पूर्ण वगळतोGET … If-None-Match: "0e9a"304 Not Modified — body नाही, तुमची प्रत अजून चांगलीPATCH /v1/students/2 If-Match: "0e9a"→ कोणी आधी बदलले असेल तर 412 (update हरवत नाही)3🧊 तिन्ही एकत्र — आणि caches कुठे बसतातcachingकमी चिठ्ठ्या: client, CDN आणि gateway सगळे Cache-Control पाळतातrate limitsन्याय्य रांग: कोसळलेल्या counter ऐवजी 429 + Retry-Aftertimeoutsकोणीच कायम थांबत नाही: client सोडतो, log करतो, backoff ने retry करतोclient cacheCDNgateway → counterprivate = फक्त client ठेवू शकतो · public = CDN ही · no-store = कधीच नाही · max-age = किती वेळ · तिन्ही, नेहमी
⏪ आधी

एक गोंगाट करणारे app counter वर गर्दी करून बाकीच्यांना उपाशी ठेवू शकायचे, आणि clients न बदललेले data पुन्हा पुन्हा आणायचे.

💡 काय

Rate limits प्रत्येक key ला 10 सेकंदात 20 slips पर्यंत मर्यादा घालतात, आणि ETags मुळे client माझी प्रत अजून चांगली आहे का असे विचारू शकतो.

⚙️ कसे

21 वी slip 429 आणि Retry-After: 10 मिळवते, आणि काही बदलले नसेल तर If-None-Match: "0e9a" असलेल्या GET ला body शिवाय 304 Not Modified मिळते.

🎯 का

Counter न्याय्य आणि जलद राहतो, आणि 3 s timeout व 1, 2, 4 s backoff वापरणारे सभ्य clients परिस्थिती न बिघडवता सावरतात.

🚀 पुढे

Production मध्ये gateway आणि CDN हे नियम प्रत्येक counter साठी लागू करतात (lesson 12), आणि 429 तपासणी smoke test मध्ये येते.

🧪 Try it here — चिठ्ठ्या भराभर द्या आणि रांग गाठा — मग ETag सह दोनदा आणा

संपूर्ण धडा 10 वाचा →

11 🔀 REST च्या पलीकडे

GraphQL, gRPC, webhooks आणि events — जेव्हा काउंटर तुम्हाला परत कॉल करतो.

🧒 सोप्या शब्दांत

प्रत्येक कामाला एकाच प्रकारचा counter जमत नाही. कधी एका मोठ्या form मधली फक्त काही उत्तरे हवी असतात (GraphQL). दिवसभर बोलणाऱ्या दोन offices ना आपसात जलद खाजगी line हवी असते (gRPC). आणि कधी तुम्ही पुन्हा पुन्हा विचारण्याऐवजी, काही घडले की office नेच तुम्हाला कळवावे असे वाटते; त्याला webhook म्हणतात.

📖 नवे शब्दGraphQL — एकच पत्ता, जिथे तुम्हाला हवे तेवढेच fields मागताgRPC — services नी एकमेकांना call करण्याची जलद, काटेकोर types असलेली पद्धतwebhook — काही घडले की server तुमच्या URL ला call करतोevent — 'हे आत्ताच घडले' असे सांगणारा संदेश
1🔀 counter चालवण्याचे चार मार्ग — आकार बोलावणाऱ्यावर🗄️ RESTनामे + क्रियापदे, JSON, cache होणारे — हा कोर्स🧩 GraphQLएक endpoint; नेमकी हवी ती fields मागा⚡ gRPCtyped करार (.proto), binary, streaming📣 webhookscounter तुम्हाला परत बोलावतो: तुमच्या URL वर POSTGET /v1/students/2→ 200 {id, name, class}प्रत्येक screen ला तोच आकारURL ने cache · publicPOST /graphql{ student(id:2) { name grades { subject } } }अनेक screens, एक endpointजास्त किंवा कमी आणणे नाहीservice School { rpc GetStudent (Id) returns (Student); }service ↔ service, बोलके, जलदHTTP/2 + protobufतुमचा URLPOST"grade बदलला" → तुमचा handlerapi/webhook_receiver.py: 12 ओळीसगळे HTTP वर जातात (gRPC HTTP/2 वर) — Networking शाळेचे पाकीट, आत चार वेगळी पत्रे2🧭 निवड — आणि webhooks जे बदलतात तेसार्वजनिक + cache होणारेRESTएक UI, अनेक आकारGraphQLअंतर्गत, बोलके, typedgRPC"कधी ते सांगा"webhooks / eventsदर 5 s ला polling ✗घडते तेव्हा एक webhook ✓queue वरचे events (SQS, Kafka) आणि SSE तीच कल्पना मध्यस्थासह · webhook receiver idempotent हवा (L07): तोच event दोनदा येऊ शकतो
⏪ आधी

फक्त REST असेल तर phone screen गरजेपेक्षा जास्त fields आणते, services JSON मध्ये हळू बोलतात, आणि clients बातमीसाठी सतत विचारत राहतात.

💡 काय

REST ची भावंडे: GraphQL नेमके fields मागते, gRPC typed binary contracts वापरते, आणि webhooks मध्ये counter तुम्हाला उलट बोलावतो.

⚙️ कसे

POST /graphql फक्त हवे तेच fields मागते, gRPC HTTP/2 + protobuf वरून rpc GetStudent बोलवतो, आणि webhook तुमच्या URL वर POST करतो.

🎯 का

आकार caller नुसार ठरतो, म्हणून प्रत्येक कामावर एकच counter लादण्याऐवजी बोलणाऱ्याला साजेशी शैली निवडता येते.

🚀 पुढे

Lesson 15 प्रत्येक API प्रकाराला कुटुंबांत बसवतो, streams आणि queues पासून network ला कधीच न शिवणाऱ्या APIs पर्यंत.

🧪 Try it here — बोलावणारा सांगा — शैली मिळवा; मग GraphQL उत्तर घडवा

संपूर्ण धडा 11 वाचा →

12 🚪 चाचण्या, docs & gateway

Contract tests, छापलेला कॅटलॉग, आणि प्रत्येक काउंटरसमोरचे शाळेचे गेट.

🧒 सोप्या शब्दांत

शाळा एक यादी छापते: counter कोणत्या slips घेतो आणि कोणते शिक्के देतो. प्रत्येक बदलानंतर एक तपासनीस test slips देऊन पाहतो की counter अजूनही यादीप्रमाणेच वागतो; काही जुळले नाही तर build लाल होते. आणि कोणी counter पर्यंत पोहोचण्याआधी शाळेच्या प्रवेशद्वारावरचे एकच gate pass तपासते आणि रांग व्यवस्थित ठेवते.

📖 नवे शब्दcontract test — खरे API अजूनही यादीत लिहिल्याप्रमाणे उत्तर देते का ते तपासणेOpenAPI — प्रत्येक route आणि उत्तराचे वर्णन करणारी यादीची file (openapi.yaml)API gateway — सगळ्या counters साठी pass, मर्यादा आणि routing सांभाळणारे एक पुढचे gateCI — प्रत्येक push वर tests चालवणारा robot
1🧪 contract tests — प्रत्येक चिठ्ठी, प्रत्येक शिक्का, CI मध्येopenapi.yaml200 · 201 · 400401 · 404 · 429↔smoke_test.sh12 नावाच्या checksexit 0 किंवा 1GET /v1/students → 200✓POST bad form → 400 + problems✓POST no key → 401✓GET /v1/students/9 → 404✓21st slip → 429 + Retry-After✓प्रत्येक push वर चालते(CI/CD शाळा)शिक्का बदलला →build लाल होतेcatalogue म्हणजे करार; test सिद्ध करते की counter तो पाळतो2📚 एक catalogue, त्यातून तीन गोष्टी तयारopenapi.yamlpaths · schemaserrors · examples📖 rendered docsप्रत्येक route ला पान, try-it-out बटणे🐍 generated clientschool_client.get_student(2)🎭 mock servercounter अस्तित्वात येण्याआधी UI शाळा त्यावर बांधतेcode पासून दूर गेलेले docs नसण्यापेक्षा वाईट — generate करा, हाताने कधीच नाही3🚪 शाळेचे दार — प्रत्येक counter पुढे एक दारएक appbrowserएक भागीदार🚪 API gatewayauth · rate limit · routingTLS · logs · X-Request-IdAWS API Gateway (L25) · Ingress▣students counter▣grades counter▣homework countergateway 7f3c2a POST /v1/students 201 4 msstudents 7f3c2a validate ok · stored id=6students 7f3c2a 201 1 ms← प्रत्येक ओळीवर तोच X-Request-Id: traceobservability: प्रत्येक चिठ्ठीला एक log ओळ · route नुसार latency histograms आणि error rate · counter on-call जाण्याआधीची checklist: p95, 5xx rate, 429 rate, सगळ्यात हळू routes
⏪ आधी

Docs code पासून दूर जायचे, बदललेला status code कोणाच्या लक्षात यायचा नाही, आणि प्रत्येक counter keys व limits एकटाच सांभाळायचा.

💡 काय

openapi.yaml catalogue हेच contract: tests ते सिद्ध करतात, docs आणि clients त्यातून तयार होतात, आणि gateway शाळेच्या दारावर पहारा देतो.

⚙️ कसे

smoke_test.sh प्रत्येक push वर 12 नावे दिलेल्या तपासण्या चालवतो, जसे key शिवाय POST ला 401 आणि 21 व्या slip ला 429, मग 0 किंवा 1 ने संपतो.

🎯 का

शिक्का बदलला तर users ना कळण्याआधीच build लाल होतो, आणि docs नेहमी प्रत्यक्ष चालणाऱ्या counter शी जुळतात.

🚀 पुढे

Lesson 16 हे API tests च्या नऊ प्रकारांपर्यंत वाढवतो, आणि CI/CD school ते प्रत्येक push वर आपोआप चालवते.

🧪 Try it here — मुद्दाम एक शिक्का मोडा आणि contract tests चालवा — मग एक request id दारातून पाठलाग करा

संपूर्ण धडा 12 वाचा →

13 🔧 प्रत्येक REST method

सात शिक्के — GET, HEAD, OPTIONS, POST, PUT, PATCH, DELETE — आणि त्यांना वेगळे करणारे तीन शब्द: safe, idempotent, cacheable.

🧒 सोप्या शब्दांत

Counter वरच्या काही क्रिया फक्त पाहतात, जसे notice वाचणे; शंभरदा केल्या तरी काहीच बदलत नाही. काही कितीही वेळा केल्या तरी शेवट तोच होतो, जसे grade A करणे. काही प्रत्येक वेळी नवीन काहीतरी बनवतात, जसे नवीन form file करणे. GET, POST, PUT आणि बाकीचे तीन शब्दांनी वेगळे ओळखले जातात: safe, idempotent आणि cacheable.

📖 नवे शब्दsafe — फक्त वाचते: काहीच बदलत नाहीidempotent — दोनदा केले तरी शेवट एकदा केल्यासारखाचcacheable — उत्तर काही काळ जपून पुन्हा वापरता येतेHEAD — GET सारखेच, पण फक्त headers परत येतात, body नाहीOPTIONS — counter कोणते methods चालू देतो ते विचारते

📋 तक्ता — सात methods, एक पडदा

आधी Safe आणि Idempotent स्तंभ वाचा: काय पुन्हा पाठवता येते, cache होते, आधीच आणले जाते आणि preflight होते हे ते ठरवतात. चित्राकडे उडी मारायला method वर क्लिक करा.

Methodकाय करतेSafeIdempotentRequest bodyResponse bodyCacheableयश🏫 काउंटरवर
GETएक resource किंवा यादी वाचा✅✅❌ (query string)✅ प्रतिरूप✅200 · 304"विद्यार्थी 2 ची फाइल पाहू का?"
HEADफक्त GET चे headers✅✅❌❌✅200 · 304"फाइल आहे का? बदलली का?"
OPTIONSपरवानगी असलेल्या methods ची यादी · CORS preflight✅✅❌❌ (headers)✅ (Max-Age)204 · 200"इथे मला काय विचारायची परवानगी आहे?"
POSTनवे बनवा · किंवा एक कृती करा❌❌ (Idempotency-Key असेल तरच)✅✅ नवे resource❌201 + Location · 200 · 202"कृपया एक नवा विद्यार्थी दाखल करा"
PUTसंपूर्ण resource बदला❌✅✅ सर्व fields✅ किंवा रिकामे❌200 · 204 · 201 (upsert)"फाइल 2 च्या जागी हे ठेवा"
PATCHresource चा भाग बदला❌✅ merge-patch साठी✅ बदल✅ किंवा रिकामे❌200 · 204"फाइल 2 वर फक्त grade बदला"
DELETEresource काढून टाका❌✅ (स्थितीनुसार)❌❌ सहसा❌204 · 202 · 200"फाइल 5 कपाटातून काढा"

🧠 तीन शब्द

Safe — विनंती server वर काहीच बदलत नाही. Crawler, आधीच आणणारा browser किंवा refresh दाबणारा घाबरलेला वापरकर्ता कधीच नुकसान करू शकत नाही. GET, HEAD, OPTIONS.
Idempotent — N वेळा पाठवल्यावर तीच स्थिती जी एकदा पाठवल्यावर. Timeout नंतरचे पुन्हा-प्रयत्न फुकट. GET, HEAD, OPTIONS, PUT, DELETE — आणि POST फक्त Idempotency-Key जोडल्यावर.
Cacheable — उत्तर browser, CDN किंवा proxy जपून पुन्हा वापरू शकतो. प्रत्यक्षात फक्त GET आणि HEAD, Cache-Control ने नियंत्रित आणि ETag ने तपासलेले (धडा 10).
का महत्त्वाचे: internet वरचा प्रत्येक मध्यस्थ — browsers, CDN, proxies, retry libraries — या शब्दांवर विश्वास ठेवतो. पुसणारा GET, किंवा idempotent नसलेला PUT, त्या सगळ्यांना एकाच वेळी मोडतो.

तुटक बाण म्हणजे एकेक संदेश. प्रत्येक चित्र काउंटर खरोखर स्वीकारते ती विनंती आणि api/methods_demo.sh ला मिळणारे नेमके उत्तर दाखवते.

GET
clientकाउंटरGET /v1/students/2 (body नाही — गाळण्या ?query मध्ये)200 · ETag "72bc…" · Cache-Control: private, max-age=30SAFE: काहीच बदलत नाही · IDEMPOTENT: दोनदा तेच उत्तर · CACHEABLE: browser आणि CDN जपू शकतातIf-None-Match: "72bc…" → 304 Not Modified, no body (lesson 10)
वाचा. बहुतांश internet फक्त हीच method वापरते. कधीच काही बदलत नाही, म्हणून पुन्हा पाठवता, cache करता, आधीच आणता आणि bookmark करता येते. गाळण्या, क्रम आणि पाने query string मध्ये प्रवास करतात, body मध्ये कधीच नाही.
HEAD
clientकाउंटरHEAD /v1/students/2200 · ETag "72bc…" · Content-Length: 58 · — no body —GET जे headers पाठवेल तेच, आणि बाकी काही नाही · safe · idempotent · cacheable"आहे का? बदलले का? केवढे?" — फक्त लखोट्याच्या किमतीत
Body शिवाय GET. तोच status, तेच headers, शून्य bytes payload. दुवे तपासणारे, cache तपासणारे आणि download managers यावर जगतात. GET बनवला की HEAD जवळजवळ फुकट मिळतो; तो विसरू नका.
OPTIONS
clientकाउंटरOPTIONS /v1/students/2 · Origin: https://board.school204 · Allow: GET, HEAD, PUT, PATCH, DELETE, OPTIONS"इथे मी काय करू शकतो?" — आणि cross-origin लिहिण्याआधी browser पाठवतो ते CORS preflightते cache करा (Access-Control-Max-Age) नाहीतर फलकावरच्या प्रत्येक लिहिण्याला दोन फेऱ्या लागतात
इथे मी काय करू शकतो? एका URL साठी परवानगी असलेल्या methods ची यादी देते, आणि browser च्या CORS preflight चे कामही करते: cross-origin लिहिण्याआधी browser प्रथम OPTIONS विचारतो आणि उत्तराने परवानगी दिली तरच पुढे जातो. UI शाळेचा धडा 11 हा या गोष्टीचा दुसरा अर्धा भाग.
POST
POST /v1/students · {name: "Zoya", class: "3B"}201 Created · Location: /v1/students/6POST /v1/students · तोच फॉर्म पुन्हा201 Created · Location: /v1/students/7 ← दुसरा विद्यार्थी!idempotent नाही: server id निवडतो · Idempotency-Key पुन्हा-प्रयत्न सुरक्षित करतो (धडा 07)
नवे बनवा — किंवा एक कृती करा. Server नवी URL निवडतो आणि Location सह 201 देतो. पुन्हा केल्यास परिणाम पुन्हा होतो, म्हणून पुन्हा-प्रयत्नांना idempotency key लागते. नामे नसलेल्या कृतींचेही हेच घर: POST /students/6/promote.
PUT
PUT /v1/students/2 · {name, class, grade} — सर्व fields200 · संपूर्ण विद्यार्थी (किंवा 204 No Content)PUT /v1/students/2 · {grade: "A"} — फक्त एक field400 · problems: name आवश्यक, class आवश्यकREPLACE: तुम्ही जे पाठवता तेच उरते · दोनदा = एकदा · client URL ठरवतो · If-Match बदलांचे रक्षण करते
संपूर्ण गोष्ट बदला. Client URL ठरवतो आणि संपूर्ण प्रतिरूप पाठवतो; आधी जे होते ते जाते. पुन्हा केल्यास आणखी काही बदलत नाही. अर्धवट body म्हणजे वेशांतर केलेला bug: एकतर 400, नाहीतर fields गुपचूप रिकामी.
PATCH
PATCH /v1/students/2 · {grade: "A"} — फक्त जे बदलते ते200 · एकत्र केलेला विद्यार्थीPATCH /v1/students/2 · {nickname: "Situ"}400 · problems: nickname हे विद्यार्थ्याचे field नाहीPARTIAL: merge-patch किंवा json-patch operations · एकत्र केलेला निकाल तपासा · अनोळखी field → 400
त्याचा भाग बदला. फक्त बदलणारी fields पाठवा; server एकत्र करतो आणि निकाल तपासतो. Merge-patch idempotent आहे; JSON-Patch operations ची यादी असेलच असे नाही. अनोळखी fields मोठ्याने नापास व्हायला हव्यात, नाहीतर clients ना वाटेल त्यांनी जे जपले ते जपलेच नाही.
DELETE
DELETE /v1/students/5 · X-API-Key: …204 No ContentDELETE /v1/students/5 — पुन्हा204 (तीच स्थिती: गेला) — इथे 404 ही प्रामाणिकस्थितीनुसार idempotent · नंतर GET → 404 · unsafe, म्हणून हॉल पास लागतो · रांगेत असेल तर 202
काढून टाका. एक DELETE किंवा दहा, विद्यार्थी गेलेला असतो — idempotent म्हणजे हेच. दुसऱ्या कॉलला 204 की 404 ही शैलीची निवड; महत्त्वाचे हे की पुन्हा-प्रयत्न कधीच नापास होत नाही. Authentication लागते, body कधीच नाही, आणि काम पुढे ढकलले असेल तर 202.
TRACE · CONNECT
TRACE — तुमची विनंती तुम्हालाच परत वाजवतेCONNECT — proxy मधून बोगदा उघडाproxies, debuggersRFC मध्ये आहेत, तुमच्या काउंटरवर जवळजवळ कधीच नाहीत · TRACE सहसा बंद असते (cross-site tracing)
भेटतात पण क्वचित लिहिले जातात ते दोन. TRACE हा निदानासाठीचा प्रतिध्वनी, जो बहुतेक servers सुरक्षेसाठी बंद ठेवतात. CONNECT proxy ला कच्चा बोगदा उघडायला सांगतो — HTTPS कंपनीच्या proxies मधून असेच जाते. परीक्षेसाठी ओळखा; infrastructure वर सोडा.

🔢 प्रत्येक method कोणते status codes देते

कारकुनाचे शिक्के, method नुसार. संपूर्ण शिक्क्यांचा कॅटलॉग धडा 02; प्रत्येक 4xx साठी एकच error shape धडा 07.

Methodआनंदीclient ची चिठ्ठी चुकीची (4xx)जाणून घ्यावे
GET200 OK · 304 Not Modified (If-None-Match)404 · 400 (चुकीची गाळणी) · वाचन खाजगी असेल तर 401/403आत error असलेला 200 कधीच नाही
HEAD200 · 304404GET देईल तोच status — body कोणत्याही बाजूने नाही
OPTIONS204 · 200404CORS उत्तरांत Access-Control-* headers असलेच पाहिजेत
POST201 Created + Location · 200 (कृती) · 202 Accepted (रांगेत)400 problems · 401 · 403 · 409 conflict (दुहेरी) · 415 · 422 · 429Idempotency-Key सह पुन्हा → तोच 201, header Idempotent-Replay
PUT200 · 204 · बनवले असेल तर 201400 · 401 · 403 · 404 · 412 Precondition Failed (If-Match)If-Match: "etag" दोन कारकुनांना एकमेकांवर लिहिण्यापासून रोखते
PATCH200 · 204400 अनोळखी/अवैध field · 404 · 409 · 415 चुकीचा media typeकोणती PATCH बोली स्वीकारता ते सांगा: merge-patch की json-patch
DELETE204 · 202 · body सह 200401 · 403 · 404 (पहिल्यांदा) · 409 (अवलंबून गोष्टी आहेत)स्थितीनुसार idempotent — दुसरा कॉल 204 किंवा 404, 500 कधीच नाही

🧭 PUT विरुद्ध PATCH विरुद्ध POST — छोटे निर्णय-मार्गदर्शन

Client ला गोष्टीची URL माहीत आहे का?
नाही — server ला ती शोधावी लागते → collection वर POST, उत्तर 201 + Location. पुन्हा-प्रयत्न जुळे बनवू नये म्हणून Idempotency-Key जोडा.
हो — client संपूर्ण गोष्ट पाठवतोय का?
  हो → PUT. नसलेली fields ही चूक, "जुने मूल्य ठेवा" नव्हे. दुसऱ्याचा बदल पुसू नये म्हणून If-Match पाठवा.
  नाही, फक्त काही fields → application/merge-patch+json सह PATCH. अनोळखी fields 400 ने नाकारा.
ती कृती आहे, दस्तऐवज नाही? ("promote", "अहवाल पाठवा") → क्रियापदाच्या आकाराच्या उप-resource वर POST, आणि docs मध्ये तसे सांगा. GET कधीच नाही.

🔬 चालवा — खऱ्या काउंटरवर प्रत्येक method

api/methods_demo.sh सातही methods api/school_api.py कडे पाठवते आणि प्रत्येक नियम सिद्ध करणारे headers छापते: GET आणि HEAD वरचा ETag, OPTIONS वरची Allow यादी, दोन POST मधून दोन Locations, दोन PUT मधून एकच विद्यार्थी, अर्धवट PUT ला 400, एकत्र केलेला PATCH, आणि DELETE ला दोनदा 204.

python3 api/school_api.py        # terminal 1
bash api/methods_demo.sh         # terminal 2

तुम्हाला काय दिसायला हवे:

── GET — read it · safe · idempotent · cacheable
   HTTP/1.0 200 OK
   ETag: "72bc985b4c68bcd2"
   Cache-Control: private, max-age=30
   {"id": 2, "name": "Katrina", "class": "3A", "grade": "A+"}

── HEAD — GET's headers without the body: same ETag and Content-Length, zero bytes of body
   HTTP/1.0 200 OK
   Content-Length: 58
   ETag: "72bc985b4c68bcd2"

── OPTIONS — what may I do here? (also the browser's CORS preflight)
   HTTP/1.0 204 No Content
   Allow: GET, HEAD, PUT, PATCH, DELETE, OPTIONS
   Access-Control-Allow-Methods: GET, HEAD, PUT, PATCH, DELETE, OPTIONS

── POST — create a NEW one · NOT idempotent: the same form twice = two students (unless Idempotency-Key, lesson 07)
   HTTP/1.0 201 Created
   Location: /v1/students/6
   HTTP/1.0 201 Created
   Location: /v1/students/7

── PUT — REPLACE the whole student · idempotent: twice = the same student
{"id": 2, "name": "Katrina", "class": "3B", "grade": "A+"}
{"id": 2, "name": "Katrina", "class": "3B", "grade": "A+"}

── PUT with only one field — a replace means ALL the fields, so this is a 400 with problems
{"error": {"code": "validation_failed", "message": "The form has problems.", "problems": [{"field": "name", "problem": "required, non-empty string"}, {"field": "class", "problem": "must be one of ['3A', '3B']"}]}}

── PATCH — change PART of the student: send only what changes
{"id": 2, "name": "Katrina", "class": "3B", "grade": "A"}

── PATCH with a field that does not exist — 400, never a silent ignore
{"error": {"code": "validation_failed", "message": "Unknown fields.", "problems": [{"field": "nickname", "problem": "not a student field"}]}}

── DELETE — remove it · idempotent: the second DELETE is still 204, because the state is the same (gone)
   first:  204   second: 204   GET afterwards: 404

── the unsafe methods need the hall pass (lesson 06); the safe ones never do
   DELETE without a key: 401   GET without a key: 200

── and one that is NOT a method: /students/5/delete as a GET is a smell — GET must never change anything
   404  ← 404: no such noun, and no verb hidden in the URL

✅ seven methods, one counter — safe · idempotent · body · cacheable decide which one you reach for

⚠️ तीन शब्द मोडणाऱ्या चुका

चूकप्रत्यक्षात काय होतेत्याऐवजी हे करा
URL मध्ये क्रियापद: GET /students/5/deletecrawler किंवा आधीच आणणारा browser तुमचा data पुसतो; caches ते "पुसणे" वाटतातDELETE /students/5 — method हेच क्रियापद
दुष्परिणाम असलेला GET (मोजणी, "वाचले म्हणून खूण")प्रत्येक proxy आणि refresh परिणाम पुन्हा घडवतो; CDN ते cache करून टाकतातस्थिती बदलणाऱ्या कशासाठीही POST, कितीही छोटे असो
सगळ्यासाठी POSTकाहीच cache होत नाही, काहीच सुरक्षित पुन्हा पाठवता येत नाही, साधने मदत करू शकत नाहीतवाचायला GET, बदलायला PUT/PATCH, काढायला DELETE
"बाकी ठेवणारी" अर्धवट body सह PUTएका client ची नसलेली field दुसऱ्याचा data गुपचूप रिकामा करतेPUT सर्व fields बदलते (काही नसतील तर 400); अर्धवटासाठी PATCH
अनोळखी fields दुर्लक्षित करणारा PATCHgrdae मधली चूक 200 देते आणि काहीच जपत नाहीएकत्र केलेला निकाल तपासा; अनोळखी field → problems सह 400
आत {"ok": false} असलेला अपयशाचा 200caches ते जपतात, clients विश्वास ठेवतात, monitoring झोपतेएकच error shape सह योग्य 4xx/5xx (धडा 07)
Location header शिवाय 201client ला अंदाज करावा किंवा यादी पुन्हा आणून त्याने काय बनवले ते शोधावे लागतेLocation: /v1/students/6 आणि body मध्ये नवे resource
OPTIONS विसरणेसूचना फलकावरचे प्रत्येक cross-origin लिहिणे browser मध्ये CORS error ने नापासAllow आणि Access-Control-* headers सह preflight ला उत्तर द्या; ते cache करा
पुन्हा पाठवलेला POST जुळे बनवतोtimeout नंतर तोच विद्यार्थी दोनदा दाखलPOST वर Idempotency-Key; server पहिले उत्तर पुन्हा देतो
🎓 लक्षात ठेवायचे एक वाक्य: method तिच्या वचनानुसार निवडा — safe, idempotent, cacheable — कारण तुमच्या आणि client च्या मधले अख्खे internet त्या वचनावर विश्वास ठेवते. धडे: 02 HTTP ची रचना · 03 REST resources · 07 चुका आणि idempotency · 10 caching.
⏪ आधी

कोणते methods पुन्हा करणे सुरक्षित हे माहीत नसल्यास clients चुकीचे calls retry करतात आणि caches नको ती उत्तरे ठेवतात.

💡 काय

GET, HEAD, OPTIONS, POST, PUT, PATCH आणि DELETE हे सात methods, तीन शब्दांनी वेगळे ओळखले जातात: safe, idempotent, cacheable.

⚙️ कसे

GET /v1/students/2 ला body नसते आणि ते ETag सह 200 देते; ते safe, idempotent आणि cacheable आहे, आणि If-None-Match ने 304 मिळू शकतो.

🎯 का

हे तीन गुणधर्म सांगतात की कोणते calls मोकळेपणाने retry करायचे, कोणते cache करायचे आणि कोणत्यांना Idempotency-Key लागते.

🚀 पुढे

Production मध्ये हेच गुणधर्म तुमच्या API समोरच्या browsers, CDNs आणि gateways चे caching व retry नियम ठरवतात.

संपूर्ण धडा 13 वाचा →

14 🪪 प्रत्येक authentication पद्धत

हॉल पास दाखवण्याचा प्रत्येक मार्ग — Basic, API keys, Bearer tokens, JWT, cookies, OAuth 2.0 आणि त्याचे grant types, OpenID Connect, HMAC signing, mutual TLS.

🧒 सोप्या शब्दांत

Hall pass चे अनेक प्रकार आहेत: प्रत्येक वेळी नाव आणि password सांगणे (Basic), machine साठी दीर्घकाळ चालणारे key card (API key), सही केलेला आणि मुदत संपणारा pass (token किंवा JWT), किंवा app ला तुमच्या वतीने काम करू देणारे पालकांचे पत्र (OAuth). प्रत्येक वेगळ्या पाहुण्याला साजेसा; योग्य pass निवडणे आणि नेहमी HTTPS वरूनच वापरणे हे कौशल्य.

📖 नवे शब्दBasic auth — प्रत्येक request वर नाव आणि password, फक्त base64 मध्ये लिहिलेले, गुप्त नाही: फक्त HTTPSJWT — तुमची माहिती आणि संपण्याची वेळ असलेला सही केलेला passOAuth 2.0 — तुमचा password न देता app ला तुमच्या वतीने काम करू देणेOpenID Connect — OAuth अधिक तुम्ही कोण आहात हे सांगणारी सही केलेली चिठ्ठीmutual TLS — दोन्ही बाजू आपण कोण हे सिद्ध करण्यासाठी certificates दाखवतात

🚦 401 विरुद्ध 403 — दोन नकार

401 Unauthorized चा खरा अर्थ unauthenticated: "तू कोण आहेस ते मला कळत नाही." त्यासोबत स्वतःची ओळख कशी द्यायची ते सांगणारे WWW-Authenticate आव्हान असलेच पाहिजे (Basic realm="school", Bearer error="invalid_token"…).
403 Forbidden म्हणजे "तू कोण आहेस ते मला नेमके माहीत आहे, आणि उत्तर नाही": grades पुसायला मागणारा विद्यार्थी.
अनोळखी API key हा मधला भाग. काटेकोरपणे तो 401 (server ला ती कोणाकडे आहे ते कळत नाही — Stripe आणि GitHub 401 देतात); धडा 06 मधले काउंटर 403 देते ("पास आहे, पण योग्य नाही"). दोन्ही प्रत्यक्षात दिसतात; खालचा demo काटेकोर मार्गाने करतो, आणि roles सह पाठ्यपुस्तकातला 403 दाखवतो.

📋 मुख्य तक्ता — नऊ पद्धती एका पडद्यावर

आधी Server स्थिती ठेवतो? वाचा: तुम्ही तत्काळ रद्द करू शकता (stateful) की lookup शिवाय वाढू शकता (stateless) हे ते ठरवते. चित्राकडे उडी मारायला नावावर क्लिक करा.

Method🏫 उपमाकाय प्रवास करतेकुठेServer स्थिती ठेवतो?कशासाठी उत्तमसावधइथे चालते
Basicप्रत्येक दारावर पुन्हा दाखवायचा पासuser:password, base64Authorization headerनाहीscripts, अंतर्गत साधने, प्रोटोटाइपHTTPS नाहीतर काहीच नाही; password हेच credential✅
API keyप्रोग्रामचा हॉल पासएक लांब यादृच्छिक stringheader (URL मध्ये कधीच नाही)keys चा तक्ताserver-to-server, मोजमाप, सार्वजनिक data APIफिरवली नाही तर संपत नाही; browsers आणि logs मधून गळते✅
Bearer tokenऑफिसमधून मिळालेला हातपट्टा/login मधून मिळालेला opaque tokenAuthorization: Bearertokens चा तक्तास्वतःची ॲप्स आणि backend असलेली SPAप्रत्येक विनंतीला एक lookup; client कडे सुरक्षित ठेवा✅
JWTस्वाक्षरी केलेला हातपट्टाheader.payload.signatureAuthorization: Bearerनाही (stateless)एक login तपासणाऱ्या अनेक servicesवाचता येणारा payload; exp आधी रद्द नाही; alg गोंधळ✅
Session cookiebrowser चा मार्गएक session idCookie (HttpOnly, SameSite, Secure)sessions चा तक्ताएकाच साइटवरची browser ॲप्सSameSite शिवाय CSRF; HttpOnly शिवाय XSS✅
OAuth 2.0ऑफिसने सही केलेली परवानगीची चिठ्ठीcode → access token (+ refresh)Authorization: Bearerauthorization serverतृतीय-पक्ष प्रवेश, सोपवलेल्या scopesगुंतागुंतीचे; PKCE सह code flow वापरा, implicit कधीच नाही✅ client_credentials · refresh
OpenID Connect"…ने sign in करा"ID token (JWT) + access tokenAuthorization: Beareridentity providerGoogle / GitHub / Microsoft / Okta मार्फत loginiss, aud, exp, signature तपासा — प्रत्येक वेळीचित्रात
HMAC signingसील केलेला, तारीख असलेला लखोटाविनंतीवरची स्वाक्षरीX-Signature + timestampsecrets चा तक्ताwebhooks, AWS-शैलीची API, यंत्र-clientsघड्याळांचा फरक; canonical string तंतोतंत जुळायला हवी✅
Mutual TLSदोघेही गेटवर ओळखपत्र दाखवतातclient + server certificatesTLS handshakeएक CA आणि रद्द-यादीservice-to-service, zero trust, नियमित प्रणालीcertificate चे जीवनचक्र हेच सगळे कामचित्रात

तुटक बाण म्हणजे एकेक संदेश, अखंड बाण म्हणजे handshake. प्रत्येक चित्र ती पद्धत तारेवर जो header ठेवते तो आणि काउंटरचे उत्तर नेमके दाखवते.

Basic
GET /grades401 · WWW-Authenticate: Basic realm="school"GET /grades · Authorization: Basic dGVhY2hlcjpjaGFsaw==200 · teacher म्हणूनप्रत्येक विनंतीवर base64 मध्ये user:password · encryption नव्हे → फक्त HTTPS · scripts, अंतर्गत साधने
प्रत्येक दारावर पुन्हा दाखवायचा पास. Username आणि password, base64 मध्ये, प्रत्येक विनंतीसह. बनवायला क्षुल्लक, प्रत्येक HTTP client मध्ये अंगभूत, आणि फक्त HTTPS वरच स्वीकारार्ह. password सोडून रद्द करण्याजोगे काहीच नाही.
API key
GET /grades · X-API-Key: hall-pass-123200 · counter-bot म्हणूनGET /grades · X-API-Key: made-up401 (काटेकोर: अनोळखी = तू कोण?) · धडा 06 म्हणतो 403प्रोग्रामचा पास, मागे माणूस नाही · scope द्या, फिरवा, log करा · browser JS किंवा URL मध्ये कधीच नाही
प्रोग्रामचा हॉल पास. माणसाला नव्हे, application ला ओळखणारी लांब यादृच्छिक string, header मधून पाठवलेली. server-to-server आणि मोजमापासाठी उत्तम. एकट्याने कमकुवत: फिरवली नाही तर संपत नाही, वापरकर्ता नाही, आणि browser किंवा URL मध्ये गळली तर घातक.
Bearer token (opaque)
POST /login · {user: "teacher", password: "chalk"}200 · {token: "k5UVL2…", expires_in: 3600}GET /grades · Authorization: Bearer k5UVL2…200 · teacher म्हणून (server ने token तक्त्यात शोधला)एकदा login करा, हातपट्टा दाखवा · opaque = तक्त्याशिवाय निरर्थक · ओळ पुसून रद्द करा
एकदा login करा, हातपट्टा मिळवा. Credentials एकदाच यादृच्छिक token साठी बदलली जातात; नंतरची प्रत्येक विनंती token घेऊन जाते. Server तो शोधतो, म्हणून त्याला मुदत देऊ शकतो, scope देऊ शकतो आणि तत्काळ रद्द करू शकतो. प्रत्येक विनंतीला एक जास्तीचा lookup ही किंमत.
JWT
eyJhbGciOiJIUzI1NiJ9 · headereyJzdWIiOi… · payload: sub, role, expHMAC(secret, header.payload) · signatureकाउंटरBearer header.payload.signaturesignature + exp तपासा · lookup नाहीpayload कोणीही वाचू शकतो → त्यात गुपिते नकोत · exp आधी रद्द होत नाही → छोटा ठेवा + refresh
स्वाक्षरी केलेला हातपट्टा. Header, payload आणि signature, टिंबांनी जोडलेले base64. key असलेला कोणताही server database शिवाय तपासतो, म्हणूनच ते services मध्ये वाढते. Payload वाचता येतो, म्हणून त्यात दावे असतात, गुपिते कधीच नाहीत; आणि तो संपेपर्यंत वैध राहतो, म्हणून ती मुदत छोटी ठेवा.
Session cookie
POST /login · {user, password}200 · Set-Cookie: sid=vJOm…; HttpOnly; Secure; SameSite=LaxGET /grades · Cookie: sid=vJOm… (browser स्वतः जोडतो)200 · teacher म्हणून (session तक्ता: sid → user)browser चा मार्ग · HttpOnly XSS ला हरवते · SameSite CSRF ला हरवते · Secure = फक्त HTTPS
Browser चा मार्ग. Login नंतर server एक cookie ठेवतो; browser ती जपतो आणि कोणत्याही कोडशिवाय प्रत्येक विनंतीसह परत पाठवतो. तीन flags सुरक्षेचे काम करतात. मागे sessions चा तक्ता असतो, म्हणून log-out आणि रद्द करणे तत्काळ.
OAuth 2.0 (authorization code + PKCE)
व्यक्तीतुमचे ॲपauthorization serverresource server · API1 · login + संमती · PKCE2 · code3 · code + verifier → token4 · Bearer access tokenscopes token ला मर्यादा घालतात · refresh नवे करतो · PKCE code चोरी थांबवते · implicit flow कधीच नाही
Password न देता सोपवणे. व्यक्ती authorization server वर login करते आणि संमती देते; तुमच्या ॲपला छोटा code मिळतो, तो (PKCE verifier सह) access token साठी बदलला जातो, आणि त्याने API ला कॉल होतो. Scopes token काय करू शकतो ते मर्यादित करतात; refresh tokens तो नवा करतात. तृतीय-पक्ष प्रवेशाचा मानक मार्ग.
OpenID Connect
व्यक्तीतुमचे ॲपidentity providerतुमचे API1 · code flow · scope=openid2 · ID token (एक JWT)3 · + access token4 · Bearer access tokenOAuth: "हे ॲप कृती करू शकते का?" · OIDC जोडते "ही व्यक्ती कोण?" · iss, aud, exp, signature तपासा
"Google ने sign in करा" — OAuth अधिक ओळख. OAuth "हे ॲप कृती करू शकते का?" याचे उत्तर देते; OpenID Connect "ही व्यक्ती कोण?" याचे उत्तर देणारा, identity provider ने स्वाक्षरी केलेला ID token जोडते. त्याची signature, issuer, audience आणि मुदत तपासा. नुसत्या access token ला ओळखीचा पुरावा कधीच मानू नका.
OAuth client credentials
POST /token · grant_type=client_credentials · id + secret200 · {access_token, token_type: Bearer, expires_in, scope}GET /oauth/grades · Authorization: Bearer …200 · report-bot म्हणून · DELETE → 403 insufficient_scopeव्यक्ती नाही, browser नाही, संमती नाही · प्रोग्राम स्वतःच्या गुपिताने स्वतःला सिद्ध करतो · SCOPE ठरवते
प्रोग्रामचे स्वतःचे दार. कोणी व्यक्ती नाही: प्रोग्राम आपला client id आणि secret (form म्हणून, किंवा Basic म्हणून) token endpoint ला पाठवतो आणि अल्पायुषी, scope असलेला access token मिळवतो. service-to-service आणि भागीदार जोडण्यांसाठी OAuth चा default grant; चोरलेला token काय करू शकतो हे तो कोणाकडे आहे यावर नव्हे, तर त्याच्या scope वर ठरते.
OAuth device code
TV · CLIauthorization server1 · device_authorization → code WDJB-MJHT3 · POST /token grant_type=device_code (विचारत रहा)4 · authorization_pending … मग access_token2 · व्यक्ती फोनवर WDJB-MJHT मंजूर करते
Keyboard नसलेल्या गोष्टींसाठीचे दार. TV किंवा command-line साधन एक छोटा code दाखवते; व्यक्ती फोन किंवा लॅपटॉपवर तो मंजूर करते; उत्तर "pending" वरून token मध्ये बदलेपर्यंत device token endpoint ला विचारत राहते. gh auth login आणि smart TV असेच sign in करतात (RFC 8628).
HMAC request signing
METHOD · PATH · TIMESTAMP · sha256(body)signature = HMAC-SHA256(secret, ती string)काउंटरX-Key-Id · X-Timestamp · X-Signatureपुन्हा मोजा · तुलना करा · 5 मिनिटांची खिडकीगुपित कधीच प्रवास करत नाही · एक byte बदलला → जुळत नाही · जुना timestamp → नाकारला · webhooks, AWS SigV4
विनंतीवरच स्वाक्षरी करा. दोन्ही बाजूंकडे गुपित; पाठवणारा method, path, वेळ आणि body वर स्वाक्षरी करतो; घेणारा पुन्हा मोजून तुलना करतो. तारेवरून गुपित काहीच जात नाही, फेरफार दिसतो, आणि timestamp पुन्हा-वाजवणे हरवतो. Webhooks असेच तपासले जातात आणि AWS प्रत्येक कॉलवर अशीच स्वाक्षरी करते.
Mutual TLS
service A🪪client certificateservice B🪪server certificateTLS handshake: दोन्ही बाजू certificate दाखवतातदोघांचा विश्वास असलेल्या CA ची सही दोघांवरकोणत्याही HTTP आधी ओळख सिद्ध · service-to-service, zero-trust meshes, बँका · certificates फिरवा
दार उघडण्याआधीच दोघे ओळखपत्र दाखवतात. साधे TLS server सिद्ध करते; mutual TLS client लाही certificate दाखवायला लावते, handshake दरम्यान विश्वासार्ह authority विरुद्ध तपासलेले. यंत्र-ते-यंत्र सर्वात भक्कम पुरावा, आणि सर्वाधिक operational काम: certificates देणे आणि फिरवणे.

🎫 OAuth 2.0 grant types — कोणत्या कॉल करणाऱ्यासाठी कोणते दार

"OAuth" म्हणजे एकच प्रवाह नव्हे. Client token endpoint ला जो grant_type पाठवतो तो सांगतो कोण विचारतोय आणि ते कसे सिद्ध करतात. आज दोन grants जवळजवळ सगळे भागवतात; जुन्या कोडमध्ये भेटणारे दोन गेलेले आहेत.

grant_typeकोण विचारतोय/token ला काय पाठवताकाय परत मिळतेकशासाठीस्थिती
authorization_code + PKCEव्यक्ती, browser मधूनcode · code_verifier · redirect_uri · client_idaccess token (+ refresh; OIDC सह + ID token)वापरकर्त्यासाठी काम करणारी web, mobile आणि desktop ॲप्स✅ चालू — माणसांसाठी default (चित्रात)
client_credentialsप्रोग्राम, व्यक्ती नाहीclient_id + client_secret (किंवा Basic, किंवा private-key JWT) · scopeaccess token, सहसा refresh नाहीservice-to-service, cron jobs, भागीदार जोडण्या✅ चालू — प्रोग्रामसाठी default (चित्रात, इथे चालते)
refresh_tokenतोच client, नंतरrefresh_tokenनवा access token, बहुधा फिरवलेला refresh tokenनव्या login शिवाय sign in राहणे✅ चालू — प्रत्येकी एकच वापर, फिरवा (इथे चालते)
urn:ietf:params:oauth:grant-type:device_codekeyboard नसलेले devicedevice_code, दर काही सेकंदांनी विचारलेलाव्यक्तीने दुसरीकडे मंजुरी दिल्यावर access tokensmart TV, gh auth login, IoT ची मांडणी✅ चालू — RFC 8628 (चित्रात)
urn:ietf:params:oauth:grant-type:jwt-bearerprivate key असलेला प्रोग्रामस्वाक्षरी केलेले JWT assertionaccess tokenservice accounts (Google), issuers मधले federation✅ चालू — RFC 7523
urn:ietf:params:oauth:grant-type:token-exchangeदुसऱ्या कॉल करणाऱ्यासाठी काम करणारी serviceत्याच्याकडचा token + त्याला हवा असलेला audienceअरुंद किंवा वेगळ्या audience चा tokenmicroservices मधले सोपवणे आणि प्रतिरूपण✅ चालू — RFC 8693
password (ROPC)ॲप स्वतःच वापरकर्त्याचा password घेतेusername + passwordaccess tokenजुनी स्वतःची ॲप्स❌ OAuth 2.1 मसुद्यात काढलेले — ॲप password पाहते; MFA नाही, संमती नाही; demo unsupported_grant_type देतो
implicit (response_type=token)browser ॲप, redirect URL मधून/token ला काहीच नाही — token URL च्या fragment मध्ये परत येतोURL मधला access tokenजुनी single-page ॲप्स❌ OAuth 2.1 मसुद्यात काढलेले — इतिहास आणि referrers मधून गळते; code + PKCE वापरा
🎫 अंगठ्याचा नियम: browser मधली व्यक्ती → authorization_code + PKCE; स्वतःहून चालणारा प्रोग्राम → client_credentials; दोन्हीपैकी कोणताही refresh_token ने जिवंत ठेवा; keyboard नसलेला पडदा → device code. एखादी library किंवा tutorial password किंवा implicit कडे जात असेल, तर ती OAuth 2.1 पेक्षा जुनी आहे — या रेपोतले token endpoint दोन्ही unsupported_grant_type ने नाकारते.

🎚️ कोणतीही पद्धत बसवणारे पाच प्रश्न

प्रश्नएक उत्तरदुसरेका महत्त्वाचे
कॉल करणारा कोण?व्यक्ती (login, cookie, OAuth, OIDC)प्रोग्राम (API key, HMAC, mTLS)माणसांना sessions आणि संमती लागते; प्रोग्रामना फिरवणे आणि scopes
Server स्थिती ठेवतो का?हो — tokens/sessions चा तक्तानाही — स्वाक्षरी केलेला token (JWT, mTLS)stateful तत्काळ रद्द करते; stateless lookup शिवाय वाढते
ते कसे संपते किंवा मरते?ओळ पुसा · log outexp ची वाट पहा · key फिरवा · certificate रद्द कराचोरलेले credential नेमके एवढेच जगते
ते कुठून प्रवास करते?Authorization headerCookie · signature headers · TLS handshakeproxies headers log आणि cache करतात; cookies ना CSRF ची काळजी लागते
ते कोणी दिले?तुम्हीauthorization server किंवा identity providerसोपवणे म्हणजे दुसऱ्याचा बिघाड किंवा घुसखोरी आता तुमची

🧭 कोणता? — छोटे निर्णय-मार्गदर्शन

तुमच्याच साइटवरचे browser ॲप → session cookie (HttpOnly, Secure, SameSite) — किंवा front end वेगळ्या origin वर असेल तर Bearer token.
विद्यमान खात्याने sign in करणारी व्यक्ती → provider मार्फत OpenID Connect; ID token तपासा.
वापरकर्त्यासाठी कृती करणारे तृतीय-पक्ष ॲप → PKCE सह OAuth 2.0 authorization code, अरुंद scopes, छोटे access tokens, refresh tokens.
तुमच्याच services एकमेकांना कॉल करतात → mTLS (किंवा तुमच्यासाठी ते करणारे service mesh); नाहीतर सामायिक authorization server कडून OAuth client_credentials, किंवा अंतर्गत issuer ने स्वाक्षरी केलेले JWT.
भागीदाराचा server तुमच्या API ला कॉल करतो → अरुंद scopes सह OAuth client_credentials, किंवा अखंडतेसाठी API key आणि HMAC signing (किंवा mTLS); वेळापत्रकानुसार फिरवा.
तुम्ही webhook receiver ला कॉल करता → payload वर timestamp सह स्वाक्षरी करा (HMAC); receiver एका byte वरही विश्वास ठेवण्याआधी तपासतो.
अंतर्गत साधनावरची झटपट script → HTTPS वरून Basic प्रामाणिक आणि ठीक — फक्त सार्वजनिकसाठी नाही.
नेहमी: authentication सांगते कोण; authorization (roles, scopes, object ची मालकी) सांगते काय — दोन्ही प्रत्येक विनंतीवर तपासा, आणि 401 किंवा 403 नेमके द्या.

🔬 त्यांपैकी सात चालवा — त्याच grades, सात हॉल पास

api/auth_demo.py एका resource चे सात प्रकारे रक्षण करते — Basic, API key, opaque Bearer token, JWT (HS256, standard library ने स्वाक्षरी आणि तपासणी), HMAC request signing, session cookie, आणि OAuth 2.0 token endpoint (client_credentials आणि refresh_token, password grant नाकारलेला) — प्रत्येक 401 वर योग्य WWW-Authenticate आणि पुसायचा प्रयत्न करणाऱ्या विद्यार्थ्याला खरा 403. api/auth_client.py तारेवरचा प्रत्येक header, संपलेला token, बनावट JWT, फेरफार केलेली signature, पुन्हा वाजवलेली विनंती, आणि insufficient_scope ने DELETE नाकारलेला scope असलेला token दाखवते.

python3 api/auth_demo.py         # terminal 1
python3 api/auth_client.py       # terminal 2

तुम्हाला काय दिसायला हवे (token ची मूल्ये प्रत्येक वेळी वेगळी):

── 1 Basic — the pass you re-show at every door (user:password, base64, on EVERY request)
   no header                                      → 401  send Authorization: Basic base64(user:password)   WWW-Authenticate: Basic realm="school"
   Authorization: Basic dGVhY2hlcj…               → 200  as teacher (teacher) via basic · 2 grades
   wrong password                                 → 401  wrong user or password   WWW-Authenticate: Basic realm="school"
   base64 is NOT encryption — Basic is only ever acceptable over HTTPS

── 2 API key — a program's pass; no person behind it (the counter's X-API-Key, lesson 06)
   no key                                         → 401  no X-API-Key header   WWW-Authenticate: ApiKey realm="school", header="X-API-Key"
   X-API-Key: hall-pass-123                       → 200  as counter-bot (teacher) via apikey · 2 grades
   X-API-Key: made-up                             → 401  unknown key — we cannot tell who you are   WWW-Authenticate: ApiKey realm="school", header="X-API-Key"
   an unknown key = we cannot tell who you are = 401 (strict); the lesson-06 counter says 403 — both are seen in the wild

── 3 Bearer token (opaque) — log in once, get a wristband, show the wristband
   POST /login teacher/chalk                      → 200  token W-TTEyrfwc… expires_in 3600
   no token                                       → 401  send Authorization: Bearer <token>   WWW-Authenticate: Bearer realm="school"
   Authorization: Bearer W-TTEyrfwc…              → 200  as teacher (teacher) via token · 2 grades
   a token issued with ttl=1, 1.2 s later         → 401  token expired   WWW-Authenticate: Bearer realm="school", error="invalid_token", error_description="expired"
   DELETE as student (valid token)                → 403  student is a student: may read grades, not delete them
   401 = who are you? · 403 = I know exactly who you are, and no · the server LOOKS UP each opaque token

── 4 JWT — a SIGNED wristband: the server verifies, it does not look anything up
   header  {'alg': 'HS256', 'typ': 'JWT'}
   payload {'sub': 'teacher', 'role': 'teacher', 'iat': 1790052651, 'exp': 1790056251}   ← readable by anyone; never put secrets in it
   Authorization: Bearer eyJhbGciOiAiSF…          → 200  as teacher (teacher) via jwt · 2 grades
   payload edited to role=headmaster, same signature → 401  JWT bad signature   WWW-Authenticate: Bearer realm="school", error="invalid_token", error_description="bad signature"
   the signature pins the payload; expiry is inside it (exp) — and a stolen JWT is valid until then, so keep them short

── 5 HMAC request signing — you sign the request itself (webhooks, AWS SigV4 style)
   unsigned                                       → 401  sign the request: X-Key-Id, X-Timestamp, X-Signature   WWW-Authenticate: HMAC-SHA256 realm="school", headers="X-Key-Id X-Timestamp X-Signature"
   X-Key-Id key-1 · X-Timestamp 1790052651 · X-Signature 2370b654… → 200  as key key-1 (teacher) via hmac · 2 grades
   same signature, path changed by an attacker    → 401  signature does not match — the request was altered or the secret is wrong   WWW-Authenticate: HMAC-SHA256 realm="school", headers="X-Key-Id X-Timestamp X-Signature"
   valid signature, 15-minute-old timestamp (replay) → 401  timestamp outside the 5-minute replay window   WWW-Authenticate: HMAC-SHA256 realm="school", headers="X-Key-Id X-Timestamp X-Signature"
   the secret never travels; the signature covers method + path + time + body, so nothing can be altered or replayed

── 6 Session cookie — the browser's way: log in, the server sets an HttpOnly cookie, the browser sends it back
   no cookie                                      → 401  no valid session cookie — POST /login first   WWW-Authenticate: Cookie realm="school"
   POST /login                                    → 200  Set-Cookie: sid=Zha4S2aRtC…; HttpOnly; SameSite=Lax
   GET with the cookie jar                        → 200  as teacher (teacher) via session · 2 grades
   HttpOnly = JavaScript cannot read it (XSS cannot steal it) · SameSite = other sites cannot ride it (CSRF)

── 7 OAuth 2.0 client_credentials — a PROGRAM's own door: id + secret → access token, at the token endpoint
   POST /token grant_type=client_credentials (form) → 200  {access_token: _qxFCGv9…, token_type: Bearer, expires_in: 900, scope: grades:read}   Cache-Control: no-store
   GET /oauth/grades · Bearer _qxFCGv9…           → 200  as report-bot (client:grades:read) via oauth · 2 grades
   DELETE with scope=grades:read                  → 403  insufficient_scope   WWW-Authenticate: Bearer realm="school", error="insufficient_scope", scope="grades:write"
   wrong client_secret                            → 401  invalid_client   WWW-Authenticate: Basic realm="token endpoint"
   grant_type=password                            → 400  unsupported_grant_type: 'password' is not offered: people use authorization_code + PKCE, programs use client_credentials
   grant_type=refresh_token                       → 200  new access_token Ka1rN5IR… (the old refresh token is now used up)
   the shape every OAuth server speaks: a FORM to /token, a JSON {access_token, token_type, expires_in, scope} back, errors as {error} — and scope, not identity, decides the 403

✅ seven hall passes, one set of grades — who is asking, how do we know, and for how long

⚠️ हॉल पास वाटून टाकणाऱ्या चुका

चूकप्रत्यक्षात काय होतेत्याऐवजी हे करा
साध्या HTTP वरून Basic किंवा tokensवाटेवरचा कोणीही password किंवा token वाचतोसगळीकडे HTTPS; HTTP पूर्ण नाकारा
browser JavaScript किंवा URL मध्ये API keysview-source, browser इतिहास, proxy logs आणि referrers सगळे त्या गाळतातkeys servers वर राहतात; browsers ना अल्पायुषी user tokens
JWT payload मध्ये गुपितेpayload base64 आहे, token असलेला कोणीही वाचतोफक्त दावे (sub, role, exp); गुपिते server वर
रद्द करायचा मार्ग नसलेले दीर्घायुषी JWTवापरकर्ता बंद केल्यानंतरही चोरलेला token दिवसभर चालतोछोटा exp, refresh tokens, आणीबाणीसाठी नकार-यादी
alg: none किंवा चुकीचा algorithm स्वीकारणेस्वाक्षरी नसलेला किंवा हल्लेखोराने स्वाक्षरी केलेला token पास होतोalgorithm आणि key server वर पक्की करा; header वर कधीच विश्वास नको
tokens किंवा signatures ची == ने तुलनावेळेतले फरक गुपित byte-byte गाळतातhmac.compare_digest (स्थिर वेळ)
HttpOnly, Secure, SameSite शिवाय cookiesXSS session वाचते; दुसरी साइट त्यावर स्वार होते (CSRF)तीनही flags, नेहमी; SameSite Lax नसेल तर forms साठी CSRF tokens
localStorage मध्ये tokensकोणतेही XSS ते बाहेर नेतेHttpOnly cookies, किंवा refresh flow सह फक्त memory मध्ये
implicit OAuth flow, किंवा PKCE नाहीaccess tokens redirects आणि इतिहासातून गळतातauthorization code + PKCE, सार्वजनिक clients साठीही
Authorization header log करणेप्रत्येक credential कायमचे log प्रणालीत जातेकाठावर आणि request log मध्ये ते झाका (धडा 05)
नाकारलेल्या login साठी {"ok": false} सह 200clients ना नकार आणि यश वेगळे कळत नाही; monitoring झोपतेWWW-Authenticate आव्हानासह 401, निषिद्धासाठी 403, एकच error shape
🎓 लक्षात ठेवायचे एक वाक्य: प्रत्येक पद्धत म्हणजे स्थिती कोण ठेवतो आणि तुम्ही किती वेगाने रद्द करू शकता यांच्यातला व्यवहार; कॉल करणाऱ्यानुसार निवडा (व्यक्ती की प्रोग्राम), सगळ्याला मुदत द्या, आणि 401 किंवा 403 नेमके द्या. धडे: 06 auth · 07 चुका · 12 gateway; IAM आणि SigV4 साठी AWS शाळा.
⏪ आधी

Teams सवयीने auth पद्धत निवडतात, मग password base64 मध्ये साध्या HTTP वरून पाठवतात आणि ते encrypted आहे असे समजतात.

💡 काय

Hall pass दाखवण्याच्या सर्व पद्धती: Basic, API keys, Bearer tokens, JWT, cookies, OAuth 2.0, OpenID Connect, HMAC आणि mutual TLS.

⚙️ कसे

Basic मध्ये GET /grades ला 401 आणि WWW-Authenticate मिळते; पुन्हा पाठवताना base64 मधले user:password Authorization: Basic मध्ये जाते आणि 200 मिळते.

🎯 का

प्रत्येक पद्धत वेगळ्या caller ला साजेशी असते, म्हणून सगळ्या माहीत असल्या की सुरक्षित पद्धत निवडता येते, जसे Basic फक्त HTTPS आणि internal tools साठी.

🚀 पुढे

खरे platforms त्यांचे मिश्रण वापरतात: लोकांसाठी OAuth आणि OIDC, machines साठी keys किंवा HMAC, आणि internal services मध्ये mutual TLS.

संपूर्ण धडा 14 वाचा →

15 🔀 प्रत्येक API प्रकार

एक शाळा, अनेक काउंटर — REST, RPC, GraphQL, gRPC, streams, sockets, webhooks, queues, MQTT, batch फाइल्स, आणि network ला कधीच स्पर्श न करणारी API.

🧒 सोप्या शब्दांत

शाळेशी चार प्रकारे संपर्क करता येतो: counter वर विचारून उत्तराची वाट पाहणे, ताज्या बातम्यांसाठी phone वर थांबणे, नंतरसाठी पत्रपेटीत चिठ्ठी टाकणे, किंवा phone शिवाय इमारतीतलेच साधन वापरणे. प्रत्येक API प्रकार यापैकी एका कुटुंबात बसतो. तीन प्रश्न ते ठरवतात: सुरुवात कोण करतो, line किती वेळ उघडी राहते, आणि वाट कोण पाहतो.

📖 नवे शब्दsynchronous — तुम्ही आत्ताच उत्तराची वाट पाहताasynchronous — तुम्ही निरोप ठेवता; उत्तर नंतर येतेWebSocket — एक उघडी line, जिथे दोन्ही बाजू कधीही बोलू शकतातqueue — पत्रपेटी, जिथे संदेश कोणी उचलेपर्यंत थांबतातSDK — तुमच्यासाठी API ला call करणारी तयार code library

🗺️ चार कुटुंबे

खालचा प्रत्येक API प्रकार म्हणजे चारांपैकी एक संवाद. ही चार शिका आणि कोणतेही नवे संक्षिप्त नाव तुमच्याकडे आधीच असलेल्या खणात बसेल.

1️⃣ 📨 विचारा आणि उत्तर घ्यातुम्ही विचारता, ते उत्तर देते, संपलेREST · JSON-RPC · SOAPGraphQL · gRPC · tRPC · OData12️⃣ 📡 लाइनवर रहाएक जोडणी, अनेक संदेशlong polling · SSE ·WebSocket · WebRTC23️⃣ 📬 निरोप ठेवाकोणीच वाट पाहत नाही; ते नंतर पोहोचतेwebhooks · queues ·event streams · batch फाइल्स34️⃣ 🧰 network अजिबात नाहीएकाच मशीनमधला interfacelibrary/SDK · system calls ·DB drivers · device APIs4🧭 तीन प्रश्न कोणत्याही API ला कुटुंबात बसवतातसंवाद कोण सुरू करतो — कॉल करणारा, की दुसरी बाजू? · जोडणी किती वेळ टिकते — एक देवाणघेवाण, की अनेक?कोण वाट पाहतो — उत्तर आत्ता अपेक्षित आहे (synchronous), की नंतर, दुसऱ्या कोणाकडून (asynchronous)?

📋 मुख्य तक्ता — प्रत्येक प्रकार एका पडद्यावर

आधी उजवीकडचे दोन स्तंभ वाचा: कशात उत्तम आणि कधी नाही. कोणत्याही benchmark पेक्षा ही जोडी जास्त रचना ठरवते.

प्रकार🏫 शाळेची उपमाकोण सुरू करतोमागणीउत्तराचा आकारCache होते?कशात उत्तमकधी नाही
RESTलेबल लावलेल्या कपाटांचे काउंटरclientGET /v1/students/2संपूर्ण resource, JSON✅ URL नुसारसार्वजनिक API, CRUD, cache होणारे काहीहीएका screen ला पाच resources लागतात
JSON-RPC"हे कर", नावाने बोलावलेलेclient{method, params, id}result किंवा error❌नामे नसलेल्या कृती; MCP हेच बोलतोतुम्हाला HTTP caching आणि status codes हवे होते
SOAP / XML-RPCनोंदणीकृत लखोटाclientXML लखोटा + WSDLXML, कडक typed❌बँकिंग, दूरसंचार, सरकारी प्रणाली ज्यांच्याशी जोडणे भाग आहेनवे काहीही — साधनांचा कर खरा आहे
GraphQLएक खिडकी, फॉर्म तुम्ही लिहिताclient{ students { name grade } }नेमकी मागितलेली fields⚠️ कठीण (एकच URL)एक UI, त्याच data चे अनेक आकारदोन endpoints ची service; सार्वजनिक cache होणारा data
gRPCtyped अंतर्गत झरोकाclient.proto मधला method callbinary protobuf, streams ही❌service ↔ service, कमी latency, अनेक भाषाproxy शिवाय browsers; curl करता येणे महत्त्वाचे
tRPCएक ऑफिस, एक भाषाclienttyped function callfunction जे परत करेल ते❌एकच TypeScript codebase, टोकापासून टोकापर्यंत typesत्या codebase बाहेरच्या कोणालाही कॉल करायचा असेल
ODataquery भाषा जोडलेले RESTclient/Students?$filter=…&$select=…गाळलेले entity संच✅ अंशतःMicrosoft-stack मधले entities वरचे अहवालसाध्या REST किंवा GraphQL ने तुम्ही जास्त समाधानी असाल
Long pollingकारकून तुमचा प्रश्न धरून ठेवतोclientGET /poll?since=NN नंतरचे events, किंवा रिकामे❌कोणत्याही proxy मधून, कोणत्याही client ला updatesवारंवार updates (प्रत्येक client साठी धरलेले socket)
SSEलाउडस्पीकरclient उघडतो, server बोलतोGET /eventstext/event-stream frames❌एकदिशा थेट updates: feeds, प्रगती, किंमतीclient ला परत बोलायचेही असेल
WebSocketउघडी फोन लाइनupgrade नंतर कोणीहीGET /ws + Upgradeframes, दोन्ही दिशांनी❌chat, cursors, खेळ, थेट dashboardsसाधे request/response पुरले असते
WebRTCबाकावरून बाकावर, थेटpeers (server फक्त ओळख करून देतो)SDP offer/answermedia आणि data channels❌audio/video कॉल, प्रचंड peer हस्तांतरेदोन्ही टोके तुमच्याच server वर आहेत
Webhookतुम्ही तुमचा फोन नंबर ठेवताserver तुम्हाला कॉल करतोतुम्ही एकदा URL नोंदवताप्रत्येक event ला एक POST❌"झाले की सांग": payments, CI, प्रवेशतुमचा consumer URL उघड करू शकत नाही
Queue (AMQP, SQS)पिजनहोल, एकच वाचणाराproducer लिहितो, worker वाचतोएक काम रांगेत टाका (RabbitMQ, SQS)उत्तर नाही — पावती❌पार्श्वभूमीचे काम, गर्दीचे झटके, पुन्हा-प्रयत्नकॉल करणाऱ्याला उत्तर आत्ता हवे
Event streamसगळे पुन्हा वाचू शकतील अशी नोंदवहीproducer जोडत जातोएका topic वर प्रकाशित कराप्रत्येक consumer स्वतःची जागा ठेवतो❌अनेक consumers, पुन्हा वाचन, लेखापरीक्षणसाधे एक-ते-एक हस्तांतरण
MQTTछोट्या उपकरणांसाठी शाळेची ध्वनिक्षेपक यंत्रणाउपकरणे प्रकाशित करतात, broker वाटतोएका topic वर प्रकाशित करा (2-byte header)subscribers नी जे मागितले ते❌sensors, फोन, अविश्वसनीय networks, IoTrequest/response; मोठे payloads
Batch / फाइलरात्रीची व्हॅनवेळापत्रकSFTP/S3 वर CSV टाकातासांनी परत एक फाइल❌लाखो ओळी, बँकिंग, पगार, EDIमाणूस वाट पाहत असलेले काहीही
Library / SDKतुमच्याच पिशवीतले साधनतुमचा कोडएक function callपरतीचे मूल्य किंवा exceptionलागू नाहीयाच process मधले काम; वरच्या कशालाही गुंडाळणेतुम्हाला network ची सीमा आणि तिची हमी हवी आहे
System callइमारतीच्या व्यवस्थापकाला विचारणेतुमची processopen(), socket()file descriptor, errnoलागू नाहीफाइल्स, memory, processes, socketsतुम्ही application कोड लिहिताय — library वापरा
Database driverरेकॉर्ड रूमपर्यंतची तारतुमचा कोडDB protocol वरून SQLओळी, एक cursorलागू नाहीDatabase शाळेच्या खोलीशी बोलणेते जगाला उघडणे — समोर काउंटर उभे करा

🔧 REST ला स्वतःच्या सात methods आहेत — पहा धडा 13, प्रत्येक REST method — आणि प्रकार कोणताही असो, कॉल करणाऱ्याला हॉल पास दाखवावा लागतो — पहा धडा 14, प्रत्येक authentication पद्धत.

प्रत्येक प्रकारासाठी एक ओळ, तक्त्याच्याच क्रमाने: डावे टोक विचारते, उजवे टोक उत्तर देते, तुटक बाण म्हणजे एकेक संदेश, अखंड बाण म्हणजे उघडी लाइन. इथे उडी मारायला तक्त्यातल्या नावावर क्लिक करा.

REST
clientकाउंटरGET /v1/students/2 — एक नाम200 · संपूर्ण विद्यार्थी, JSON मध्येHTTP method हेच क्रियापद · प्रत्येक resource ला एक URL · URL नुसार cache होते
लेबल लावलेल्या कपाटांतली नामे. Resources URL वर राहतात; GET/POST/PUT/DELETE ही क्रियापदे; संपूर्ण प्रतिरूप परत येते, आणि caches URL वरून ओळखतात. हा कोर्स हाच आकार बांधतो.
JSON-RPC
clientकाउंटरPOST /jsonrpc · {method:'students.list', id:1}{id:1, result:[…]} किंवा {id:1, error:{code}}नावाने बोलावलेले क्रियापद · एकच URL · id प्रश्नाला उत्तर जोडतो · चुका म्हणजे data (तरी 200)
"हे कर", नावाने. एकच endpoint, method चे नाव आणि params; उत्तर तोच id घेऊन येते. चुका HTTP status म्हणून नव्हे, तर result च्या आत प्रवास करतात. MCP शाळा नेमके हेच बोलते.
SOAP / XML-RPC
cliententerprise प्रणालीXMLPOST · text/xml · SOAPActionWSDL कराराने वर्णन केलेले<soap:Envelope><soap:Body>…</soap:Body></soap:Envelope>कडक typed, स्वाक्षरी केलेला, transactional — बँका आणि सरकार अजूनही मागतात तो नोंदणीकृत लखोटा
नोंदणीकृत लखोटा. लखोट्यातले XML संदेश, WSDL कराराने वर्णन केलेले, स्वाक्षरी, सुरक्षा आणि transactions च्या मानकांसह. जड साधने; बँकिंग, दूरसंचार आणि सरकारी जोडण्यांत अजूनही अनिवार्य.
GraphQL
clientएकच endpointstudentsclassesgradesPOST /graphql · { students { name grade } }{ data: { students: [ {name, grade} … ] } }उत्तराचा आकार तुम्ही लिहिता · server तो अनेक स्रोतांतून सोडवतो
एक खिडकी, फॉर्म तुम्ही लिहिता. एकच endpoint आणि एक query भाषा: client ला हवी असलेली fields तो नेमकी सांगतो, server ती अनेक स्रोतांतून सोडवतो आणि नेमके तेच परत देतो. जास्तीचे आणणे नाही; पण caching आणि query चा खर्च तुमची डोकेदुखी.
gRPC
service A.protoservice B.proto010010 · protobuf, binary · HTTP/2 वरूनListStudents(ClassFilter) → stream Studentप्रत्येक भाषेत तयार clients · दोन्ही टोकांना typed · दोन्ही दिशांनी streams · curl करता येत नाही
Typed अंतर्गत झरोका. एक .proto फाइल calls ठरवते; प्रत्येक भाषेसाठी कोड तयार होतो; संदेश HTTP/2 वरून घट्ट binary म्हणून प्रवास करतात, दोन्ही दिशांनी streaming सह. तुमच्याच services मध्ये उत्तम; browsers ना proxy लागतो.
tRPC
एकच TypeScript codebasefront endback endtrpc.students.list.query({ class: '3A' })Student[] — TYPE टोकापासून टोकापर्यंत वाहतो, schema फाइल नाही
एक ऑफिस, एक भाषा. Client server ची functions स्थानिक असल्यासारखी बोलावतो, आणि TypeScript वेगळ्या schema शिवाय types तारेवरून पलीकडे नेते. एकाच codebase मध्ये सुंदर; बाहेरच्या कोणालाही REST किंवा GraphQL द्यावेच लागते.
OData
clientकाउंटरentity संचGET /Students?$filter=class eq '3A'&$select=name{ value: [ {name} … ], @odata.count }REST च्या रूढी + प्रमाणित query भाषा ($filter · $select · $orderby · $top) · Microsoft stack
Query भाषा जोडलेले REST. Entity संचांवर गाळणी, निवड, क्रम आणि पाने यांसाठी प्रमाणित URL operators, शिवाय metadata दस्तऐवज. Microsoft परिसंस्थेत आणि reporting साधनांत सामान्य; नव्या सार्वजनिक API साठी क्वचितच निवडले जाते.
Long polling
clientकाउंटरGET /poll?since=7 (कारकून प्रश्न धरून ठेवतो)नंतर (≤10 s): { events: [8, 9], cursor: 9 }वाट पाहणारी एक विनंती · timeout वर रिकामे उत्तर · मग नव्या cursor ने पुन्हा विचारा
कारकून तुमचा प्रश्न धरून ठेवतो. बातमी किंवा timeout येईपर्यंत server उघडी ठेवणारी साधी विनंती; मग client लगेच पुन्हा विचारतो. कोणत्याही proxy आणि client मधून चालते; प्रत्येक client मागे एक धरलेली जोडणी हा खर्च.
Server-Sent Events
clientकाउंटरGET /events · Accept: text/event-stream (एकदाच)id: 8 · event: student.created · data: {…}id: 9 · event: student.created · data: {…}एक जोडणी, फक्त server → client · browsers स्वतःहून पुन्हा जोडतात आणि Last-Event-ID पाठवतात
लाउडस्पीकर. कधीच न संपणारा एक HTTP प्रतिसाद; server त्यातून छोटे मजकूर-frames खाली ढकलतो, प्रत्येकाला id. Browsers आपोआप पुन्हा जोडतात आणि शेवटच्या id पासून पुढे सुरू करतात. फक्त एकदिशा, आणि अतिशय स्वस्त.
WebSocket
clientकाउंटरGET /ws · Upgrade: websocket → 101 Switching Protocolspush →← pushupgrade नंतर एकच socket: दोन्हीपैकी कोणीही केव्हाही बोलू शकते · frames, विनंत्या नव्हे
उघडी फोन लाइन. एक HTTP विनंती कायमच्या socket मध्ये upgrade होते, आणि त्यानंतर दोन्ही बाजू हव्या तेव्हा frames पाठवतात. Chat, cursors, खेळ, थेट dashboards. साध्या request/response साठी अतिरेक.
WebRTC
लॅपटॉपफोनओळख करून देणारा serverSDP offerSDP answeraudio · video · data channel — peer to peerserver फक्त दोन टोकांची ओळख करून देतो (STUN/TURN त्यांना एकमेकांना शोधायला मदत करतात); media त्याला स्पर्शही करत नाही
बाकावरून बाकावर, थेट. Server offers आणि answers ची देवाणघेवाण करून दोन peers ची ओळख करून देतो; त्यानंतर audio, video आणि data थेट त्यांच्यात वाहतात. Video कॉल आणि प्रचंड peer हस्तांतरे. Server वर नियंत्रण हवे असलेल्या कशासाठीही नाही.
Webhook
तुमचा serverत्यांचे काउंटर1 · एकदाच: https://you/hook नोंदवा2 · नंतर: POST /hook · X-Signature · {event, id}ते तुम्हाला कॉल करतात · स्वाक्षरी तपासा · पुन्हा-प्रयत्न आणि दुहेरी अपेक्षित → event id नुसार दुहेरी काढा
तुम्ही तुमचा फोन नंबर ठेवता. एकदा URL नोंदवा; काही घडले की त्यांचा server तुम्हाला event POST करतो. वरच्या सगळ्याच्या उलट. स्वाक्षरी करा, तपासा, आणि handler idempotent बनवा कारण पोहोच पुन्हा पुन्हा होते.
Queue · AMQP / SQS
producerexchangequeue: gradesqueue: emailsworkerworkerकाम एकच worker उचलतो आणि ते संपले · acks, पुन्हा-प्रयत्न, dead-letter queue · कॉल करणारा कधीच थांबत नाही
पिजनहोल, एकच वाचणारा. Producer काम टाकतो; broker ते एका queue कडे पाठवतो; नेमका एक worker ते उचलतो आणि पावती देतो. पुन्हा-प्रयत्न, dead-letter queues आणि backpressure अंगभूत. AMQP (RabbitMQ) आणि SQS या सामान्य बोली.
Event stream · Kafka
producer12345678topic: enrolments — फक्त जोडत जाणारी नोंदवहीconsumer Aconsumer B8 पर्यंत वाचले3 पर्यंत वाचले — पुन्हा वाचतोय
सगळे पुन्हा वाचतात ती नोंदवही. Producers विभागलेल्या log ला जोडत जातात; प्रत्येक consumer त्यातली स्वतःची जागा ठेवतो आणि सुरुवातीपासून पुन्हा वाचू शकतो. अनेक वाचणारे, लेखापरीक्षण, bug नंतर पुन्हा वाचन. Queue पेक्षा चालवायला जड.
MQTT
topics · 2-byte headers · QoS 0 / 1 / 2 · last-will संदेश · sensors आणि लहरी networks साठी बनवलेलेsensorॲपbrokerdashboardloggerpublish school/attendancesubscribe school/#
छोट्या उपकरणांसाठी शाळेची ध्वनिक्षेपक यंत्रणा. नावे दिलेल्या topics वर broker मार्फत publish/subscribe, दोन-चार bytes चे headers आणि पोहोचीच्या तीन हमी. Sensors, फोन आणि अविश्वसनीय networks साठी बनवलेले. Request/response चे साधन नव्हे.
Batch / फाइल हस्तांतरण
पगार प्रणालीCSVstudents_2026-09-22.csvSFTP / S3 bucketबँकरोज रात्री 02:00 · 12 लाख ओळीहळू, साधे, तपासण्याजोगे, सगळीकडे · EDI, CSV, fixed-width · तासांनी परत एक फाइल
रात्रीची व्हॅन. वेळापत्रकानुसार एक फाइल सामायिक जागी टाकली जाते आणि दुसरी प्रणाली ती तासांनी उचलते. बँका, पगार आणि किरकोळ व्यापार लाखो ओळी अजूनही अशाच हलवतात. कोणी वाट पाहत नसेल तर ठीक; माणूस वाट पाहत असेल तर चूक.
Library / SDK
एकच process — network नाहीतुमचा कोड · import boto3librarys3.upload_file('grades.csv')परतीचे मूल्य — किंवा exception
तुमच्याच पिशवीतले साधन. Package तुमच्या कोडला functions देते; तुम्ही त्या बोलावता आणि त्याच process मध्ये मूल्य किंवा exception परत मिळते. API चा सर्वात जुना प्रकार, आणि versioning, docs आणि deprecation त्याला काउंटरसारखेच लागू.
System call
तुमची processkernel · इमारतीचा व्यवस्थापकdiskopen('school.db')fd 3 — किंवा errno ENOENTPOSIX / Win32 · फाइल्स, memory, processes, sockets · प्रत्येक library इथे येऊन संपते
इमारतीच्या व्यवस्थापकाला विचारणे. प्रोग्राम फाइल्स, memory किंवा network ला स्वतः हात लावू शकत नाहीत; ते ठरलेल्या calls मधून operating system ला विचारतात आणि descriptor किंवा error क्रमांक परत मिळवतात. या पानावरचे प्रत्येक network API शेवटी इथेच पोहोचते.
Database driver
तुमचे ॲपdriver · psycopg, JDBCरेकॉर्ड रूमSQLओळी / cursorDB चा wire protocolDatabase शाळेची खोली, कोडमधून गाठलेली · connection pools · कधीच internet ला उघड नाही
रेकॉर्ड रूमपर्यंतची तार. Driver database ची स्वतःची भाषा बोलतो म्हणजे तुमचा कोड SQL पाठवू शकतो आणि cursor मधून ओळी वाचू शकतो. तेही एक API आहे, आणि थेट कधीच उघड न करण्याचे: समोर एक काउंटर उभे करा.
Device / hardware
तुमचे ॲप · browserGPS / camera / USBnavigator.geolocation.getCurrentPosition(){ lat, lng } — वापरकर्त्याने हो म्हटल्यावरआधी परवानग्या · OS मध्यस्थी करते · Web Bluetooth, WebUSB, Raspberry Pi वर GPIO
भिंतीतले socket. Cameras, GPS, USB, Bluetooth आणि GPIO pins operating system किंवा browser मध्यस्थी करत असलेल्या API मधून, बहुधा परवानगीच्या विचारणीमागे, गाठले जातात. तीच कराराची कल्पना, मध्ये एक माणूस.

1 📨 विचारा आणि उत्तर घ्या — request/response कुटुंब

तुम्ही विचारता, ते उत्तर देते, संवाद संपला. तीन उप-आकार: नामे (REST), क्रियापदे (RPC) आणि "उत्तराचा आकार तुम्ही लिहिता" (GraphQL).

🗄️ resource-केंद्रित — RESTGET /v1/students/2 — एक नाम;method हेच क्रियापद; cache होणारेसंपूर्ण प्रतिरूप परत येते1📞 call-केंद्रित — RPC{method: 'students.list', id: 1}नावाने एक क्रियापद · JSON-RPC, gRPC,SOAP, tRPC — चुका म्हणजे data2🧩 query-केंद्रित — GraphQL{ students { name grade } }एकच endpoint; उत्तराचा आकारतुम्ही लिहिता · OData SQL सारखे3⚖️ तोच प्रश्न, तीन आकार — आणि तीन वेगळी बिलेREST: 3 resources लागणाऱ्या screen साठी 3 फेऱ्या, पण प्रत्येक उत्तर URL नुसार cache होतेRPC: 1 call, typed आणि वेगवान — आणि caches ना व URL वाचणाऱ्याला अदृश्यGraphQL: 1 call, नेमकी तीच fields — आणि आता query चा खर्च, खोलीच्या मर्यादा व cache keys तुमच्या जबाबदारीवर
⏪ आधी

SOAP, tRPC, SSE, MQTT, webhooks अशा API नावांच्या गर्दीत प्रत्येक नेमके कशासाठी आहे ते समजणे कठीण जाते.

💡 काय

प्रत्येक API ला चार कुटुंबांत बसवणारा नकाशा: विचारा आणि उत्तर, line वर राहा, निरोप ठेवा, आणि network अजिबात नाही.

⚙️ कसे

तीन प्रश्न कोणत्याही API ची जागा ठरवतात: संभाषण कोण सुरू करतो, connection किती काळ टिकते, आणि उत्तराची वाट कोण पाहतो.

🎯 का

नवीन API चे नाव भेटले की ते कुटुंबात बसवता येते आणि docs वाचण्याआधीच ते कसे वागते ते कळते.

🚀 पुढे

खऱ्या systems मध्ये कुटुंबे एकत्र येतात: requests साठी REST, events साठी webhooks किंवा queues, आणि सगळ्यांना गुंडाळणारे SDKs.

या कोर्समध्ये: REST म्हणजे धडे 03–12; बाकीचे धडा 11. याच कुटुंबात: MCP शाळा हा टोकापासून टोकापर्यंत JSON-RPC प्रोटोकॉल आहे.

2 📡 लाइनवर रहा — streaming आणि realtime

एक जोडणी, अनेक संदेश. त्यांच्यातला फरक म्हणजे कोण बोलू शकतो, आणि लाइन किती वेळ उघडी राहते.

⏳ long pollingएक विनंती, उघडी धरलेलीबातमी येईपर्यंत किंवा timeout पर्यंतसगळीकडे चालते · फक्त HTTP1📢 SSEtext/event-streamफक्त server → clientआपोआप पुनर्जोडणी + Last-Event-ID2☎️ WebSocketHTTP upgrade → एक socketदोन्ही बाजू बोलू शकतातchat, cursors, थेट dashboards3🎥 WebRTCबाकावरून बाकावर, peer to peeraudio, video, data channelsserver फक्त ओळख करून देतो4📡 'किती ताजे, आणि कोण बोलतो?' याचे उत्तर देणारी सर्वात छोटी गोष्ट निवडाएकदिशा updates, काही सेकंद चालतील → SSE · दोन्ही दिशा, दहा-वीस milliseconds → WebSocket · क्वचित updates, जुने clients → long pollingmedia किंवा प्रचंड peer-to-peer data → WebRTC · यापैकी काहीच नाही → टाइमरवरचे साधे polling खरोखर ठीक आहे

लक्षात ठेवायचा खर्च: प्रत्येक उघडी जोडणी म्हणजे server वरची memory आणि एक file descriptor — 10,000 निष्क्रिय sockets हा रचनेचा निर्णय आहे, तपशील नव्हे. Load balancers आणि proxies ना ते परवानगी द्यायला सांगावे लागते.

3 📬 निरोप ठेवा — asynchronous आणि सुटे

उत्तरासाठी कोणीच थांबत नाही. संदेश स्वीकारला की producer चे काम संपले; प्रत्यक्ष काम नंतर होते, कदाचित दुसरीकडे, कदाचित दोनदा.

📣 webhookतुम्ही URL ठेवता; producerevent तुम्हाला POST करतोस्वाक्षरी करा · पुन्हा-प्रयत्न व दुहेरी अपेक्षित1📬 queue — एकच वाचणाराSQS · RabbitMQ — एक पिजनहोल;worker काम उचलतो आणि ते संपलेपुन्हा-प्रयत्न, dead-letter, backpressure2📖 event stream — अनेक वाचणारेKafka — फक्त जोडत जाणारी नोंदवही;प्रत्येक consumer स्वतःची जागा ठेवतोकालचे कधीही पुन्हा वाचा3🚚 batch / फाइल — रात्रीची व्हॅनSFTP, S3 CSV, EDI — बँका, पगार आणि किरकोळ व्यापारअजूनही लाखो ओळी अशाच देवाणघेवाण करतातहळू, साधे, तपासण्याजोगे, आणि सगळीकडे4🔑 async चा नियमपोहोच किमान एकदा — handleridempotent बनवा (धडा 07)आणि इथले काहीच 'आत्ता' उत्तर देत नाही

तुम्हाला वाचवणारा नियम: किमान-एकदा पोहोच म्हणजे दुहेरी संदेश. प्रत्येक handler idempotent करा (धडा 07) आणि अख्खे कुटुंब सुरक्षित होते.

4 🧰 Network अजिबात नाही — बहुतेकांना विसरलेले API

"API" हे web पेक्षा जुने आहे. Library, system call, database driver आणि device interface — हे सगळे दोन सॉफ्टवेअरमधले करारच आहेत; आणि या कोर्सचे धडे त्यांना जसेच्या तसे लागू होतात.

📚 library / SDK APIpackage तुमच्या कोडलादेते ती functionsjson.loads() · boto31🏛️ OS / system callsइमारतीच्या व्यवस्थापकाला विचारणे:open, read, socket, forkPOSIX · Win322🗄️ database driverरेकॉर्ड रूमपर्यंतचा wireprotocol · JDBC, psycopg(Database शाळा)3🔌 device / hardwarecamera, GPS, USB, GPIO —भिंतीतले socketbrowser: navigator.*4🧠 हे सुद्धा API का मोजले जातातAPI म्हणजे दोन सॉफ्टवेअरमधला करार — network हा अंमलबजावणीचा तपशील आहे, व्याख्या नव्हे ·versioning (L09), चुका (L07), auth (L06) आणि docs (L12) library ला काउंटरसारखेच लागू होतात

🌍 वर्गीकरणाचा दुसरा मार्ग: कोणाला कॉल करायची परवानगी आहे

प्रकार "कोणता आकार?" याचे उत्तर देतो. श्रोते "नियम काय?" याचे — आणि आकारापेक्षा श्रोतेच तुमचे जास्त काम ठरवतात.

श्रोतेकोण कॉल करू शकतेकाय बदलतेउदाहरण
🌍 सार्वजनिक / खुलेkey असलेला कोणीही (किंवा काहीच नसलेला)versioning आणि docs हेच करार; rate limits व गैरवापरापासून संरक्षण अनिवार्यनकाशांचे API, हवामानाचे API
🤝 भागीदारकरारानुसार, नावाने ठरलेल्या संस्थाकडक auth, SLA, sandbox वातावरणे, वाटाघाटीने बदलpayment पुरवठादार, logistics ची जोडणी
🏠 खाजगी / अंतर्गततुमच्याच servicesतुम्ही पटकन बदलू शकता — जर प्रत्येक कॉल करणाराही अद्ययावत करू शकत असालतुमच्या दोन services मधले काउंटर
🧩 संमिश्र / BFFएकच front endते अनेक API कडे पसरते आणि एका screen च्या आकाराचे उत्तर देतेmobile साठीचे backend-for-frontend

🎚️ कोणत्याही API चे वर्णन करणारे पाच अक्ष

कोणी तुम्ही न भेटलेल्या तंत्रज्ञानाचे नाव घेतले, तर ते या पाच अक्षांवर ठेवा आणि ते काय करू शकते व काय नाही हे बहुतांश कळेल.

अक्षएक टोकदुसरे टोकतो कोणत्या प्रश्नाचे उत्तर देतो
वेळsynchronous — उत्तर आत्ताasynchronous — उत्तर नंतर, दुसरीकडेमाणूस वाट पाहतोय का?
कोण सुरू करतोclient ओढतोserver ढकलतो (webhook, SSE, WS)बदल आधी कोणाला कळतो?
आकारresource (REST)procedure (RPC) / query (GraphQL)क्षेत्र नामांचे आहे की क्रियापदांचे?
Payloadमजकूर (JSON, XML)binary (protobuf, MessagePack)माणसाला तपासता येणारे की वेगवान?
जोडणीएक कॉल करणारा, एक उत्तर देणारामध्ये एक दलाल (queue, stream)एक बाजू एकटी बंद असू शकते का?

🧭 कोणता? — छोटे निर्णय-मार्गदर्शन

इथून सुरू करा: उत्तरासाठी माणूस वाट पाहतोय का?
नाही → asynchronous. एकच ठरलेला consumer → queue. अनेक consumers किंवा पुन्हा वाचन → event stream. दुसऱ्याच्या प्रणालीला सांगावे लागते → webhook. रात्रभरात लाखो ओळी → batch फाइल.
हो → update सतत चालू असते का?
  हो, एकदिशा → SSE. दोन्ही दिशा → WebSocket. Media किंवा peer-to-peer → WebRTC. जुने clients किंवा आडमुठे proxies → long polling.
  नाही → कोण कॉल करतो? सार्वजनिक/भागीदार → REST (cache होणारे, दस्तऐवज असलेले, कंटाळवाणे — रोमांचक वाटते त्यापेक्षा कितीतरी जास्त वेळा योग्य उत्तर). तुमच्याच services, गप्पिष्ट आणि typed → gRPC. अनेक आकार लागणारे एक UI → GraphQL. एकच TypeScript codebase → tRPC. ते मागणारी enterprise → SOAP.
आणि नेहमी: आकार एकत्र येतात. एखादे काम रांगेत टाकणारे, webhook ने संपणारे आणि SSE वरून प्रगती दाखवणारे REST काउंटर म्हणजे तीन रचना नव्हेत — ती एकच आहे, प्रत्येक कुटुंब त्याच्या बलस्थानासाठी वापरणारी.

🔬 त्यांपैकी सहा चालवा — तेच पाच विद्यार्थी, सहा आकार

api/api_types.py हा एकच शून्य-dependency server आहे जो त्याच data बद्दल REST, JSON-RPC, GraphQL, long polling, SSE आणि खऱ्या WebSocket (handshake आणि frames सह, ~160 ओळी) म्हणून उत्तर देतो. api/types_client.py सहाही वापरून पाहतो आणि प्रत्येक byte छापतो.

python3 api/api_types.py        # terminal 1
python3 api/types_client.py     # terminal 2

तुम्हाला काय दिसायला हवे (छाटलेले):

── 1 REST — GET /v1/students?class=3A
   → {"items": [{"id": 1, "name": "Aishwarya", "class": "3A", "grade": "A"}, {"id": 2, "name": "Katrina", "class": "3A", "gra
   the shape: you asked for a RESOURCE; you got all of its fields, whether you wanted them or not

── 2 JSON-RPC — POST /jsonrpc  {method: 'students.list'}
   → {"jsonrpc": "2.0", "id": 1, "result": [{"id": 4, "name": "Meera", "class": "3B", "grade": "A"}, {"id": 5, "name": "Rohan
   unknown method → {"code": -32601, "message": "Method not found: students.teleport"}  (an ERROR in a 200 — the RPC way)

── 3 GraphQL — POST /graphql  { students { name grade } }
   → {"data": {"students": [{"name": "Aishwarya", "grade": "A"}, {"name": "Katrina", "grade": "A+"}, {"name": "Dipika", "grad
   ask for less → {"data": {"students": [{"name": "Aishwarya"}, {"name": "Katrina"}, {"name": "Dipika"}, {"n  (no 'class', no 'id' — you chose)

── 4 Long polling — GET /poll?since=0  (the clerk holds it open)
   → answered after 0.4s with 1 event(s): [{"seq": 1, "event": "student.created", "student": {"id": 6, "name": "Zoya", "class": "3B", "grade": "A"}}]
   the shape: ONE request that waits — no news means an empty answer and you ask again

── 5 SSE — GET /events  (a one-way stream; Last-Event-ID resumes it)
    : keep-alive
    : keep-alive
    id: 2
    event: student.created
    data: {"id": 7, "name": "Yash", "class": "3A", "grade": "C"}
   the shape: text/event-stream, id/event/data frames — and browsers resend Last-Event-ID to resume
   resuming from id 0 replays history: id: 1 | event: student.created | data: {"id": 6, "name": "Zoya", "class": "3B", "grade": "A"}

── 6 WebSocket — GET /ws  (Upgrade: websocket)
   handshake: HTTP/1.1 101 Switching Protocols · Sec-WebSocket-Accept: uNRiaq9Sfw1P3AXc4r+qyqV7Ojw=
   → 'hello'   ← {"echo": "hello", "at": 1789998291.82}
   → 'students'   ← {"students": ["Aishwarya", "Katrina", "Dipika", "Meera", "Rohan", "Zoya", "Yash"]}
   the shape: one socket, either side may speak at any time — chat, cursors, live dashboards

✅ six shapes, one dataset — the difference is who starts, how often, and how much comes back
🔍 क्रमाने काय पहावे: REST संपूर्ण resources परत देते; JSON-RPC 200 च्या आतच error देते; GraphQL नेमकी तुम्ही सांगितलेली fields देते; long polling उशिरा, एकदाच उत्तर देते; SSE एकच जोडणी ठेवते आणि प्रत्येक event ला id लावते जो browser Last-Event-ID ने पुन्हा मागतो; WebSocket 101 Switching Protocols ने upgrade होतो आणि मग दोन्हीपैकी कोणीही बोलू शकते. तोच data, सहा तारा.

⚠️ चुकीचा प्रकार निवडायला लावणाऱ्या चुका

चूकप्रत्यक्षात काय होतेत्याऐवजी हे करा
लोकप्रियतेनुसार निवडणे ("सगळे GraphQL वापरतात")दोन endpoints च्या service साठी query-खर्चाच्या मर्यादा, cache ची गुंतागुंत आणि schema ची टीम वारशाने मिळतेआधी पाच अक्षांवर ठेवा; कंटाळवाणे REST श्रेय मिळते त्यापेक्षा जास्त वेळा जिंकते
क्वचित घडणाऱ्या events साठी दर काही सेकंदांनी pollingहजारो रिकामी उत्तरे, आणि तरी उशीरwebhook (ते तुम्हाला कॉल करतात) किंवा SSE (एक उघडी लाइन)
request/response साठी WebSocketids, पुन्हा-प्रयत्न, timeouts आणि caching तुम्ही हाताने पुन्हा बांधता — वाईट रीतीनेसाधे HTTP; socket खऱ्या दुहेरी कामासाठी ठेवा
थेट browsers ला gRPCशेवटी REST किंवा gRPC-Web proxy लिहून चालवावाच लागतोकाठावर REST/JSON, services मध्ये gRPC
कॉल करणाऱ्याला उत्तर हवे असताना queuesynchrony चे नाटक करायला status-polling endpoint शोधावा लागतोsynchronously उत्तर द्या; फक्त हळू भाग रांगेत टाका
स्वाक्षरी किंवा idempotency शिवाय webhooksबनावट events, आणि दुहेरी संदेश दोनदा लागूpayload वर स्वाक्षरी करा, ती तपासा, event id नुसार दुहेरी काढा
library API ला "खरे API नाही" मानणेआवृत्तीशिवाय मोडणारे बदल जातात, आणि कॉल करणारे मोडताततिला आवृत्ती द्या, दस्तऐवज करा, deprecate करा — धडा 09 लागू होतो
🎓 लक्षात ठेवायचे एक वाक्य: API म्हणजे करार; प्रकार म्हणजे तो करार कसा प्रवास करतो एवढेच. या कोर्सने शिकवलेले सगळे — एकच error shape, idempotency, pagination, versioning, मर्यादा, auth, चाचण्या आणि docs — वरच्या मुख्य तक्त्यातल्या प्रत्येक ओळीला लागू होते.

संपूर्ण धडा 15 वाचा →

16 🧪 API चाचणीचा प्रत्येक प्रकार

काउंटर तपासण्याचे नऊ मार्ग — smoke, functional, integration, regression, load, stress, security, UI, fuzz — आणि ते स्वीकारण्याचा क्रम.

🧒 सोप्या शब्दांत

शाळा उघडण्याआधी शिपाई प्रत्येक दिव्याचे बटण एकदा दाबून पाहतो; 30 सेकंदात कळते की काही बिघडलेले नाही. हाच smoke test. बाकीचे tests खोलवर जातात: प्रत्येक खोली चालते का, खोल्या एकत्र चालतात का, सभागृहात सगळी शाळा मावते का, दुप्पट लोक आले तर काय? आधी जलद test सुरू करा, मग बाकीचे क्रमाने जोडा.

📖 नवे शब्दsmoke test — मूलभूत गोष्टी चालतात का याची जलद तपासणीregression test — जुना bug परत आला नाही याची खात्रीload test — अपेक्षित प्रमाणात एकाच वेळी अनेक usersstress test — मर्यादेपलीकडे नेऊन ते कसे बिघडते ते पाहणेfuzz test — crashes शोधण्यासाठी त्यावर विचित्र, random inputs टाकणे

🧪 काउंटर तपासण्याचे नऊ मार्ग — API testing चे प्रकार

प्रकार कोणताही असो, API त्याच नऊ पद्धतींनी तपासले जाते. प्रत्येक ओळ सांगते चाचणी काय विचारते, आणि ती या काउंटरवर कशी चालवाल. धडा 12 पहिल्या तीन बांधतो; बाकीच्या production च्या सवयी.

Smoke testing
input dataताजा serverकाउंटरकाही मोडत नाही ना?प्रत्येक बटण एकदा दाबा · 30 सेकंद · प्रत्येक push वर चालते
प्रत्येक बटण एकदा दाबा. काउंटर सुरू करा, प्रत्येक endpoint ला एक बरोबर विनंती पाठवा, आनंदी status codes अपेक्षित. इथे ते api/smoke_test.sh आहे: curl मधल्या 12 नावे दिलेल्या तपासण्या, प्रत्येक धड्याला एक — CI/CD शाळा ते प्रत्येक push वर चालवते.
Functional testing
📋functional specinput dataकाउंटरनिकालअपेक्षित resultतुलनाspec मधला प्रत्येक नियम एक case: चुकीचा email → problems सह 400, 500 नव्हे
Spec म्हणते तसे होते का? प्रत्येक गरजेचा अपेक्षित उत्तरासह एक case बनतो: दुहेरी email ला 409, key नसेल तर 401, error shape नेहमी तोच. result ची अपेक्षेशी तुलना, प्रत्येक नियमासाठी.
Integration testing
📝test plan1 · POST /v1/students2 · GET /v1/students/{id}3 · DELETE → 204 · GET → 404काउंटरनिकालअपेक्षितओळीने अनेक calls, मध्ये state वाहत — आणि database, webhook receiver, gateway सगळे खरे
अनेक calls, एक गोष्ट. विद्यार्थी नोंदवा, परत वाचा, बदला, काढून टाका, 404 ची खात्री करा: calls एकमेकांवर आणि खऱ्या शेजाऱ्यांवर (database, webhook receiver) अवलंबून. बहुतेक production bugs इथेच राहतात.
Regression testing
📋functional specतोच inputजुने ॲप · v1.4नवे ॲप · v1.5तुलनाकालची नोंदवलेली उत्तरे म्हणजे आजची अपेक्षित उत्तरे · JSON चा snapshot घ्या, diff करा
बदलाने आधी चालणारे मोडले का? तेच inputs जुन्या आणि नव्या build वर चालवा आणि उत्तरे diff करा. नोंदवलेले प्रतिसाद अपेक्षित results बनतात; कोणालाही नको असलेला बदललेला field build पाडतो.
Load testing
तपासणाराtest enginetest engineकाउंटर200 वापरकर्ते · 10 मिनिटे · वास्तववादी मिश्रणअपेक्षित traffic वर p50 / p95 / p99 latency आणि errors मोजा · k6, JMeter, hey · क्षमता शोधा
क्षमता किती? अपेक्षित traffic (आणि थोडे जास्त) load साधनाने घडवा, आणि latency percentiles, error दर आणि rate limiter पहा. जो आकडा कळतो त्यावर autoscaling आणि on-call runbook अवलंबून.
Stress testing
तपासणाराtest enginetest engineकाउंटर10× load · काहीतरी मोडेपर्यंतकुठे मोडते, कसे मोडते (429? timeouts? crashes?) — आणि स्वतःहून सावरते का?
मुद्दाम मोडेपर्यंत ढकला. अपेक्षित load च्या खूप पलीकडे, बिघाडाचा प्रकार पाहायला: सभ्य 429 आणि रांग, की timeouts आणि crash? आणि पूर थांबल्यावर ते स्वतःहून सावरते का. मोडणे ठीक; वाईट रीतीने मोडणे हाच शोध.
Security testing
🛡️security speckey नाही → 401 · चुकीची key → 403class=' OR 1=1 → 400, data नव्हे1000 विनंत्या → 429काउंटरकाही गळत नाही ना?OWASP API Top 10 · auth, object-level access, injection, rate limits, logs मधली गुपिते, TLS
प्रत्येक दार, प्रत्येक कुलूप. हॉल पासशिवाय, दुसऱ्याच्या पासने, प्रत्येक field मध्ये injection घालून, खूप विनंत्या पाठवून आत शिरायचा प्रयत्न करा. काय log होते ते तपासा. OWASP API Top 10 ही चेकलिस्ट; उत्तर नेहमी सभ्य नकारच असले पाहिजे.
UI testing
सूचना फलकप्रवेश फॉर्म भरतोकाउंटरकार्ड दिसण्याची अपेक्षाखरा browser UI चालवतो आणि UI API चालवते · Playwright · थोडे, हळू, अनमोल (UI शाळा, धडा 10)
सूचना फलकातून. खरा browser फॉर्म भरतो; UI काउंटरला बोलावते; चाचणी माणसाला काय दिसते ते तपासते. दोन शाळांच्या मध्ये राहणारे bugs सापडतात: CORS, बदललेले field नाव, कधीच न संपणारी loading स्थिती.
Fuzz testing
'' · null · -1 · 10 MB · 🧟 · {}काउंटरकाही मोडते का?400 + problems = बरोबर500 किंवा अडकणे = bugयादृच्छिक आणि विकृत input, हजारो वेळा
दचकेपर्यंत निरर्थक खाऊ घाला. यादृच्छिक आणि विकृत inputs तयार करा — रिकामे, प्रचंड, चुकीचे प्रकार, unicode — आणि हजारो पाठवा. कोणताही 500, अडकणे किंवा crash हा शोध; प्रमाणित error shape सह 400 म्हणजे काउंटर आपले काम करतोय.
🧭 स्वीकारण्याचा क्रम: प्रत्येक push वर smoke → spec मधल्या प्रत्येक नियमासाठी functional → महत्त्वाच्या गोष्टींसाठी integration → नोंदवलेली उत्तरे diff करून regression → launch आधी आणि प्रत्येक मोठ्या बदलानंतर एकदा load → काहीही सार्वजनिक होण्याआधी security → parser ला हात लावाल तेव्हा fuzz → बिघाडाचा प्रकार जाणायचा असेल तेव्हा stress → सूचना फलकातून UI, मोजके सोनेरी मार्ग.
⏪ आधी

एकाच प्रकारचा test किंवा एकही test नसेल तर मंद endpoint, security मधले छिद्र किंवा विचित्र input आधी users पर्यंत पोहोचते.

💡 काय

Counter तपासण्याच्या नऊ पद्धती: smoke, functional, integration, regression, load, stress, security, UI आणि fuzz, स्वीकारण्याच्या क्रमाने.

⚙️ कसे

Smoke test नवीन server सुरू करतो आणि प्रत्येक दिव्याचे बटण एकदा दाबून पाहतो, सुमारे 30 सेकंदात, प्रत्येक push वर.

🎯 का

प्रत्येक प्रकार वेगळे failure पकडतो, म्हणून ते क्रमाने जोडल्यास कमी मेहनतीत जास्तीत जास्त सुरक्षितता मिळते.

🚀 पुढे

हे tests प्रत्येक push वर CI मध्ये चालतात (CI/CD school), आणि खरी traffic वाढेल तसे load आणि security tests API चे रक्षण करतात.

संपूर्ण धडा 16 वाचा →

17 📈 Performance आणि monitoring

काउंटरवरचे स्टॉपवॉच — प्रत्येक route चे latency percentiles p25, p50, p75, p90, p95, p99, RED metrics, आणि Prometheus, Datadog व CloudWatch API वर कसे लक्ष ठेवतात.

🧒 सोप्या शब्दांत

शाळेच्या office counter वर एक stopwatch ठेवा आणि प्रत्येक पालकाला किती वेळ थांबावे लागले ते लिहून ठेवा. दिवसाच्या शेवटी पालकांना सर्वात कमी वाट पाहणाऱ्यापासून सर्वात जास्त वाट पाहणाऱ्यापर्यंत रांगेत उभे करा. मधला पालक म्हणजे नेहमीची वाट; शेवटाजवळचा पालक म्हणजे दुर्दैवी — आणि सरासरी त्या दुर्दैवी पालकाला लपवते.

📖 नवे शब्दlatency — विचारल्यापासून उत्तर मिळेपर्यंत किती वेळ थांबावे लागतेp50 — रांगेचा मध्य — नेहमीची वाटp95 — दर 100 पैकी फक्त 5 जणांनी यापेक्षा जास्त वाट पाहिलीSLO — पाळायचे वचन, ज्यावर alarm लावतात, उदा. 100 पैकी 95 जणांना 100 ms च्या आत उत्तरRED — दर कालखंडाला तीन प्रश्न: किती आले, किती अपयशी झाले, त्यांनी किती वाट पाहिली
1⏱️ 104 report requests, सर्वात जलद → सर्वात हळू — percentile म्हणजे या रांगेतली एक जागा050100150mean 18.9 ms — ठीक दिसतो, लाल पट्ट्या लपवतोp25 10.1p50 10.4p75 10.7p90 11.3p95 135.8p99 155.5p95 = 135.8 ms म्हणजे: दर 100 पैकी 95 जणांनी यापेक्षा कमी वाट पाहिली · p50 (median) म्हणजे नेहमीचा caller · p99 म्हणजे दुर्दैवी callerpython3 api/perf.py — आमच्या laptop वरची एक run; लाल पट्ट्या म्हणजे SIMULATED cache misses (15 पैकी 1 report)2🕵️ routes एकत्र केल्याने हळू route लपतो — p95 प्रत्येक ROUTE साठी मोजाrequestsमोजाp50p90p95p99meanसर्व routes एकत्र4000.610.510.8152.05.4GET /v1/reports/grades10410.411.3135.8155.518.9GET /v1/students/{id}2010.40.91.14.60.7GET /v1/students950.40.91.11.40.5सगळे एकत्र, p95 म्हणतो 10.8 ms — "निरोगी"फक्त report route: 135.8 msजलद student reads संख्येने जास्त आहेत आणित्याला बुडवून टाकतात — फक्त p99 ला ते लक्षात येते→ प्रत्येक route साठी एक latency metric (method + pathtemplate, ids असलेला कच्चा URL कधीच नाही)3📡 स्टॉपवॉच dashboard पर्यंत पोहोचण्याचे तीन मार्ग — आणि प्रत्येकात तोच alarm📊 Prometheus + Grafanapull: दर 15 s ला GET /metrics scrape करतोschool_api_request_duration_seconds_bucket{route="/v1/reports/grades",le="0.25"} 104🔔 histogram_quantile(0.95, …rate(…_bucket[5m])) > 0.1🐶 Datadogpush: प्रत्येक request ला UDP वरून एक DogStatsD packetschool_api.request.duration:10.16|d|#route:/v1/reports/grades,status:200🔔 percentile(last_15m):p95:school_api.request.duration{…} > 100☁️ CloudWatchpush: प्रत्येक request ला एक EMF JSON log ओळ{"_aws":{…"Metrics":[{"Name":"Latency","Unit":"Milliseconds"}]}, "Route":"GET /v1/reports/grades", "Latency":10.4}🔔 put-metric-alarm --extended-statistic p95 --threshold 100 --period 300 × 3प्रत्येक route चे RED पहा — Rate (req/s) · Errors (5xx %) · Duration (p50/p95/p99) — आणि माणसाला फक्त SLO वर page करा: "p95 < 100 ms"
⏪ आधी

Teams सरासरी response time पाहायच्या; ती 19 ms दाखवायची, तर पंधरापैकी एक caller 150 ms थांबायचा आणि तक्रार करायचा.

💡 काय

Latency percentiles: प्रत्येक request वेळेनुसार लावा; p50 म्हणजे सामान्य caller, p95 आणि p99 म्हणजे दुर्दैवी callers.

⚙️ कसे

api/perf.py 400 requests पाठवतो आणि प्रत्येक route चे p25–p99 दाखवतो; /metrics, DogStatsD आणि EMF हेच आकडे tools कडे पाठवतात.

🎯 का

सगळे एकत्र असताना p95 10.8 ms दिसला; route नुसार report 135.8 ms होता — route नुसार मोजले तरच दुरुस्त करता येते.

🚀 पुढे

SLO वर (p95 < 100 ms) एक alarm लिहा, मग हळू request सुरुवातीपासून शेवटपर्यंत trace करा — production मधली पुढची पायरी.

🧪 Try it here — काही requests हळू करा आणि कोणत्या percentile ला ते लक्षात येते ते पहा — मग alarm लिहा

संपूर्ण धडा 17 वाचा →