diff --git a/docs/hi/docs/about/index.md b/docs/hi/docs/about/index.md new file mode 100644 index 000000000..c155450a3 --- /dev/null +++ b/docs/hi/docs/about/index.md @@ -0,0 +1,3 @@ +# परिचय { #about } + +FastAPI, इसके design, प्रेरणा और और भी बहुत कुछ के बारे में। 🤓 diff --git a/docs/hi/docs/advanced/additional-responses.md b/docs/hi/docs/advanced/additional-responses.md new file mode 100644 index 000000000..410157c7a --- /dev/null +++ b/docs/hi/docs/advanced/additional-responses.md @@ -0,0 +1,247 @@ +# OpenAPI में अतिरिक्त Responses { #additional-responses-in-openapi } + +/// warning | चेतावनी + +यह एक काफ़ी advanced विषय है। + +अगर आप **FastAPI** के साथ शुरुआत कर रहे हैं, तो शायद आपको इसकी ज़रूरत न पड़े। + +/// + +आप अतिरिक्त status codes, media types, descriptions आदि के साथ अतिरिक्त responses घोषित कर सकते हैं। + +ये अतिरिक्त responses OpenAPI schema में शामिल किए जाएँगे, इसलिए वे API docs में भी दिखाई देंगे। + +लेकिन उन अतिरिक्त responses के लिए आपको यह सुनिश्चित करना होगा कि आप अपने status code और content के साथ सीधे `JSONResponse` जैसा कोई `Response` return करें। + +## `model` के साथ अतिरिक्त Response { #additional-response-with-model } + +आप अपने *path operation decorators* को `responses` parameter दे सकते हैं। + +यह एक `dict` प्राप्त करता है: keys प्रत्येक response के status codes होते हैं (जैसे `200`), और values अन्य `dict`s होते हैं जिनमें उनमें से प्रत्येक की जानकारी होती है। + +इनमें से प्रत्येक response `dict` में `model` key हो सकती है, जिसमें `response_model` की तरह एक Pydantic model होता है। + +**FastAPI** उस model को लेगा, उसका JSON Schema generate करेगा और उसे OpenAPI में सही जगह शामिल करेगा। + +उदाहरण के लिए, status code `404` और Pydantic model `Message` के साथ एक और response घोषित करने के लिए, आप लिख सकते हैं: + +{* ../../docs_src/additional_responses/tutorial001_py310.py hl[18,22] *} + +/// note | नोट + +ध्यान रखें कि आपको सीधे `JSONResponse` return करना होगा। + +/// + +/// note | नोट + +`model` key OpenAPI का हिस्सा नहीं है। + +**FastAPI** वहाँ से Pydantic model लेगा, JSON Schema generate करेगा, और उसे सही जगह रखेगा। + +सही जगह है: + +* `content` key में, जिसकी value एक और JSON object (`dict`) होती है जिसमें शामिल है: + * media type वाली एक key, जैसे `application/json`, जिसकी value एक और JSON object होती है, जिसमें शामिल है: + * एक key `schema`, जिसकी value model से JSON Schema होती है, यही सही जगह है। + * **FastAPI** इसे सीधे शामिल करने के बजाय आपके OpenAPI में किसी अन्य जगह मौजूद global JSON Schemas का reference यहाँ जोड़ता है। इस तरह, अन्य applications और clients उन JSON Schemas को सीधे उपयोग कर सकते हैं, बेहतर code generation tools प्रदान कर सकते हैं, आदि। + +/// + +इस *path operation* के लिए OpenAPI में generate किए गए responses होंगे: + +```JSON hl_lines="3-12" +{ + "responses": { + "404": { + "description": "Additional Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Message" + } + } + } + }, + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/Item" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } +} +``` + +Schemas को OpenAPI schema के अंदर किसी दूसरी जगह reference किया गया है: + +```JSON hl_lines="4-16" +{ + "components": { + "schemas": { + "Message": { + "title": "Message", + "required": [ + "message" + ], + "type": "object", + "properties": { + "message": { + "title": "Message", + "type": "string" + } + } + }, + "Item": { + "title": "Item", + "required": [ + "id", + "value" + ], + "type": "object", + "properties": { + "id": { + "title": "Id", + "type": "string" + }, + "value": { + "title": "Value", + "type": "string" + } + } + }, + "ValidationError": { + "title": "ValidationError", + "required": [ + "loc", + "msg", + "type" + ], + "type": "object", + "properties": { + "loc": { + "title": "Location", + "type": "array", + "items": { + "type": "string" + } + }, + "msg": { + "title": "Message", + "type": "string" + }, + "type": { + "title": "Error Type", + "type": "string" + } + } + }, + "HTTPValidationError": { + "title": "HTTPValidationError", + "type": "object", + "properties": { + "detail": { + "title": "Detail", + "type": "array", + "items": { + "$ref": "#/components/schemas/ValidationError" + } + } + } + } + } + } +} +``` + +## मुख्य response के लिए अतिरिक्त media types { #additional-media-types-for-the-main-response } + +आप इसी `responses` parameter का उपयोग करके उसी मुख्य response के लिए अलग-अलग media types जोड़ सकते हैं। + +उदाहरण के लिए, आप `image/png` का एक अतिरिक्त media type जोड़ सकते हैं, यह घोषित करते हुए कि आपका *path operation* एक JSON object (media type `application/json` के साथ) या एक PNG image return कर सकता है: + +{* ../../docs_src/additional_responses/tutorial002_py310.py hl[17:22,26] *} + +/// note | नोट + +ध्यान दें कि आपको image को सीधे `FileResponse` का उपयोग करके return करना होगा। + +/// + +/// note | नोट + +जब तक आप अपने `responses` parameter में स्पष्ट रूप से कोई अलग media type specify नहीं करते, FastAPI मान लेगा कि response का media type मुख्य response class (default `application/json`) जैसा ही है। + +लेकिन अगर आपने custom response class specify की है जिसका media type `None` है, तो FastAPI किसी भी ऐसे अतिरिक्त response के लिए `application/json` का उपयोग करेगा जिसके साथ कोई associated model है। + +/// + +## जानकारी को मिलाना { #combining-information } + +आप कई जगहों से response जानकारी को भी मिला सकते हैं, जिसमें `response_model`, `status_code`, और `responses` parameters शामिल हैं। + +आप default status code `200` (या ज़रूरत पड़ने पर custom code) का उपयोग करके `response_model` घोषित कर सकते हैं, और फिर उसी response के लिए अतिरिक्त जानकारी सीधे OpenAPI schema में `responses` के अंदर घोषित कर सकते हैं। + +**FastAPI** `responses` से अतिरिक्त जानकारी बनाए रखेगा, और उसे आपके model से JSON Schema के साथ मिला देगा। + +उदाहरण के लिए, आप status code `404` वाला एक response घोषित कर सकते हैं जो Pydantic model का उपयोग करता है और जिसमें custom `description` है। + +और status code `200` वाला एक response, जो आपके `response_model` का उपयोग करता है, लेकिन जिसमें custom `example` शामिल है: + +{* ../../docs_src/additional_responses/tutorial003_py310.py hl[20:31] *} + +यह सब मिलाकर आपके OpenAPI में शामिल किया जाएगा, और API docs में दिखाया जाएगा: + + + +## पहले से परिभाषित responses और custom responses को मिलाएँ { #combine-predefined-responses-and-custom-ones } + +आप कुछ पहले से परिभाषित responses रखना चाह सकते हैं जो कई *path operations* पर लागू होते हैं, लेकिन आप उन्हें प्रत्येक *path operation* के लिए ज़रूरी custom responses के साथ मिलाना चाहते हैं। + +ऐसे मामलों के लिए, आप `**dict_to_unpack` के साथ `dict` को "unpacking" करने की Python technique का उपयोग कर सकते हैं: + +```Python +old_dict = { + "old key": "old value", + "second old key": "second old value", +} +new_dict = {**old_dict, "new key": "new value"} +``` + +यहाँ, `new_dict` में `old_dict` के सभी key-value pairs के साथ नया key-value pair भी होगा: + +```Python +{ + "old key": "old value", + "second old key": "second old value", + "new key": "new value", +} +``` + +आप इस technique का उपयोग अपने *path operations* में कुछ पहले से परिभाषित responses को reuse करने और उन्हें अतिरिक्त custom responses के साथ मिलाने के लिए कर सकते हैं। + +उदाहरण के लिए: + +{* ../../docs_src/additional_responses/tutorial004_py310.py hl[11:15,24] *} + +## OpenAPI responses के बारे में अधिक जानकारी { #more-information-about-openapi-responses } + +Responses में आप ठीक-ठीक क्या शामिल कर सकते हैं, यह देखने के लिए आप OpenAPI specification में ये sections देख सकते हैं: + +* [OpenAPI Responses Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#responses-object), इसमें `Response Object` शामिल है। +* [OpenAPI Response Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#response-object), आप इसमें से कुछ भी सीधे अपने `responses` parameter के अंदर प्रत्येक response में शामिल कर सकते हैं। जिसमें `description`, `headers`, `content` (इसी के अंदर आप अलग-अलग media types और JSON Schemas घोषित करते हैं), और `links` शामिल हैं। diff --git a/docs/hi/docs/advanced/additional-status-codes.md b/docs/hi/docs/advanced/additional-status-codes.md new file mode 100644 index 000000000..bec6e4eae --- /dev/null +++ b/docs/hi/docs/advanced/additional-status-codes.md @@ -0,0 +1,41 @@ +# अतिरिक्त Status Codes { #additional-status-codes } + +default रूप से, **FastAPI** responses को `JSONResponse` का उपयोग करके return करेगा, जिसमें आपके *path operation* से return किया गया content उस `JSONResponse` के अंदर रखा जाएगा। + +यह default status code या वह status code उपयोग करेगा जो आपने अपने *path operation* में set किया है। + +## अतिरिक्त status codes { #additional-status-codes_1 } + +अगर आप मुख्य status code के अलावा अतिरिक्त status codes return करना चाहते हैं, तो आप सीधे `Response`, जैसे `JSONResponse`, return करके और अतिरिक्त status code को सीधे set करके ऐसा कर सकते हैं। + +उदाहरण के लिए, मान लीजिए कि आप एक ऐसा *path operation* रखना चाहते हैं जो items को update करने की अनुमति देता है, और सफल होने पर HTTP status code 200 "OK" return करता है। + +लेकिन आप यह भी चाहते हैं कि यह नए items को स्वीकार करे। और जब items पहले मौजूद नहीं थे, तो यह उन्हें बनाता है, और HTTP status code 201 "Created" return करता है। + +ऐसा करने के लिए, `JSONResponse` import करें, और अपना content वहीं सीधे return करें, साथ में अपनी पसंद का `status_code` set करें: + +{* ../../docs_src/additional_status_codes/tutorial001_an_py310.py hl[4,25] *} + +/// warning | चेतावनी + +जब आप सीधे `Response` return करते हैं, जैसे ऊपर के उदाहरण में, तो वह सीधे return किया जाएगा। + +इसे किसी model आदि के साथ serialize नहीं किया जाएगा। + +सुनिश्चित करें कि इसमें वही data है जो आप चाहते हैं, और values valid JSON हैं (अगर आप `JSONResponse` उपयोग कर रहे हैं)। + +/// + +/// note | तकनीकी विवरण + +आप `from starlette.responses import JSONResponse` भी उपयोग कर सकते हैं। + +**FastAPI** आपकी सुविधा के लिए, developer के रूप में, वही `starlette.responses` `fastapi.responses` के रूप में प्रदान करता है। लेकिन उपलब्ध अधिकांश responses सीधे Starlette से आते हैं। `status` के साथ भी यही है। + +/// + +## OpenAPI और API docs { #openapi-and-api-docs } + +अगर आप अतिरिक्त status codes और responses सीधे return करते हैं, तो वे OpenAPI schema (API docs) में शामिल नहीं होंगे, क्योंकि FastAPI के पास पहले से यह जानने का तरीका नहीं है कि आप क्या return करने वाले हैं। + +लेकिन आप इसे अपने code में document कर सकते हैं, उपयोग करके: [अतिरिक्त Responses](additional-responses.md)। diff --git a/docs/hi/docs/advanced/advanced-dependencies.md b/docs/hi/docs/advanced/advanced-dependencies.md new file mode 100644 index 000000000..4c6648b95 --- /dev/null +++ b/docs/hi/docs/advanced/advanced-dependencies.md @@ -0,0 +1,163 @@ +# Advanced Dependencies { #advanced-dependencies } + +## Parameterized dependencies { #parameterized-dependencies } + +अब तक हमने जो भी dependencies देखी हैं, वे एक निश्चित function या class हैं। + +लेकिन ऐसे मामले हो सकते हैं जहाँ आप dependency पर parameters सेट कर पाना चाहें, बिना कई अलग-अलग functions या classes declare किए। + +कल्पना करें कि हम एक ऐसी dependency रखना चाहते हैं जो जाँचती है कि query parameter `q` में कुछ निश्चित content है या नहीं। + +लेकिन हम उस निश्चित content को parameterize कर पाना चाहते हैं। + +## एक "callable" instance { #a-callable-instance } + +Python में किसी class के instance को "callable" बनाने का एक तरीका है। + +खुद class को नहीं (जो पहले से ही callable होती है), बल्कि उस class के एक instance को। + +ऐसा करने के लिए, हम एक method `__call__` declare करते हैं: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[12] *} + +इस मामले में, यही `__call__` है जिसे **FastAPI** अतिरिक्त parameters और sub-dependencies की जाँच के लिए उपयोग करेगा, और बाद में आपकी *path operation function* में parameter को value पास करने के लिए यही call किया जाएगा। + +## Instance को parameterize करें { #parameterize-the-instance } + +और अब, हम `__init__` का उपयोग करके instance के parameters declare कर सकते हैं जिन्हें हम dependency को "parameterize" करने के लिए उपयोग कर सकते हैं: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[9] *} + +इस मामले में, **FastAPI** कभी भी `__init__` को छुएगा या उसकी परवाह नहीं करेगा, हम इसे सीधे अपने code में उपयोग करेंगे। + +## एक instance बनाएँ { #create-an-instance } + +हम इस class का एक instance इस तरह बना सकते हैं: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[18] *} + +और इस तरह हम अपनी dependency को "parameterize" कर पाते हैं, जिसमें अब `"bar"` उसके अंदर है, attribute `checker.fixed_content` के रूप में। + +## Instance को dependency के रूप में उपयोग करें { #use-the-instance-as-a-dependency } + +फिर, हम `Depends(FixedContentQueryChecker)` के बजाय इस `checker` को `Depends(checker)` में उपयोग कर सकते हैं, क्योंकि dependency class खुद नहीं, बल्कि instance `checker` है। + +और dependency को solve करते समय, **FastAPI** इस `checker` को इस तरह call करेगा: + +```Python +checker(q="somequery") +``` + +...और जो भी यह return करेगा उसे हमारी *path operation function* में dependency की value के रूप में parameter `fixed_content_included` में पास करेगा: + +{* ../../docs_src/dependencies/tutorial011_an_py310.py hl[22] *} + +/// tip | सुझाव + +यह सब थोड़ा बनावटी लग सकता है। और अभी यह बहुत स्पष्ट नहीं हो सकता कि यह कैसे उपयोगी है। + +ये उदाहरण जानबूझकर सरल रखे गए हैं, लेकिन दिखाते हैं कि यह सब कैसे काम करता है। + +Security वाले chapters में utility functions हैं जिन्हें इसी तरीके से implement किया गया है। + +अगर आपने यह सब समझ लिया है, तो आप पहले से जानते हैं कि security के लिए वे utility tools अंदर से कैसे काम करते हैं। + +/// + +## `yield`, `HTTPException`, `except` और Background Tasks वाली Dependencies { #dependencies-with-yield-httpexception-except-and-background-tasks } + +/// warning | चेतावनी + +सबसे अधिक संभावना है कि आपको इन तकनीकी विवरणों की आवश्यकता नहीं है। + +ये विवरण मुख्य रूप से तब उपयोगी हैं जब आपके पास 0.121.0 से पुरानी FastAPI application थी और आपको `yield` वाली dependencies के साथ समस्याएँ आ रही हैं। + +/// + +`yield` वाली dependencies समय के साथ अलग-अलग use cases को संभालने और कुछ समस्याएँ ठीक करने के लिए विकसित हुई हैं, यहाँ बदले हुए व्यवहार का सारांश है। + +### `yield` और `scope` वाली Dependencies { #dependencies-with-yield-and-scope } + +Version 0.121.0 में, FastAPI ने `yield` वाली dependencies के लिए `Depends(scope="function")` का support जोड़ा। + +`Depends(scope="function")` का उपयोग करने पर, `yield` के बाद का exit code *path operation function* के समाप्त होते ही, response client को वापस भेजे जाने से पहले execute होता है। + +और `Depends(scope="request")` (default) का उपयोग करने पर, `yield` के बाद का exit code response भेजे जाने के बाद execute होता है। + +आप इसके बारे में docs में [Dependencies with `yield` - Early exit and `scope`](../tutorial/dependencies/dependencies-with-yield.md#early-exit-and-scope) में अधिक पढ़ सकते हैं। + +### `yield` और `StreamingResponse` वाली Dependencies, तकनीकी विवरण { #dependencies-with-yield-and-streamingresponse-technical-details } + +FastAPI 0.118.0 से पहले, यदि आप `yield` वाली dependency उपयोग करते थे, तो यह *path operation function* के return करने के बाद लेकिन response भेजने से ठीक पहले exit code run करती थी। + +इरादा यह था कि आवश्यक से अधिक समय तक resources को पकड़े रखने से बचा जाए, response के network से गुजरने की प्रतीक्षा करते हुए। + +इस बदलाव का अर्थ यह भी था कि यदि आपने `StreamingResponse` return किया, तो `yield` वाली dependency का exit code पहले ही run हो चुका होता। + +उदाहरण के लिए, यदि आपके पास `yield` वाली dependency में database session था, तो `StreamingResponse` data stream करते समय उस session का उपयोग नहीं कर पाता क्योंकि `yield` के बाद वाले exit code में session पहले ही बंद हो चुका होता। + +यह व्यवहार 0.118.0 में revert कर दिया गया, ताकि `yield` के बाद का exit code response भेजे जाने के बाद execute हो। + +/// note | ध्यान दें + +जैसा कि आप नीचे देखेंगे, यह version 0.106.0 से पहले के व्यवहार से बहुत मिलता-जुलता है, लेकिन कई सुधारों और corner cases के लिए bug fixes के साथ। + +/// + +#### Early Exit Code वाले Use Cases { #use-cases-with-early-exit-code } + +कुछ specific conditions वाले use cases हैं जिन्हें response भेजने से पहले `yield` वाली dependencies का exit code run करने के पुराने व्यवहार से लाभ हो सकता है। + +उदाहरण के लिए, कल्पना करें कि आपके पास ऐसा code है जो `yield` वाली dependency में database session का उपयोग केवल user verify करने के लिए करता है, लेकिन database session फिर *path operation function* में कभी उपयोग नहीं होता, केवल dependency में उपयोग होता है, **और** response भेजे जाने में लंबा समय लेता है, जैसे `StreamingResponse` जो data धीरे-धीरे भेजता है, लेकिन किसी कारण से database का उपयोग नहीं करता। + +इस मामले में, database session तब तक पकड़ा रहेगा जब तक response भेजना समाप्त नहीं हो जाता, लेकिन यदि आप इसका उपयोग नहीं करते हैं, तो इसे पकड़े रखना आवश्यक नहीं होगा। + +यह इस तरह दिख सकता है: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py *} + +Exit code, यानी `Session` का automatic closing, यहाँ: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[19:21] *} + +...response द्वारा slow data भेजना समाप्त करने के बाद run होगा: + +{* ../../docs_src/dependencies/tutorial013_an_py310.py ln[30:38] hl[31:33] *} + +लेकिन क्योंकि `generate_stream()` database session का उपयोग नहीं करता, response भेजते समय session को खुला रखना वास्तव में आवश्यक नहीं है। + +यदि आपके पास SQLModel (या SQLAlchemy) का उपयोग करते हुए यह specific use case है, तो आप session को तब explicit रूप से बंद कर सकते हैं जब आपको इसकी आगे आवश्यकता न हो: + +{* ../../docs_src/dependencies/tutorial014_an_py310.py ln[24:28] hl[28] *} + +इस तरह session database connection release कर देगा, ताकि अन्य requests उसका उपयोग कर सकें। + +यदि आपके पास कोई अलग use case है जिसे `yield` वाली dependency से early exit करने की आवश्यकता है, तो कृपया अपने specific use case और dependencies with `yield` के लिए early closing से आपको क्यों लाभ होगा, इसके साथ एक [GitHub Discussion Question](https://github.com/fastapi/fastapi/discussions/new?category=questions) बनाएँ। + +यदि dependencies with `yield` में early closing के लिए compelling use cases होते हैं, तो मैं early closing में opt in करने का नया तरीका जोड़ने पर विचार करूँगा। + +### `yield` और `except` वाली Dependencies, तकनीकी विवरण { #dependencies-with-yield-and-except-technical-details } + +FastAPI 0.110.0 से पहले, यदि आप `yield` वाली dependency उपयोग करते थे, और फिर उस dependency में `except` के साथ exception capture करते थे, और exception को फिर से raise नहीं करते थे, तो exception automatic रूप से किसी भी exception handlers या internal server error handler को raise/forward कर दिया जाता था। + +यह version 0.110.0 में बदला गया ताकि handler के बिना forwarded exceptions (internal server errors) से होने वाली unhandled memory consumption ठीक की जा सके, और इसे regular Python code के व्यवहार के साथ consistent बनाया जा सके। + +### Background Tasks और `yield` वाली Dependencies, तकनीकी विवरण { #background-tasks-and-dependencies-with-yield-technical-details } + +FastAPI 0.106.0 से पहले, `yield` के बाद exceptions raise करना संभव नहीं था, `yield` वाली dependencies में exit code response भेजे जाने के *बाद* execute होता था, इसलिए [Exception Handlers](../tutorial/handling-errors.md#install-custom-exception-handlers) पहले ही run हो चुके होते। + +इसे मुख्य रूप से इस तरह design किया गया था ताकि dependencies द्वारा "yielded" किए गए उन्हीं objects को background tasks के अंदर उपयोग किया जा सके, क्योंकि exit code background tasks के समाप्त होने के बाद execute होता था। + +यह FastAPI 0.106.0 में बदला गया, इस इरादे से कि response के network से गुजरने की प्रतीक्षा करते समय resources को पकड़े न रखा जाए। + +/// tip | सुझाव + +इसके अतिरिक्त, background task सामान्यतः logic का एक independent set होता है जिसे अलग से संभाला जाना चाहिए, अपने स्वयं के resources के साथ (जैसे उसका अपना database connection)। + +इसलिए, इस तरह आपके पास शायद अधिक साफ़ code होगा। + +/// + +यदि आप इस व्यवहार पर निर्भर थे, तो अब आपको background tasks के लिए resources background task के अंदर ही बनाने चाहिए, और internally केवल ऐसा data उपयोग करना चाहिए जो `yield` वाली dependencies के resources पर निर्भर न हो। + +उदाहरण के लिए, उसी database session का उपयोग करने के बजाय, आप background task के अंदर एक नया database session बनाएँगे, और इस नए session का उपयोग करके database से objects प्राप्त करेंगे। और फिर database से object को background task function में parameter के रूप में पास करने के बजाय, आप उस object की ID पास करेंगे और फिर background task function के अंदर object को फिर से प्राप्त करेंगे। diff --git a/docs/hi/docs/advanced/advanced-python-types.md b/docs/hi/docs/advanced/advanced-python-types.md new file mode 100644 index 000000000..d73a95fd8 --- /dev/null +++ b/docs/hi/docs/advanced/advanced-python-types.md @@ -0,0 +1,61 @@ +# उन्नत Python Types { #advanced-python-types } + +Python types के साथ काम करते समय यहाँ कुछ अतिरिक्त विचार हैं जो उपयोगी हो सकते हैं। + +## `Union` या `Optional` का उपयोग { #using-union-or-optional } + +अगर आपका code किसी कारण से `|` का उपयोग नहीं कर सकता, उदाहरण के लिए अगर यह type annotation में नहीं बल्कि `response_model=` जैसी किसी चीज़ में है, तो vertical bar (`|`) का उपयोग करने के बजाय आप `typing` से `Union` का उपयोग कर सकते हैं। + +उदाहरण के लिए, आप declare कर सकते हैं कि कोई चीज़ `str` या `None` हो सकती है: + +```python +from typing import Union + + +def say_hi(name: Union[str, None]): + print(f"Hi {name}!") +``` + +`typing` में `Optional` के साथ यह declare करने का एक shortcut भी है कि कोई चीज़ `None` हो सकती है। + +मेरे बहुत **subjective** दृष्टिकोण से एक tip यहाँ है: + +* 🚨 `Optional[SomeType]` का उपयोग करने से बचें +* इसके बजाय ✨ **`Union[SomeType, None]` का उपयोग करें** ✨। + +दोनों equivalent हैं और अंदर से वे समान हैं, लेकिन मैं `Optional` के बजाय `Union` की सलाह दूँगा क्योंकि "**optional**" शब्द से ऐसा लग सकता है कि value optional है, जबकि इसका वास्तविक अर्थ है "यह `None` हो सकता है", भले ही यह optional न हो और अभी भी required हो। + +मुझे लगता है कि `Union[SomeType, None]` अपने अर्थ के बारे में अधिक explicit है। + +यह बस शब्दों और नामों की बात है। लेकिन ये शब्द इस बात को प्रभावित कर सकते हैं कि आप और आपके teammates code के बारे में कैसे सोचते हैं। + +एक उदाहरण के रूप में, इस function को लेते हैं: + +```python +from typing import Optional + + +def say_hi(name: Optional[str]): + print(f"Hey {name}!") +``` + +parameter `name` को `Optional[str]` के रूप में define किया गया है, लेकिन यह **optional नहीं है**, आप function को parameter के बिना call नहीं कर सकते: + +```Python +say_hi() # अरे नहीं, यह error throw करता है! 😱 +``` + +`name` parameter **अभी भी required** है (*optional* नहीं) क्योंकि इसमें default value नहीं है। फिर भी, `name` value के रूप में `None` स्वीकार करता है: + +```Python +say_hi(name=None) # यह काम करता है, None valid है 🎉 +``` + +अच्छी खबर यह है कि अधिकतर मामलों में, आप types के unions को define करने के लिए बस `|` का उपयोग कर पाएँगे: + +```python +def say_hi(name: str | None): + print(f"Hey {name}!") +``` + +इसलिए, सामान्यतः आपको `Optional` और `Union` जैसे नामों के बारे में चिंता करने की ज़रूरत नहीं होती। 😎 diff --git a/docs/hi/docs/advanced/async-tests.md b/docs/hi/docs/advanced/async-tests.md new file mode 100644 index 000000000..8981d552b --- /dev/null +++ b/docs/hi/docs/advanced/async-tests.md @@ -0,0 +1,99 @@ +# Async Tests { #async-tests } + +आपने पहले ही देखा है कि दिए गए `TestClient` का उपयोग करके अपनी **FastAPI** applications को कैसे test किया जाता है। अब तक, आपने केवल synchronous tests लिखना देखा है, `async` functions का उपयोग किए बिना। + +अपने tests में asynchronous functions का उपयोग कर पाना उपयोगी हो सकता है, उदाहरण के लिए, जब आप अपने database को asynchronously query कर रहे हों। कल्पना करें कि आप अपनी FastAPI application को requests भेजना test करना चाहते हैं और फिर verify करना चाहते हैं कि आपके backend ने async database library का उपयोग करते हुए database में सही data सफलतापूर्वक लिखा है। + +आइए देखें कि हम इसे कैसे काम करवा सकते हैं। + +## pytest.mark.anyio { #pytest-mark-anyio } + +अगर हम अपने tests में asynchronous functions call करना चाहते हैं, तो हमारे test functions asynchronous होने चाहिए। AnyIO इसके लिए एक अच्छा plugin प्रदान करता है, जो हमें specify करने देता है कि कुछ test functions को asynchronously call किया जाना है। + +## HTTPX { #httpx } + +भले ही आपकी **FastAPI** application `async def` के बजाय सामान्य `def` functions का उपयोग करती हो, यह अंदर से फिर भी एक `async` application होती है। + +`TestClient` अंदर कुछ magic करता है ताकि standard pytest का उपयोग करते हुए आपकी सामान्य `def` test functions में asynchronous FastAPI application को call किया जा सके। लेकिन जब हम इसे asynchronous functions के अंदर उपयोग करते हैं, तो वह magic अब काम नहीं करता। अपने tests को asynchronously चलाने पर, हम अपने test functions के अंदर `TestClient` का उपयोग नहीं कर सकते। + +`TestClient` [HTTPX](https://www.python-httpx.org) पर आधारित है, और सौभाग्य से, हम API को test करने के लिए इसे सीधे उपयोग कर सकते हैं। + +## उदाहरण { #example } + +एक सरल उदाहरण के लिए, आइए [बड़ी Applications](../tutorial/bigger-applications.md) और [Testing](../tutorial/testing.md) में वर्णित file structure जैसी एक structure पर विचार करें: + +``` +. +├── app +│   ├── __init__.py +│   ├── main.py +│   └── test_main.py +``` + +file `main.py` में यह होगा: + +{* ../../docs_src/async_tests/app_a_py310/main.py *} + +file `test_main.py` में `main.py` के लिए tests होंगे, यह अब कुछ ऐसा दिख सकता है: + +{* ../../docs_src/async_tests/app_a_py310/test_main.py *} + +## इसे चलाएँ { #run-it } + +आप अपने tests को हमेशा की तरह इस तरह चला सकते हैं: + +
+ +```console +$ pytest + +---> 100% +``` + +
+ +## विस्तार से { #in-detail } + +marker `@pytest.mark.anyio` pytest को बताता है कि इस test function को asynchronously call किया जाना चाहिए: + +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[7] *} + +/// tip | सुझाव + +ध्यान दें कि test function अब पहले की तरह `TestClient` का उपयोग करते समय केवल `def` नहीं, बल्कि `async def` है। + +/// + +फिर हम app के साथ एक `AsyncClient` बना सकते हैं, और `await` का उपयोग करते हुए इसमें async requests भेज सकते हैं। + +{* ../../docs_src/async_tests/app_a_py310/test_main.py hl[9:12] *} + +यह इसके बराबर है: + +```Python +response = client.get('/') +``` + +...जिसका उपयोग हम `TestClient` के साथ अपनी requests बनाने के लिए करते थे। + +/// tip | सुझाव + +ध्यान दें कि हम नए `AsyncClient` के साथ async/await का उपयोग कर रहे हैं - request asynchronous है। + +/// + +/// warning | चेतावनी + +अगर आपकी application lifespan events पर निर्भर करती है, तो `AsyncClient` इन events को trigger नहीं करेगा। यह सुनिश्चित करने के लिए कि वे trigger हों, [florimondmanca/asgi-lifespan](https://github.com/florimondmanca/asgi-lifespan#usage) से `LifespanManager` का उपयोग करें। + +/// + +## अन्य asynchronous function calls { #other-asynchronous-function-calls } + +क्योंकि testing function अब asynchronous है, आप अब अपने tests में अपनी FastAPI application को requests भेजने के अलावा अन्य `async` functions को भी call (और `await`) कर सकते हैं, ठीक वैसे ही जैसे आप उन्हें अपने code में कहीं और call करते हैं। + +/// tip | सुझाव + +अगर अपने tests में asynchronous function calls integrate करते समय आपको `RuntimeError: Task attached to a different loop` मिलता है (जैसे [MongoDB's MotorClient](https://stackoverflow.com/questions/41584243/runtimeerror-task-attached-to-a-different-loop) का उपयोग करते समय), तो याद रखें कि जिन objects को event loop की जरूरत होती है, उन्हें केवल async functions के भीतर ही instantiate करें, जैसे कि `@app.on_event("startup")` callback। + +/// diff --git a/docs/hi/docs/advanced/behind-a-proxy.md b/docs/hi/docs/advanced/behind-a-proxy.md new file mode 100644 index 000000000..11bd984a2 --- /dev/null +++ b/docs/hi/docs/advanced/behind-a-proxy.md @@ -0,0 +1,466 @@ +# Proxy के पीछे { #behind-a-proxy } + +कई स्थितियों में, आप अपने FastAPI app के सामने Traefik या Nginx जैसा **proxy** उपयोग करेंगे। + +ये proxies HTTPS certificates और दूसरी चीज़ें संभाल सकते हैं। + +## Proxy Forwarded Headers { #proxy-forwarded-headers } + +आपकी application के सामने मौजूद **proxy** आम तौर पर requests को आपके **server** तक भेजने से पहले तुरंत कुछ headers सेट करेगा, ताकि server को पता चल सके कि request proxy द्वारा **forwarded** की गई थी, उसे मूल (public) URL पता चल सके, जिसमें domain शामिल हो, कि वह HTTPS उपयोग कर रहा है, आदि। + +**server** program (उदाहरण के लिए **FastAPI CLI** के जरिए **Uvicorn**) इन headers को समझने में सक्षम है, और फिर वह जानकारी आपकी application को पास कर सकता है। + +लेकिन security के लिए, क्योंकि server को यह नहीं पता कि वह किसी trusted proxy के पीछे है, वह उन headers को interpret नहीं करेगा। + +/// note | तकनीकी विवरण + +Proxy headers हैं: + +* [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For) +* [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto) +* [X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host) + +/// + +### Proxy Forwarded Headers सक्षम करें { #enable-proxy-forwarded-headers } + +आप FastAPI CLI को *CLI Option* `--forwarded-allow-ips` के साथ शुरू कर सकते हैं और वे IP addresses पास कर सकते हैं जिन पर उन forwarded headers को पढ़ने के लिए भरोसा किया जाना चाहिए। + +अगर आप इसे `--forwarded-allow-ips="*"` पर सेट करते हैं, तो यह सभी incoming IPs पर भरोसा करेगा। + +अगर आपका **server** किसी trusted **proxy** के पीछे है और केवल proxy ही उससे बात करता है, तो इससे वह उस **proxy** का जो भी IP है, उसे accept करेगा। + +
+ +```console +$ fastapi run --forwarded-allow-ips="*" + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### HTTPS के साथ Redirects { #redirects-with-https } + +उदाहरण के लिए, मान लें कि आप एक *path operation* `/items/` define करते हैं: + +{* ../../docs_src/behind_a_proxy/tutorial001_01_py310.py hl[6] *} + +अगर client `/items` पर जाने की कोशिश करता है, तो default रूप से, उसे `/items/` पर redirect किया जाएगा। + +लेकिन *CLI Option* `--forwarded-allow-ips` सेट करने से पहले यह `http://localhost:8000/items/` पर redirect कर सकता है। + +लेकिन शायद आपकी application `https://mysuperapp.com` पर hosted है, और redirection `https://mysuperapp.com/items/` पर होना चाहिए। + +अब `--proxy-headers` सेट करने से FastAPI सही location पर redirect कर पाएगा। 😎 + +``` +https://mysuperapp.com/items/ +``` + +/// tip | सुझाव + +अगर आप HTTPS के बारे में और जानना चाहते हैं, तो guide [HTTPS के बारे में](../deployment/https.md) देखें। + +/// + +### Proxy Forwarded Headers कैसे काम करते हैं { #how-proxy-forwarded-headers-work } + +यहाँ client और **application server** के बीच **proxy** द्वारा forwarded headers जोड़ने का एक visual representation है: + +```mermaid +sequenceDiagram + participant Client + participant Proxy as Proxy/Load Balancer + participant Server as FastAPI Server + + Client->>Proxy: HTTPS Request
Host: mysuperapp.com
Path: /items + + Note over Proxy: Proxy adds forwarded headers + + Proxy->>Server: HTTP Request
X-Forwarded-For: [client IP]
X-Forwarded-Proto: https
X-Forwarded-Host: mysuperapp.com
Path: /items + + Note over Server: Server interprets headers
(if --forwarded-allow-ips is set) + + Server->>Proxy: HTTP Response
with correct HTTPS URLs + + Proxy->>Client: HTTPS Response +``` + +**proxy** मूल client request को intercept करता है और request को **application server** तक पास करने से पहले खास *forwarded* headers (`X-Forwarded-*`) जोड़ता है। + +ये headers मूल request के बारे में वह जानकारी सुरक्षित रखते हैं जो अन्यथा खो जाती: + +* **X-Forwarded-For**: मूल client का IP address +* **X-Forwarded-Proto**: मूल protocol (`https`) +* **X-Forwarded-Host**: मूल host (`mysuperapp.com`) + +जब **FastAPI CLI** को `--forwarded-allow-ips` के साथ configured किया जाता है, तो यह इन headers पर भरोसा करता है और उनका उपयोग करता है, उदाहरण के लिए redirects में सही URLs generate करने के लिए। + +## Stripped path prefix वाला Proxy { #proxy-with-a-stripped-path-prefix } + +आपके पास ऐसा proxy हो सकता है जो आपकी application में एक path prefix जोड़ता हो। + +इन मामलों में आप अपनी application configure करने के लिए `root_path` का उपयोग कर सकते हैं। + +`root_path` ASGI specification द्वारा प्रदान किया गया एक mechanism है (जिस पर FastAPI, Starlette के जरिए, बना है)। + +`root_path` का उपयोग इन specific cases को handle करने के लिए किया जाता है। + +और इसका उपयोग sub-applications mount करते समय internally भी किया जाता है। + +इस case में, stripped path prefix वाला proxy होने का मतलब है कि आप अपने code में `/app` पर एक path declare कर सकते हैं, लेकिन फिर आप ऊपर एक layer (proxy) जोड़ते हैं जो आपकी **FastAPI** application को `/api/v1` जैसे path के नीचे रखेगी। + +इस case में, मूल path `/app` वास्तव में `/api/v1/app` पर serve किया जाएगा। + +हालाँकि आपका सारा code यह मानकर लिखा गया है कि सिर्फ `/app` है। + +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[6] *} + +और proxy app server (शायद FastAPI CLI के जरिए Uvicorn) तक request भेजने से पहले तुरंत **path prefix** को **"strip"** कर देगा, आपकी application को यह भरोसा दिलाते हुए कि वह `/app` पर serve हो रही है, ताकि आपको prefix `/api/v1` शामिल करने के लिए अपना सारा code update न करना पड़े। + +यहाँ तक, सब कुछ सामान्य रूप से काम करेगा। + +लेकिन फिर, जब आप integrated docs UI (frontend) खोलेंगे, तो वह OpenAPI schema को `/api/v1/openapi.json` के बजाय `/openapi.json` पर पाने की अपेक्षा करेगा। + +इसलिए, frontend (जो browser में चलता है) `/openapi.json` तक पहुँचने की कोशिश करेगा और OpenAPI schema प्राप्त नहीं कर पाएगा। + +क्योंकि हमारे app के लिए `/api/v1` का path prefix वाला proxy है, frontend को OpenAPI schema `/api/v1/openapi.json` पर fetch करना होगा। + +```mermaid +graph LR + +browser("Browser") +proxy["Proxy on http://0.0.0.0:9999/api/v1/app"] +server["Server on http://127.0.0.1:8000/app"] + +browser --> proxy +proxy --> server +``` + +/// tip | सुझाव + +IP `0.0.0.0` आम तौर पर यह बताने के लिए उपयोग किया जाता है कि program उस machine/server में उपलब्ध सभी IPs पर listen करता है। + +/// + +Docs UI को OpenAPI schema में यह declare करने की भी ज़रूरत होगी कि यह API `server` `/api/v1` (proxy के पीछे) पर स्थित है। उदाहरण के लिए: + +```JSON hl_lines="4-8" +{ + "openapi": "3.1.0", + // यहाँ और चीज़ें + "servers": [ + { + "url": "/api/v1" + } + ], + "paths": { + // यहाँ और चीज़ें + } +} +``` + +इस उदाहरण में, "Proxy" कुछ **Traefik** जैसा हो सकता है। और server **Uvicorn** के साथ FastAPI CLI जैसा हो सकता है, जो आपकी FastAPI application चला रहा है। + +### `root_path` प्रदान करना { #providing-the-root-path } + +इसे हासिल करने के लिए, आप command line option `--root-path` इस तरह उपयोग कर सकते हैं: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +अगर आप Hypercorn उपयोग करते हैं, तो उसमें भी option `--root-path` है। + +/// note | तकनीकी विवरण + +ASGI specification इस use case के लिए `root_path` define करती है। + +और `--root-path` command line option वही `root_path` प्रदान करता है। + +/// + +### वर्तमान `root_path` जाँचना { #checking-the-current-root-path } + +आप प्रत्येक request के लिए आपकी application द्वारा उपयोग किया गया वर्तमान `root_path` प्राप्त कर सकते हैं, यह `scope` dictionary का हिस्सा है (जो ASGI spec का हिस्सा है)। + +यहाँ हम इसे केवल demonstration purposes के लिए message में शामिल कर रहे हैं। + +{* ../../docs_src/behind_a_proxy/tutorial001_py310.py hl[8] *} + +फिर, अगर आप Uvicorn को इस तरह शुरू करते हैं: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +Response कुछ ऐसा होगा: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +### FastAPI app में `root_path` सेट करना { #setting-the-root-path-in-the-fastapi-app } + +वैकल्पिक रूप से, अगर आपके पास `--root-path` या equivalent जैसा command line option देने का तरीका नहीं है, तो आप अपनी FastAPI app बनाते समय `root_path` parameter सेट कर सकते हैं: + +{* ../../docs_src/behind_a_proxy/tutorial002_py310.py hl[3] *} + +`root_path` को `FastAPI` में पास करना, Uvicorn या Hypercorn को `--root-path` command line option पास करने के equivalent होगा। + +### `root_path` के बारे में { #about-root-path } + +ध्यान रखें कि server (Uvicorn) उस `root_path` का उपयोग app को पास करने के अलावा किसी और चीज़ के लिए नहीं करेगा। + +लेकिन अगर आप अपने browser में [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app) पर जाते हैं, तो आपको normal response दिखाई देगा: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +इसलिए, यह `http://127.0.0.1:8000/api/v1/app` पर access किए जाने की अपेक्षा नहीं करेगा। + +Uvicorn अपेक्षा करेगा कि proxy Uvicorn को `http://127.0.0.1:8000/app` पर access करे, और फिर ऊपर extra `/api/v1` prefix जोड़ना proxy की जिम्मेदारी होगी। + +## Stripped path prefix वाले proxies के बारे में { #about-proxies-with-a-stripped-path-prefix } + +ध्यान रखें कि stripped path prefix वाला proxy इसे configure करने के तरीकों में से केवल एक है। + +शायद कई cases में default यह होगा कि proxy के पास stripped path prefix नहीं होगा। + +ऐसे case में (बिना stripped path prefix के), proxy कुछ `https://myawesomeapp.com` जैसा listen करेगा, और फिर अगर browser `https://myawesomeapp.com/api/v1/app` पर जाता है और आपका server (जैसे Uvicorn) `http://127.0.0.1:8000` पर listen करता है, तो proxy (बिना stripped path prefix के) Uvicorn को उसी path पर access करेगा: `http://127.0.0.1:8000/api/v1/app`। + +## Traefik के साथ local testing { #testing-locally-with-traefik } + +आप [Traefik](https://docs.traefik.io/) का उपयोग करके stripped path prefix के साथ experiment आसानी से locally चला सकते हैं। + +[Traefik download करें](https://github.com/containous/traefik/releases), यह एक single binary है, आप compressed file extract कर सकते हैं और इसे सीधे terminal से चला सकते हैं। + +फिर `traefik.toml` नाम की file बनाएँ जिसमें यह हो: + +```TOML hl_lines="3" +[entryPoints] + [entryPoints.http] + address = ":9999" + +[providers] + [providers.file] + filename = "routes.toml" +``` + +यह Traefik को port 9999 पर listen करने और दूसरी file `routes.toml` उपयोग करने के लिए कहता है। + +/// tip | सुझाव + +हम standard HTTP port 80 के बजाय port 9999 उपयोग कर रहे हैं ताकि आपको इसे admin (`sudo`) privileges के साथ न चलाना पड़े। + +/// + +अब वह दूसरी file `routes.toml` बनाएँ: + +```TOML hl_lines="5 12 20" +[http] + [http.middlewares] + + [http.middlewares.api-stripprefix.stripPrefix] + prefixes = ["/api/v1"] + + [http.routers] + + [http.routers.app-http] + entryPoints = ["http"] + service = "app" + rule = "PathPrefix(`/api/v1`)" + middlewares = ["api-stripprefix"] + + [http.services] + + [http.services.app] + [http.services.app.loadBalancer] + [[http.services.app.loadBalancer.servers]] + url = "http://127.0.0.1:8000" +``` + +यह file Traefik को path prefix `/api/v1` उपयोग करने के लिए configure करती है। + +और फिर Traefik अपनी requests को `http://127.0.0.1:8000` पर चल रहे आपके Uvicorn पर redirect करेगा। + +अब Traefik शुरू करें: + +
+ +```console +$ ./traefik --configFile=traefik.toml + +INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml +``` + +
+ +और अब `--root-path` option का उपयोग करके अपना app शुरू करें: + +
+ +```console +$ fastapi run main.py --forwarded-allow-ips="*" --root-path /api/v1 + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +### Responses जाँचें { #check-the-responses } + +अब, अगर आप Uvicorn के port वाले URL पर जाते हैं: [http://127.0.0.1:8000/app](http://127.0.0.1:8000/app), तो आपको normal response दिखाई देगा: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +/// tip | सुझाव + +ध्यान दें कि भले ही आप इसे `http://127.0.0.1:8000/app` पर access कर रहे हैं, यह option `--root-path` से लिया गया `/api/v1` का `root_path` दिखाता है। + +/// + +और अब Traefik के port वाले URL को खोलें, जिसमें path prefix शामिल है: [http://127.0.0.1:9999/api/v1/app](http://127.0.0.1:9999/api/v1/app)। + +हमें वही response मिलता है: + +```JSON +{ + "message": "Hello World", + "root_path": "/api/v1" +} +``` + +लेकिन इस बार proxy द्वारा प्रदान किए गए prefix path वाले URL पर: `/api/v1`। + +बेशक, यहाँ विचार यह है कि हर कोई app को proxy के जरिए access करेगा, इसलिए path prefix `/api/v1` वाला version "correct" है। + +और बिना path prefix वाला version (`http://127.0.0.1:8000/app`), जो सीधे Uvicorn द्वारा प्रदान किया गया है, केवल _proxy_ (Traefik) के access के लिए होगा। + +यह दिखाता है कि Proxy (Traefik) path prefix का उपयोग कैसे करता है और server (Uvicorn) option `--root-path` से `root_path` का उपयोग कैसे करता है। + +### Docs UI जाँचें { #check-the-docs-ui } + +लेकिन यहाँ मज़ेदार हिस्सा है। ✨ + +App को access करने का "official" तरीका उस path prefix वाले proxy के जरिए होगा जिसे हमने define किया है। इसलिए, जैसा कि हम अपेक्षा करेंगे, अगर आप Uvicorn द्वारा सीधे serve किया गया docs UI try करते हैं, URL में path prefix के बिना, तो यह काम नहीं करेगा, क्योंकि यह proxy के जरिए access किए जाने की अपेक्षा करता है। + +आप इसे [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) पर देख सकते हैं: + + + +लेकिन अगर हम port `9999` वाले proxy का उपयोग करके "official" URL पर, `/api/v1/docs` पर docs UI access करते हैं, तो यह सही तरीके से काम करता है! 🎉 + +आप इसे [http://127.0.0.1:9999/api/v1/docs](http://127.0.0.1:9999/api/v1/docs) पर देख सकते हैं: + + + +बिल्कुल जैसा हम चाहते थे। ✔️ + +ऐसा इसलिए है क्योंकि FastAPI इस `root_path` का उपयोग OpenAPI में default `server` बनाने के लिए करता है, जिसमें `root_path` द्वारा दिया गया URL होता है। + +## अतिरिक्त servers { #additional-servers } + +/// warning | चेतावनी + +यह एक अधिक advanced use case है। चाहें तो इसे skip कर सकते हैं। + +/// + +Default रूप से, **FastAPI** OpenAPI schema में `root_path` के URL वाला एक `server` बनाएगा। + +लेकिन आप अन्य alternative `servers` भी प्रदान कर सकते हैं, उदाहरण के लिए अगर आप चाहते हैं कि *वही* docs UI staging और production environment दोनों के साथ interact करे। + +अगर आप `servers` की custom list पास करते हैं और कोई `root_path` है (क्योंकि आपकी API proxy के पीछे रहती है), तो **FastAPI** list की शुरुआत में इस `root_path` के साथ एक "server" insert करेगा। + +उदाहरण के लिए: + +{* ../../docs_src/behind_a_proxy/tutorial003_py310.py hl[4:7] *} + +यह इस तरह का OpenAPI schema generate करेगा: + +```JSON hl_lines="5-7" +{ + "openapi": "3.1.0", + // यहाँ और चीज़ें + "servers": [ + { + "url": "/api/v1" + }, + { + "url": "https://stag.example.com", + "description": "Staging environment" + }, + { + "url": "https://prod.example.com", + "description": "Production environment" + } + ], + "paths": { + // यहाँ और चीज़ें + } +} +``` + +/// tip | सुझाव + +ध्यान दें कि `/api/v1` के `url` value वाला auto-generated server `root_path` से लिया गया है। + +/// + +[http://127.0.0.1:9999/api/v1/docs](http://127.0.0.1:9999/api/v1/docs) पर docs UI में यह ऐसा दिखेगा: + + + +/// tip | सुझाव + +Docs UI आपके द्वारा चुने गए server के साथ interact करेगा। + +/// + +/// note | तकनीकी विवरण + +OpenAPI specification में `servers` property optional है। + +अगर आप `servers` parameter specify नहीं करते और `root_path` `/` के बराबर है, तो generated OpenAPI schema में `servers` property default रूप से पूरी तरह omit कर दी जाएगी, जो `/` के `url` value वाले single server के equivalent है। + +/// + +### `root_path` से automatic server disable करें { #disable-automatic-server-from-root-path } + +अगर आप नहीं चाहते कि **FastAPI** `root_path` का उपयोग करके automatic server शामिल करे, तो आप parameter `root_path_in_servers=False` उपयोग कर सकते हैं: + +{* ../../docs_src/behind_a_proxy/tutorial004_py310.py hl[9] *} + +और फिर यह उसे OpenAPI schema में शामिल नहीं करेगा। + +## Sub-application mount करना { #mounting-a-sub-application } + +अगर आपको `root_path` वाले proxy का उपयोग करते हुए भी sub-application mount करनी है (जैसा कि [Sub Applications - Mounts](sub-applications.md) में बताया गया है), तो आप इसे सामान्य रूप से कर सकते हैं, जैसा कि आप अपेक्षा करेंगे। + +FastAPI internally `root_path` का smart तरीके से उपयोग करेगा, इसलिए यह बस काम करेगा। ✨ diff --git a/docs/hi/docs/advanced/custom-response.md b/docs/hi/docs/advanced/custom-response.md new file mode 100644 index 000000000..8655618f2 --- /dev/null +++ b/docs/hi/docs/advanced/custom-response.md @@ -0,0 +1,273 @@ +# कस्टम Response - HTML, Stream, File, अन्य { #custom-response-html-stream-file-others } + +Default रूप से, **FastAPI** JSON responses लौटाएगा। + +आप [सीधे Response लौटाएँ](response-directly.md) में दिखाए गए अनुसार सीधे `Response` लौटाकर इसे override कर सकते हैं। + +लेकिन अगर आप सीधे `Response` लौटाते हैं (या कोई subclass, जैसे `JSONResponse`), तो data अपने आप convert नहीं होगा (भले ही आप `response_model` declare करें), और documentation अपने आप generate नहीं होगी (उदाहरण के लिए, generated OpenAPI के हिस्से के रूप में HTTP header `Content-Type` में specific "media type" शामिल करना)। + +लेकिन आप *path operation decorator* में `response_class` parameter का उपयोग करके वह `Response` भी declare कर सकते हैं जिसे आप उपयोग करना चाहते हैं (जैसे कोई भी `Response` subclass)। + +आप अपनी *path operation function* से जो contents लौटाते हैं, उन्हें उस `Response` के अंदर रख दिया जाएगा। + +/// note | नोट + +यदि आप बिना media type वाली response class का उपयोग करते हैं, तो FastAPI अपेक्षा करेगा कि आपके response में कोई content न हो, इसलिए यह अपने generated OpenAPI docs में response format को document नहीं करेगा। + +/// + +## JSON Responses { #json-responses } + +Default रूप से FastAPI JSON responses लौटाता है। + +यदि आप [Response Model](../tutorial/response-model.md) declare करते हैं तो FastAPI Pydantic का उपयोग करके data को JSON में serialize करने के लिए उसका उपयोग करेगा। + +यदि आप response model declare नहीं करते हैं, तो FastAPI [JSON Compatible Encoder](../tutorial/encoder.md) में समझाए गए `jsonable_encoder` का उपयोग करेगा और उसे `JSONResponse` में रखेगा। + +यदि आप JSON media type (`application/json`) के साथ `response_class` declare करते हैं, जैसा कि `JSONResponse` के साथ होता है, तो आपके द्वारा लौटाया गया data आपकी *path operation decorator* में declare किए गए किसी भी Pydantic `response_model` के साथ अपने आप convert (और filter) हो जाएगा। लेकिन data Pydantic के साथ JSON bytes में serialize नहीं होगा, इसके बजाय इसे `jsonable_encoder` के साथ convert किया जाएगा और फिर `JSONResponse` class को pass किया जाएगा, जो Python की standard JSON library का उपयोग करके इसे bytes में serialize करेगी। + +### JSON Performance { #json-performance } + +संक्षेप में, यदि आप maximum performance चाहते हैं, तो [Response Model](../tutorial/response-model.md) का उपयोग करें और *path operation decorator* में `response_class` declare न करें। + +{* ../../docs_src/response_model/tutorial001_01_py310.py ln[15:17] hl[16] *} + +## HTML Response { #html-response } + +**FastAPI** से सीधे HTML के साथ response लौटाने के लिए, `HTMLResponse` का उपयोग करें। + +* `HTMLResponse` import करें। +* अपने *path operation decorator* के parameter `response_class` के रूप में `HTMLResponse` pass करें। + +{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *} + +/// note | नोट + +Parameter `response_class` का उपयोग response के "media type" को define करने के लिए भी किया जाएगा। + +इस मामले में, HTTP header `Content-Type` को `text/html` पर set किया जाएगा। + +और इसे OpenAPI में इसी तरह document किया जाएगा। + +/// + +### `Response` लौटाएँ { #return-a-response } + +जैसा कि [सीधे Response लौटाएँ](response-directly.md) में देखा गया है, आप अपनी *path operation* में response को सीधे लौटाकर भी override कर सकते हैं। + +ऊपर वाला वही उदाहरण, जो `HTMLResponse` लौटाता है, इस तरह दिख सकता है: + +{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *} + +/// warning | चेतावनी + +आपकी *path operation function* द्वारा सीधे लौटाया गया `Response` OpenAPI में document नहीं होगा (उदाहरण के लिए, `Content-Type` document नहीं होगा) और automatic interactive docs में visible नहीं होगा। + +/// + +/// note | नोट + +बेशक, वास्तविक `Content-Type` header, status code, आदि, आपके द्वारा लौटाए गए `Response` object से आएँगे। + +/// + +### OpenAPI में document करें और `Response` override करें { #document-in-openapi-and-override-response } + +यदि आप function के अंदर से response को override करना चाहते हैं लेकिन साथ ही OpenAPI में "media type" document करना चाहते हैं, तो आप `response_class` parameter का उपयोग कर सकते हैं और `Response` object भी लौटा सकते हैं। + +तब `response_class` का उपयोग केवल OpenAPI *path operation* को document करने के लिए किया जाएगा, लेकिन आपका `Response` जैसा है वैसा ही उपयोग किया जाएगा। + +#### सीधे `HTMLResponse` लौटाएँ { #return-an-htmlresponse-directly } + +उदाहरण के लिए, यह कुछ ऐसा हो सकता है: + +{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *} + +इस उदाहरण में, function `generate_html_response()` पहले से ही HTML को `str` में लौटाने के बजाय `Response` generate करके लौटाता है। + +`generate_html_response()` को call करने का result लौटाकर, आप पहले से ही एक `Response` लौटा रहे हैं जो default **FastAPI** behavior को override करेगा। + +लेकिन क्योंकि आपने `response_class` में भी `HTMLResponse` pass किया है, **FastAPI** को पता होगा कि इसे OpenAPI और interactive docs में `text/html` के साथ HTML के रूप में कैसे document करना है: + + + +## उपलब्ध responses { #available-responses } + +यहाँ कुछ उपलब्ध responses दिए गए हैं। + +ध्यान रखें कि आप कुछ और लौटाने के लिए `Response` का उपयोग कर सकते हैं, या custom sub-class भी बना सकते हैं। + +/// note | तकनीकी विवरण + +आप `from starlette.responses import HTMLResponse` भी उपयोग कर सकते हैं। + +**FastAPI** आपकी सुविधा के लिए, developer के रूप में, वही `starlette.responses` `fastapi.responses` के रूप में प्रदान करता है। लेकिन अधिकांश उपलब्ध responses सीधे Starlette से आते हैं। + +/// + +### `Response` { #response } + +मुख्य `Response` class, बाकी सभी responses इससे inherit करते हैं। + +आप इसे सीधे लौटा सकते हैं। + +यह निम्नलिखित parameters accept करता है: + +* `content` - एक `str` या `bytes`। +* `status_code` - एक `int` HTTP status code। +* `headers` - strings का एक `dict`। +* `media_type` - media type बताने वाला एक `str`। उदाहरण के लिए `"text/html"`। + +FastAPI (असल में Starlette) अपने आप एक Content-Length header शामिल करेगा। यह `media_type` के आधार पर Content-Type header भी शामिल करेगा और text types के लिए charset append करेगा। + +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} + +### `HTMLResponse` { #htmlresponse } + +कुछ text या bytes लेता है और HTML response लौटाता है, जैसा आपने ऊपर पढ़ा। + +### `PlainTextResponse` { #plaintextresponse } + +कुछ text या bytes लेता है और plain text response लौटाता है। + +{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *} + +### `JSONResponse` { #jsonresponse } + +कुछ data लेता है और `application/json` encoded response लौटाता है। + +जैसा आपने ऊपर पढ़ा, यह **FastAPI** में उपयोग किया जाने वाला default response है। + +/// note | तकनीकी विवरण + +लेकिन यदि आप response model या return type declare करते हैं, तो उसका उपयोग सीधे data को JSON में serialize करने के लिए किया जाएगा, और JSON के लिए सही media type वाला response सीधे लौटाया जाएगा, `JSONResponse` class का उपयोग किए बिना। + +यह best performance पाने का ideal तरीका है। + +/// + +### `RedirectResponse` { #redirectresponse } + +HTTP redirect लौटाता है। Default रूप से 307 status code (Temporary Redirect) का उपयोग करता है। + +आप सीधे `RedirectResponse` लौटा सकते हैं: + +{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *} + +--- + +या आप इसे `response_class` parameter में उपयोग कर सकते हैं: + + +{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *} + +यदि आप ऐसा करते हैं, तो आप अपनी *path operation* function से URL सीधे लौटा सकते हैं। + +इस मामले में, उपयोग किया गया `status_code` `RedirectResponse` के लिए default वाला होगा, जो `307` है। + +--- + +आप `status_code` parameter को `response_class` parameter के साथ combine करके भी उपयोग कर सकते हैं: + +{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *} + +### `StreamingResponse` { #streamingresponse } + +एक async generator या सामान्य generator/iterator (`yield` वाली function) लेता है और response body को stream करता है। + +{* ../../docs_src/custom_response/tutorial007_py310.py hl[3,16] *} + +/// note | तकनीकी विवरण + +एक `async` task केवल तब cancel किया जा सकता है जब वह किसी `await` तक पहुँचता है। यदि कोई `await` नहीं है, तो generator (`yield` वाली function) ठीक से cancel नहीं हो सकता और cancellation request किए जाने के बाद भी चलना जारी रख सकता है। + +चूँकि इस छोटे उदाहरण को किसी `await` statement की आवश्यकता नहीं है, हम event loop को cancellation handle करने का अवसर देने के लिए `await anyio.sleep(0)` जोड़ते हैं। + +यह बड़े या infinite streams के साथ और भी अधिक महत्वपूर्ण होगा। + +/// + +/// tip | टिप + +सीधे `StreamingResponse` लौटाने के बजाय, आपको शायद [Stream Data](./stream-data.md) में दिए गए style का पालन करना चाहिए, यह कहीं अधिक सुविधाजनक है और आपके लिए पर्दे के पीछे cancellation handle करता है। + +यदि आप JSON Lines stream कर रहे हैं, तो [Stream JSON Lines](../tutorial/stream-json-lines.md) tutorial का पालन करें। + +/// + +### `FileResponse` { #fileresponse } + +एक file को response के रूप में asynchronously stream करता है। + +Instantiate करने के लिए अन्य response types की तुलना में अलग set of arguments लेता है: + +* `path` - stream की जाने वाली file का file path। +* `headers` - dictionary के रूप में शामिल किए जाने वाले कोई भी custom headers। +* `media_type` - media type बताने वाली string। यदि unset है, तो media type infer करने के लिए filename या path का उपयोग किया जाएगा। +* `filename` - यदि set है, तो इसे response `Content-Disposition` में शामिल किया जाएगा। + +File responses में उपयुक्त `Content-Length`, `Last-Modified` और `ETag` headers शामिल होंगे। + +{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *} + +आप `response_class` parameter का उपयोग भी कर सकते हैं: + +{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *} + +इस मामले में, आप अपनी *path operation* function से file path सीधे लौटा सकते हैं। + +## Custom response class { #custom-response-class } + +आप `Response` से inherit करके और उसका उपयोग करके अपनी खुद की custom response class बना सकते हैं। + +उदाहरण के लिए, मान लें कि आप कुछ settings के साथ [`orjson`](https://github.com/ijl/orjson) का उपयोग करना चाहते हैं। + +मान लें आप चाहते हैं कि यह indented और formatted JSON लौटाए, इसलिए आप orjson option `orjson.OPT_INDENT_2` का उपयोग करना चाहते हैं। + +आप `CustomORJSONResponse` बना सकते हैं। आपको मुख्य रूप से `Response.render(content)` method बनाना है जो content को `bytes` के रूप में लौटाता है: + +{* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *} + +अब यह लौटाने के बजाय: + +```json +{"message": "Hello World"} +``` + +...यह response लौटाएगा: + +```json +{ + "message": "Hello World" +} +``` + +बेशक, JSON formatting की तुलना में इसका लाभ उठाने के लिए आपको शायद कहीं बेहतर तरीके मिलेंगे। 😉 + +### `orjson` या Response Model { #orjson-or-response-model } + +यदि आप performance खोज रहे हैं, तो शायद `orjson` response की तुलना में [Response Model](../tutorial/response-model.md) का उपयोग करना आपके लिए बेहतर होगा। + +Response model के साथ, FastAPI data को JSON में serialize करने के लिए Pydantic का उपयोग करेगा, intermediate steps के बिना, जैसे `jsonable_encoder` के साथ convert करना, जो किसी भी अन्य मामले में होता। + +और अंदर से, Pydantic JSON में serialize करने के लिए `orjson` जैसे ही underlying Rust mechanisms का उपयोग करता है, इसलिए response model के साथ आपको पहले से ही best performance मिल जाएगी। + +## Default response class { #default-response-class } + +**FastAPI** class instance या `APIRouter` बनाते समय आप specify कर सकते हैं कि default रूप से कौन-सी response class उपयोग करनी है। + +इसे define करने वाला parameter `default_response_class` है। + +नीचे दिए गए उदाहरण में, **FastAPI** सभी *path operations* में JSON के बजाय default रूप से `HTMLResponse` का उपयोग करेगा। + +{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *} + +/// tip | टिप + +आप पहले की तरह *path operations* में अब भी `response_class` override कर सकते हैं। + +/// + +## अतिरिक्त documentation { #additional-documentation } + +आप `responses` का उपयोग करके OpenAPI में media type और कई अन्य details भी declare कर सकते हैं: [OpenAPI में अतिरिक्त Responses](additional-responses.md)। diff --git a/docs/hi/docs/advanced/dataclasses.md b/docs/hi/docs/advanced/dataclasses.md new file mode 100644 index 000000000..55e487691 --- /dev/null +++ b/docs/hi/docs/advanced/dataclasses.md @@ -0,0 +1,95 @@ +# Dataclasses का उपयोग { #using-dataclasses } + +FastAPI **Pydantic** के ऊपर बनाया गया है, और मैंने आपको दिखाया है कि requests और responses घोषित करने के लिए Pydantic models का उपयोग कैसे करें। + +लेकिन FastAPI उसी तरह [`dataclasses`](https://docs.python.org/3/library/dataclasses.html) का उपयोग भी support करता है: + +{* ../../docs_src/dataclasses_/tutorial001_py310.py hl[1,6:11,18:19] *} + +यह अभी भी **Pydantic** की वजह से support किया जाता है, क्योंकि इसमें [`dataclasses` के लिए internal support](https://docs.pydantic.dev/latest/concepts/dataclasses/#use-of-stdlib-dataclasses-with-basemodel) है। + +इसलिए, ऊपर दिए गए code में भी, जो Pydantic का स्पष्ट रूप से उपयोग नहीं करता, FastAPI उन standard dataclasses को Pydantic की अपनी तरह की dataclasses में बदलने के लिए Pydantic का उपयोग कर रहा है। + +और निश्चित रूप से, यह इन्हें भी support करता है: + +* data validation +* data serialization +* data documentation, आदि। + +यह Pydantic models की तरह ही काम करता है। और अंदर से यह वास्तव में उसी तरह, Pydantic का उपयोग करके हासिल किया जाता है। + +/// note | नोट + +ध्यान रखें कि dataclasses वह सब कुछ नहीं कर सकतीं जो Pydantic models कर सकते हैं। + +इसलिए, आपको अभी भी Pydantic models का उपयोग करना पड़ सकता है। + +लेकिन अगर आपके पास बहुत सारी dataclasses पहले से मौजूद हैं, तो FastAPI का उपयोग करके web API को power देने के लिए उनका उपयोग करने की यह एक अच्छी तरकीब है। 🤓 + +/// + +## `response_model` में Dataclasses { #dataclasses-in-response-model } + +आप `response_model` parameter में भी `dataclasses` का उपयोग कर सकते हैं: + +{* ../../docs_src/dataclasses_/tutorial002_py310.py hl[1,6:12,18] *} + +dataclass अपने आप Pydantic dataclass में बदल जाएगी। + +इस तरह, उसका schema API docs के user interface में दिखाई देगा: + + + +## Nested Data Structures में Dataclasses { #dataclasses-in-nested-data-structures } + +आप nested data structures बनाने के लिए `dataclasses` को अन्य type annotations के साथ भी जोड़ सकते हैं। + +कुछ मामलों में, आपको अभी भी Pydantic के `dataclasses` वाले version का उपयोग करना पड़ सकता है। उदाहरण के लिए, अगर automatically generated API documentation में errors हों। + +उस स्थिति में, आप standard `dataclasses` को बस `pydantic.dataclasses` से बदल सकते हैं, जो एक drop-in replacement है: + +{* ../../docs_src/dataclasses_/tutorial003_py310.py hl[1,4,7:10,13:16,22:24,27] *} + +1. हम अभी भी standard `dataclasses` से `field` import करते हैं। + +2. `pydantic.dataclasses`, `dataclasses` के लिए एक drop-in replacement है। + +3. `Author` dataclass में `Item` dataclasses की एक list शामिल है। + +4. `Author` dataclass को `response_model` parameter के रूप में उपयोग किया गया है। + +5. आप request body के रूप में dataclasses के साथ अन्य standard type annotations का उपयोग कर सकते हैं। + + इस मामले में, यह `Item` dataclasses की एक list है। + +6. यहाँ हम एक dictionary return कर रहे हैं जिसमें `items` है, जो dataclasses की एक list है। + + FastAPI अभी भी data को JSON में serialize करने में सक्षम है। + +7. यहाँ `response_model`, `Author` dataclasses की list के type annotation का उपयोग कर रहा है। + + फिर से, आप `dataclasses` को standard type annotations के साथ जोड़ सकते हैं। + +8. ध्यान दें कि यह *path operation function* `async def` की बजाय सामान्य `def` का उपयोग करता है। + + हमेशा की तरह, FastAPI में आप आवश्यकता के अनुसार `def` और `async def` को जोड़ सकते हैं। + + अगर आपको यह याद दिलाने की आवश्यकता है कि किसे कब उपयोग करना है, तो [`async` और `await`](../async.md#in-a-hurry) के docs में _"जल्दी में हैं?"_ section देखें। + +9. यह *path operation function* dataclasses return नहीं कर रहा है (हालाँकि कर सकता था), बल्कि internal data वाली dictionaries की list return कर रहा है। + + FastAPI response को बदलने के लिए `response_model` parameter (जिसमें dataclasses शामिल हैं) का उपयोग करेगा। + +आप जटिल data structures बनाने के लिए `dataclasses` को कई अलग-अलग combinations में अन्य type annotations के साथ जोड़ सकते हैं। + +अधिक विशिष्ट विवरण देखने के लिए ऊपर दिए गए in-code annotation tips देखें। + +## और जानें { #learn-more } + +आप `dataclasses` को अन्य Pydantic models के साथ भी जोड़ सकते हैं, उनसे inherit कर सकते हैं, उन्हें अपने models में शामिल कर सकते हैं, आदि। + +अधिक जानने के लिए, [dataclasses के बारे में Pydantic docs](https://docs.pydantic.dev/latest/concepts/dataclasses/) देखें। + +## Version { #version } + +यह FastAPI version `0.67.0` से उपलब्ध है। 🔖 diff --git a/docs/hi/docs/advanced/events.md b/docs/hi/docs/advanced/events.md new file mode 100644 index 000000000..05afd4e1c --- /dev/null +++ b/docs/hi/docs/advanced/events.md @@ -0,0 +1,165 @@ +# Lifespan Events { #lifespan-events } + +आप ऐसी logic (code) define कर सकते हैं जिसे application के **starts up** होने से पहले execute किया जाना चाहिए। इसका मतलब है कि यह code application के **requests receive करना शुरू करने से पहले**, **एक बार** execute होगा। + +उसी तरह, आप ऐसी logic (code) define कर सकते हैं जिसे application के **shutting down** होने पर execute किया जाना चाहिए। इस मामले में, यह code संभवतः **कई requests** handle करने के **बाद**, **एक बार** execute होगा। + +क्योंकि यह code application के requests लेना **शुरू** करने से पहले, और requests handle करना **पूरा** करने के तुरंत बाद execute होता है, यह पूरी application **lifespan** को cover करता है (शब्द "lifespan" थोड़ी देर में महत्वपूर्ण होगा 😉)। + +यह उन **resources** को setup करने के लिए बहुत उपयोगी हो सकता है जिनकी आपको पूरी app में जरूरत होती है, और जो requests के बीच **shared** होते हैं, और/या जिन्हें आपको बाद में **clean up** करना होता है। उदाहरण के लिए, database connection pool, या कोई shared machine learning model load करना। + +## Use Case { #use-case } + +आइए एक उदाहरण **use case** से शुरू करते हैं और फिर देखते हैं कि इसे इससे कैसे solve किया जाए। + +मान लीजिए कि आपके पास कुछ **machine learning models** हैं जिन्हें आप requests handle करने के लिए use करना चाहते हैं। 🤖 + +वही models requests के बीच shared हैं, इसलिए, यह हर request के लिए एक model, या हर user के लिए एक model या ऐसा कुछ नहीं है। + +मान लीजिए कि model load करने में **काफी समय लग सकता है**, क्योंकि उसे disk से बहुत सारा **data** read करना होता है। इसलिए आप इसे हर request के लिए नहीं करना चाहते। + +आप इसे module/file के top level पर load कर सकते हैं, लेकिन इसका मतलब यह भी होगा कि अगर आप सिर्फ एक simple automated test run कर रहे हैं, तब भी यह **model load** करेगा, और फिर वह test **slow** होगा क्योंकि code के किसी independent part को run कर पाने से पहले उसे model load होने का इंतजार करना पड़ेगा। + +यही हम solve करेंगे, चलिए model को requests handle होने से पहले load करते हैं, लेकिन केवल application के requests receive करना शुरू करने से ठीक पहले, code load होते समय नहीं। + +## Lifespan { #lifespan } + +आप `FastAPI` app के `lifespan` parameter और एक "context manager" (मैं अभी दिखाऊंगा कि यह क्या है) का use करके यह *startup* और *shutdown* logic define कर सकते हैं। + +आइए एक उदाहरण से शुरू करते हैं और फिर इसे detail में देखते हैं। + +हम `yield` के साथ एक async function `lifespan()` इस तरह create करते हैं: + +{* ../../docs_src/events/tutorial003_py310.py hl[16,19] *} + +यहां हम `yield` से पहले machine learning models वाली dictionary में (fake) model function रखकर model load करने वाली महंगी *startup* operation को simulate कर रहे हैं। यह code application के **requests लेना शुरू करने से पहले**, *startup* के दौरान execute होगा। + +और फिर, `yield` के तुरंत बाद, हम model unload करते हैं। यह code application के **requests handle करना पूरा करने के बाद**, *shutdown* से ठीक पहले execute होगा। उदाहरण के लिए, यह memory या GPU जैसे resources release कर सकता है। + +/// tip | सुझाव + +`shutdown` तब होगा जब आप application को **stop** कर रहे होंगे। + +शायद आपको कोई नया version start करना हो, या आप इसे चलाते-चलाते बस थक गए हों। 🤷 + +/// + +### Lifespan function { #lifespan-function } + +ध्यान देने वाली पहली चीज यह है कि हम `yield` के साथ एक async function define कर रहे हैं। यह `yield` वाली Dependencies से बहुत मिलता-जुलता है। + +{* ../../docs_src/events/tutorial003_py310.py hl[14:19] *} + +function का पहला हिस्सा, `yield` से पहले वाला, application start होने से **पहले** execute होगा। + +और `yield` के बाद वाला हिस्सा application के finish हो जाने के **बाद** execute होगा। + +### Async Context Manager { #async-context-manager } + +अगर आप check करें, तो function को `@asynccontextmanager` से decorate किया गया है। + +यह function को "**async context manager**" नाम की चीज में convert करता है। + +{* ../../docs_src/events/tutorial003_py310.py hl[1,13] *} + +Python में एक **context manager** ऐसी चीज है जिसे आप `with` statement में use कर सकते हैं, उदाहरण के लिए, `open()` को context manager की तरह use किया जा सकता है: + +```Python +with open("file.txt") as file: + file.read() +``` + +Python के नए versions में, एक **async context manager** भी है। आप इसे `async with` के साथ use करेंगे: + +```Python +async with lifespan(app): + await do_stuff() +``` + +जब आप ऊपर की तरह कोई context manager या async context manager create करते हैं, तो यह क्या करता है कि `with` block में enter करने से पहले, यह `yield` से पहले वाला code execute करेगा, और `with` block से exit करने के बाद, यह `yield` के बाद वाला code execute करेगा। + +ऊपर हमारे code example में, हम इसे सीधे use नहीं करते, बल्कि FastAPI को pass करते हैं ताकि वह इसे use कर सके। + +`FastAPI` app का `lifespan` parameter एक **async context manager** लेता है, इसलिए हम अपना नया `lifespan` async context manager उसे pass कर सकते हैं। + +{* ../../docs_src/events/tutorial003_py310.py hl[22] *} + +## Alternative Events (deprecated) { #alternative-events-deprecated } + +/// warning | चेतावनी + +*startup* और *shutdown* को handle करने का recommended तरीका ऊपर बताए गए अनुसार `FastAPI` app के `lifespan` parameter का use करना है। अगर आप `lifespan` parameter provide करते हैं, तो `startup` और `shutdown` event handlers अब call नहीं किए जाएंगे। यह पूरा `lifespan` होगा या पूरे events, दोनों नहीं। + +आप शायद यह हिस्सा skip कर सकते हैं। + +/// + +इस logic को *startup* के दौरान और *shutdown* के दौरान execute करने के लिए define करने का एक alternative तरीका है। + +आप event handlers (functions) define कर सकते हैं जिन्हें application के starts up होने से पहले, या application के shutting down होने पर execute किया जाना चाहिए। + +इन functions को `async def` या normal `def` के साथ declare किया जा सकता है। + +### `startup` event { #startup-event } + +application start होने से पहले run होने वाला function add करने के लिए, इसे event `"startup"` के साथ declare करें: + +{* ../../docs_src/events/tutorial001_py310.py hl[8] *} + +इस मामले में, `startup` event handler function items "database" (बस एक `dict`) को कुछ values के साथ initialize करेगा। + +आप एक से अधिक event handler function add कर सकते हैं। + +और आपकी application requests receive करना तब तक शुरू नहीं करेगी जब तक सभी `startup` event handlers complete नहीं हो जाते। + +### `shutdown` event { #shutdown-event } + +application के shutting down होने पर run होने वाला function add करने के लिए, इसे event `"shutdown"` के साथ declare करें: + +{* ../../docs_src/events/tutorial002_py310.py hl[6] *} + +यहां, `shutdown` event handler function एक text line `"Application shutdown"` को `log.txt` file में write करेगा। + +/// note | नोट + +`open()` function में, `mode="a"` का मतलब "append" होता है, इसलिए, line उस file में जो भी है उसके बाद add की जाएगी, पिछले contents को overwrite किए बिना। + +/// + +/// tip | सुझाव + +ध्यान दें कि इस मामले में हम एक standard Python `open()` function use कर रहे हैं जो एक file के साथ interact करता है। + +इसलिए, इसमें I/O (input/output) शामिल है, जिसके लिए चीजों के disk पर write होने का "waiting" करना पड़ता है। + +लेकिन `open()` `async` और `await` use नहीं करता। + +इसलिए, हम event handler function को `async def` के बजाय standard `def` के साथ declare करते हैं। + +/// + +### `startup` और `shutdown` साथ में { #startup-and-shutdown-together } + +इस बात की काफी संभावना है कि आपके *startup* और *shutdown* की logic connected हो, आप शायद कुछ start करना और फिर उसे finish करना, कोई resource acquire करना और फिर उसे release करना, आदि चाहें। + +इसे अलग-अलग functions में करना, जो logic या variables को साथ में share नहीं करते, अधिक कठिन है क्योंकि आपको values को global variables या इसी तरह की tricks में store करना पड़ेगा। + +इसी वजह से, अब इसके बजाय ऊपर explain किए गए `lifespan` को use करने की recommendation है। + +## Technical Details { #technical-details } + +जिज्ञासु nerds के लिए बस एक technical detail। 🤓 + +अंदर से, ASGI technical specification में, यह [Lifespan Protocol](https://asgi.readthedocs.io/en/latest/specs/lifespan.html) का हिस्सा है, और यह `startup` और `shutdown` नाम के events define करता है। + +/// note | नोट + +आप Starlette `lifespan` handlers के बारे में [Starlette की Lifespan docs](https://www.starlette.dev/lifespan/) में और पढ़ सकते हैं। + +इसमें यह भी शामिल है कि lifespan state को कैसे handle किया जाए जिसे आपके code के अन्य areas में use किया जा सकता है। + +/// + +## Sub Applications { #sub-applications } + +🚨 ध्यान रखें कि ये lifespan events (startup और shutdown) केवल main application के लिए execute होंगे, [Sub Applications - Mounts](sub-applications.md) के लिए नहीं। diff --git a/docs/hi/docs/advanced/generate-clients.md b/docs/hi/docs/advanced/generate-clients.md new file mode 100644 index 000000000..fa4b8f496 --- /dev/null +++ b/docs/hi/docs/advanced/generate-clients.md @@ -0,0 +1,192 @@ +# SDKs जेनरेट करना { #generating-sdks } + +क्योंकि **FastAPI** **OpenAPI** specification पर आधारित है, इसकी APIs को एक standard format में वर्णित किया जा सकता है जिसे कई tools समझते हैं। + +इससे up-to-date **documentation**, कई भाषाओं में client libraries (**SDKs**), और **testing** या **automation workflows** जेनरेट करना आसान हो जाता है, जो आपके code के साथ sync में रहते हैं। + +इस guide में, आप सीखेंगे कि अपने FastAPI backend के लिए **TypeScript SDK** कैसे जेनरेट करें। + +## Open Source SDK Generators { #open-source-sdk-generators } + +एक versatile विकल्प [OpenAPI Generator](https://openapi-generator.tech/) है, जो **कई programming languages** को support करता है और आपकी OpenAPI specification से SDKs जेनरेट कर सकता है। + +**TypeScript clients** के लिए, [Hey API](https://heyapi.dev/) एक purpose-built solution है, जो TypeScript ecosystem के लिए optimized experience प्रदान करता है। + +आप [OpenAPI.Tools](https://openapi.tools/#sdk) पर और SDK generators खोज सकते हैं। + +/// tip | सुझाव + +FastAPI अपने-आप **OpenAPI 3.1** specifications जेनरेट करता है, इसलिए आपके द्वारा उपयोग किया जाने वाला कोई भी tool इस version को support करना चाहिए। + +/// + +## TypeScript SDK बनाएँ { #create-a-typescript-sdk } + +आइए एक सरल FastAPI application से शुरू करें: + +{* ../../docs_src/generate_clients/tutorial001_py310.py hl[7:9,12:13,16:17,21] *} + +ध्यान दें कि *path operations* उन models को define करते हैं जिनका उपयोग वे request payload और response payload के लिए करते हैं, `Item` और `ResponseMessage` models का उपयोग करके। + +### API Docs { #api-docs } + +यदि आप `/docs` पर जाते हैं, तो आप देखेंगे कि इसमें requests में भेजे जाने और responses में प्राप्त होने वाले data के लिए **schemas** हैं: + + + +आप वे schemas देख सकते हैं क्योंकि उन्हें app में models के साथ declare किया गया था। + +वह जानकारी app के **OpenAPI schema** में उपलब्ध होती है, और फिर API docs में दिखाई जाती है। + +Models से वही जानकारी जो OpenAPI में शामिल होती है, **client code जेनरेट करने** के लिए उपयोग की जा सकती है। + +### Hey API { #hey-api } + +जब हमारे पास models के साथ एक FastAPI app हो, तो हम Hey API का उपयोग करके TypeScript client जेनरेट कर सकते हैं। ऐसा करने का सबसे तेज़ तरीका npx के माध्यम से है। + +```sh +npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client +``` + +यह `./src/client` में TypeScript SDK जेनरेट करेगा। + +आप उनकी website पर [`@hey-api/openapi-ts` install करना](https://heyapi.dev/openapi-ts/get-started) सीख सकते हैं और [generated output](https://heyapi.dev/openapi-ts/output) के बारे में पढ़ सकते हैं। + +### SDK का उपयोग करना { #using-the-sdk } + +अब आप client code को import करके उपयोग कर सकते हैं। यह कुछ ऐसा दिख सकता है, ध्यान दें कि आपको methods के लिए autocompletion मिलता है: + + + +आपको भेजने के लिए payload के लिए भी autocompletion मिलेगा: + + + +/// tip | सुझाव + +`name` और `price` के लिए autocompletion पर ध्यान दें, जिसे FastAPI application में, `Item` model में define किया गया था। + +/// + +आपके द्वारा भेजे जाने वाले data के लिए inline errors होंगे: + + + +Response object में भी autocompletion होगा: + + + +## Tags के साथ FastAPI App { #fastapi-app-with-tags } + +कई मामलों में, आपका FastAPI app बड़ा होगा, और आप शायद *path operations* के अलग-अलग groups को separate करने के लिए tags का उपयोग करेंगे। + +उदाहरण के लिए, आपके पास **items** के लिए एक section और **users** के लिए दूसरा section हो सकता है, और उन्हें tags द्वारा separate किया जा सकता है: + +{* ../../docs_src/generate_clients/tutorial002_py310.py hl[21,26,34] *} + +### Tags के साथ TypeScript Client जेनरेट करें { #generate-a-typescript-client-with-tags } + +यदि आप tags का उपयोग करने वाले FastAPI app के लिए client जेनरेट करते हैं, तो यह सामान्यतः client code को भी tags के आधार पर separate करेगा। + +इस तरह, आप client code के लिए चीज़ों को सही तरह से ordered और grouped रख पाएँगे: + + + +इस मामले में, आपके पास हैं: + +* `ItemsService` +* `UsersService` + +### Client Method Names { #client-method-names } + +अभी, जेनरेट किए गए method names जैसे `createItemItemsPost` बहुत साफ़ नहीं दिखते: + +```TypeScript +ItemsService.createItemItemsPost({name: "Plumbus", price: 5}) +``` + +...ऐसा इसलिए है क्योंकि client generator प्रत्येक *path operation* के लिए OpenAPI internal **operation ID** का उपयोग करता है। + +OpenAPI required करता है कि प्रत्येक operation ID सभी *path operations* में unique हो, इसलिए FastAPI उस operation ID को जेनरेट करने के लिए **function name**, **path**, और **HTTP method/operation** का उपयोग करता है, क्योंकि इस तरह यह सुनिश्चित कर सकता है कि operation IDs unique हैं। + +लेकिन मैं आगे आपको दिखाऊँगा कि इसे कैसे बेहतर बनाया जाए। 🤓 + +## Custom Operation IDs और बेहतर Method Names { #custom-operation-ids-and-better-method-names } + +आप इन operation IDs को **जेनरेट** करने के तरीके को **modify** कर सकते हैं ताकि वे clients में सरल हों और **सरल method names** हों। + +इस मामले में, आपको किसी दूसरे तरीके से सुनिश्चित करना होगा कि प्रत्येक operation ID **unique** हो। + +उदाहरण के लिए, आप सुनिश्चित कर सकते हैं कि प्रत्येक *path operation* में एक tag हो, और फिर **tag** और *path operation* **name** (function name) के आधार पर operation ID जेनरेट करें। + +### Custom Generate Unique ID Function { #custom-generate-unique-id-function } + +FastAPI प्रत्येक *path operation* के लिए एक **unique ID** का उपयोग करता है, जिसका उपयोग **operation ID** के लिए और requests या responses के लिए आवश्यक किसी भी custom models के names के लिए भी किया जाता है। + +आप उस function को customize कर सकते हैं। यह एक `APIRoute` लेता है और एक string output करता है। + +उदाहरण के लिए, यहाँ यह पहले tag (आपके पास शायद केवल एक tag होगा) और *path operation* name (function name) का उपयोग कर रहा है। + +फिर आप उस custom function को `generate_unique_id_function` parameter के रूप में **FastAPI** को pass कर सकते हैं: + +{* ../../docs_src/generate_clients/tutorial003_py310.py hl[6:7,10] *} + +### Custom Operation IDs के साथ TypeScript Client जेनरेट करें { #generate-a-typescript-client-with-custom-operation-ids } + +अब, यदि आप client को फिर से जेनरेट करते हैं, तो आप देखेंगे कि इसमें बेहतर method names हैं: + + + +जैसा कि आप देखते हैं, method names में अब tag और फिर function name है, अब वे URL path और HTTP operation की जानकारी शामिल नहीं करते। + +### Client Generator के लिए OpenAPI Specification को Preprocess करें { #preprocess-the-openapi-specification-for-the-client-generator } + +जेनरेट किए गए code में अभी भी कुछ **duplicated information** है। + +हम पहले से जानते हैं कि यह method **items** से संबंधित है क्योंकि वह शब्द `ItemsService` (tag से लिया गया) में है, लेकिन method name में भी tag name prefixed है। 😕 + +हम शायद इसे सामान्य रूप से OpenAPI के लिए रखना चाहेंगे, क्योंकि यह सुनिश्चित करेगा कि operation IDs **unique** हैं। + +लेकिन generated client के लिए, हम clients जेनरेट करने से ठीक पहले OpenAPI operation IDs को **modify** कर सकते हैं, ताकि उन method names को अधिक अच्छे और **cleaner** बनाया जा सके। + +हम OpenAPI JSON को `openapi.json` file में download कर सकते हैं और फिर इस तरह के script से **उस prefixed tag को remove** कर सकते हैं: + +{* ../../docs_src/generate_clients/tutorial004_py310.py *} + +//// tab | Node.js + +```Javascript +{!> ../../docs_src/generate_clients/tutorial004.js!} +``` + +//// + +इसके साथ, operation IDs को `items-get_items` जैसी चीज़ों से बदलकर सिर्फ़ `get_items` कर दिया जाएगा, इस तरह client generator सरल method names जेनरेट कर सकता है। + +### Preprocessed OpenAPI के साथ TypeScript Client जेनरेट करें { #generate-a-typescript-client-with-the-preprocessed-openapi } + +क्योंकि अंतिम परिणाम अब `openapi.json` file में है, आपको अपनी input location update करनी होगी: + +```sh +npx @hey-api/openapi-ts -i ./openapi.json -o src/client +``` + +नया client जेनरेट करने के बाद, अब आपके पास **clean method names** होंगे, सभी **autocompletion**, **inline errors**, आदि के साथ: + + + +## लाभ { #benefits } + +Automatically generated clients का उपयोग करते समय, आपको इन चीज़ों के लिए **autocompletion** मिलेगा: + +* Methods. +* body में request payloads, query parameters, आदि। +* Response payloads. + +आपके पास हर चीज़ के लिए **inline errors** भी होंगे। + +और जब भी आप backend code update करते हैं, और frontend को **regenerate** करते हैं, तो इसमें methods के रूप में कोई भी नए *path operations* उपलब्ध होंगे, पुराने remove हो जाएँगे, और कोई भी अन्य change generated code में reflect होगा। 🤓 + +इसका मतलब यह भी है कि यदि कुछ बदलता है, तो वह client code में अपने-आप **reflect** होगा। और यदि आप client को **build** करते हैं, तो यदि उपयोग किए गए data में कोई **mismatch** है, तो यह error देगा। + +इसलिए, आप development cycle में बहुत जल्दी **कई errors detect** कर लेंगे, बजाय इसके कि errors के production में आपके अंतिम users को दिखने का इंतज़ार करना पड़े और फिर यह debug करने की कोशिश करनी पड़े कि समस्या कहाँ है। ✨ diff --git a/docs/hi/docs/advanced/index.md b/docs/hi/docs/advanced/index.md new file mode 100644 index 000000000..d2ecb69dc --- /dev/null +++ b/docs/hi/docs/advanced/index.md @@ -0,0 +1,21 @@ +# उन्नत उपयोगकर्ता गाइड { #advanced-user-guide } + +## अतिरिक्त feature { #additional-features } + +मुख्य [ट्यूटोरियल - उपयोगकर्ता गाइड](../tutorial/index.md) आपको **FastAPI** के सभी मुख्य feature का अवलोकन देने के लिए पर्याप्त होना चाहिए। + +अगले sections में आप अन्य विकल्प, configurations, और अतिरिक्त feature देखेंगे। + +/// tip | सुझाव + +अगले sections **ज़रूरी नहीं कि "उन्नत"** हों। + +और संभव है कि आपके उपयोग के मामले के लिए समाधान उनमें से किसी एक में हो। + +/// + +## पहले ट्यूटोरियल पढ़ें { #read-the-tutorial-first } + +आप मुख्य [ट्यूटोरियल - उपयोगकर्ता गाइड](../tutorial/index.md) से मिली जानकारी के साथ भी **FastAPI** के ज़्यादातर feature का उपयोग कर सकते हैं। + +और अगले sections मानते हैं कि आपने इसे पहले ही पढ़ लिया है, और यह भी मानते हैं कि आप उन मुख्य विचारों को जानते हैं। diff --git a/docs/hi/docs/advanced/json-base64-bytes.md b/docs/hi/docs/advanced/json-base64-bytes.md new file mode 100644 index 000000000..c99ffbc7f --- /dev/null +++ b/docs/hi/docs/advanced/json-base64-bytes.md @@ -0,0 +1,63 @@ +# Base64 के रूप में Bytes वाला JSON { #json-with-bytes-as-base64 } + +अगर आपके app को JSON data receive और send करना है, लेकिन आपको उसमें binary data शामिल करना है, तो आप उसे base64 के रूप में encode कर सकते हैं। + +## Base64 बनाम Files { #base64-vs-files } + +पहले यह विचार करें कि क्या आप binary data upload करने के लिए [Request Files](../tutorial/request-files.md) और binary data भेजने के लिए [कस्टम Response - FileResponse](./custom-response.md#fileresponse) का उपयोग कर सकते हैं, बजाय इसके कि उसे JSON में encode किया जाए। + +JSON में केवल UTF-8 encoded strings हो सकती हैं, इसलिए उसमें raw bytes नहीं हो सकते। + +Base64 binary data को strings में encode कर सकता है, लेकिन ऐसा करने के लिए उसे मूल binary data की तुलना में अधिक characters का उपयोग करना पड़ता है, इसलिए यह सामान्य files की तुलना में आमतौर पर कम efficient होगा। + +Base64 का उपयोग केवल तभी करें जब आपको निश्चित रूप से JSON में binary data शामिल करना हो, और आप उसके लिए files का उपयोग नहीं कर सकते। + +## Pydantic `bytes` { #pydantic-bytes } + +आप `bytes` fields वाला एक Pydantic model declare कर सकते हैं, और फिर model config में `val_json_bytes` का उपयोग करके उसे बता सकते हैं कि input JSON data को *validate* करने के लिए base64 का उपयोग करे; उस validation के हिस्से के रूप में यह base64 string को bytes में decode करेगा। + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} + +अगर आप `/docs` देखें, तो वे दिखाएँगे कि field `data` base64 encoded bytes की अपेक्षा करता है: + +
+ +
+ +आप इस तरह का request भेज सकते हैं: + +```json +{ + "description": "Some data", + "data": "aGVsbG8=" +} +``` + +/// tip | सुझाव + +`aGVsbG8=` `hello` की base64 encoding है। + +/// + +और फिर Pydantic base64 string को decode करेगा और आपको model के `data` field में मूल bytes देगा। + +आपको इस तरह का response मिलेगा: + +```json +{ + "description": "Some data", + "content": "hello" +} +``` + +## Output Data के लिए Pydantic `bytes` { #pydantic-bytes-for-output-data } + +आप output data के लिए model config में `ser_json_bytes` के साथ `bytes` fields का भी उपयोग कर सकते हैं, और JSON response generate करते समय Pydantic bytes को base64 के रूप में *serialize* करेगा। + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} + +## Input और Output Data के लिए Pydantic `bytes` { #pydantic-bytes-for-input-and-output-data } + +और बेशक, JSON data receive और send करते समय आप उसी model को base64 उपयोग करने के लिए configure कर सकते हैं, ताकि input (*validate*) को `val_json_bytes` के साथ और output (*serialize*) को `ser_json_bytes` के साथ handle किया जा सके। + +{* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} diff --git a/docs/hi/docs/advanced/middleware.md b/docs/hi/docs/advanced/middleware.md new file mode 100644 index 000000000..a920ba224 --- /dev/null +++ b/docs/hi/docs/advanced/middleware.md @@ -0,0 +1,97 @@ +# उन्नत Middleware { #advanced-middleware } + +मुख्य tutorial में आपने पढ़ा कि अपनी application में [Custom Middleware](../tutorial/middleware.md) कैसे जोड़ें। + +और फिर आपने यह भी पढ़ा कि [`CORSMiddleware` के साथ CORS](../tutorial/cors.md) को कैसे handle करें। + +इस section में हम देखेंगे कि अन्य middleware का उपयोग कैसे करें। + +## ASGI middleware जोड़ना { #adding-asgi-middlewares } + +क्योंकि **FastAPI** Starlette पर आधारित है और ASGI specification को implement करता है, आप कोई भी ASGI middleware उपयोग कर सकते हैं। + +किसी middleware को काम करने के लिए FastAPI या Starlette के लिए बना होना required नहीं है, जब तक वह ASGI spec का पालन करता है। + +सामान्यतः, ASGI middleware ऐसी classes होती हैं जो पहले argument के रूप में एक ASGI app प्राप्त करने की अपेक्षा करती हैं। + +इसलिए, third-party ASGI middleware के documentation में वे शायद आपको कुछ ऐसा करने के लिए कहेंगे: + +```Python +from unicorn import UnicornMiddleware + +app = SomeASGIApp() + +new_app = UnicornMiddleware(app, some_config="rainbow") +``` + +लेकिन FastAPI (वास्तव में Starlette) इसे करने का एक सरल तरीका प्रदान करता है, जो सुनिश्चित करता है कि internal middleware server errors को handle करें और custom exception handlers सही तरीके से काम करें। + +इसके लिए, आप `app.add_middleware()` का उपयोग करते हैं (जैसे CORS के उदाहरण में)। + +```Python +from fastapi import FastAPI +from unicorn import UnicornMiddleware + +app = FastAPI() + +app.add_middleware(UnicornMiddleware, some_config="rainbow") +``` + +`app.add_middleware()` पहले argument के रूप में एक middleware class प्राप्त करता है और middleware को pass किए जाने वाले कोई भी अतिरिक्त arguments भी प्राप्त करता है। + +## एकीकृत middleware { #integrated-middlewares } + +**FastAPI** common use cases के लिए कई middleware शामिल करता है, आगे हम देखेंगे कि उनका उपयोग कैसे करें। + +/// note | तकनीकी विवरण + +अगले उदाहरणों के लिए, आप `from starlette.middleware.something import SomethingMiddleware` भी उपयोग कर सकते हैं। + +**FastAPI** `fastapi.middleware` में कई middleware सिर्फ आपकी, developer की, सुविधा के लिए प्रदान करता है। लेकिन उपलब्ध अधिकांश middleware सीधे Starlette से आते हैं। + +/// + +## `HTTPSRedirectMiddleware` { #httpsredirectmiddleware } + +यह enforce करता है कि सभी incoming requests या तो `https` या `wss` हों। + +`http` या `ws` पर आने वाली कोई भी incoming request इसके बजाय secure scheme पर redirect कर दी जाएगी। + +{* ../../docs_src/advanced_middleware/tutorial001_py310.py hl[2,6] *} + +## `TrustedHostMiddleware` { #trustedhostmiddleware } + +यह enforce करता है कि सभी incoming requests में `Host` header सही तरीके से set हो, ताकि HTTP Host Header attacks से बचाव हो सके। + +{* ../../docs_src/advanced_middleware/tutorial002_py310.py hl[2,6:8] *} + +निम्नलिखित arguments supported हैं: + +* `allowed_hosts` - domain names की एक सूची जिन्हें hostnames के रूप में allow किया जाना चाहिए। `*.example.com` जैसे Wildcard domains subdomains को match करने के लिए supported हैं। किसी भी hostname को allow करने के लिए या तो `allowed_hosts=["*"]` उपयोग करें या middleware को omit करें। +* `www_redirect` - यदि True पर set किया गया है, तो allowed hosts के non-www versions पर आने वाली requests उनके www counterparts पर redirect कर दी जाएँगी। Default `True` है। + +यदि कोई incoming request सही तरीके से validate नहीं होती है तो `400` response भेजा जाएगा। + +## `GZipMiddleware` { #gzipmiddleware } + +ऐसी किसी भी request के लिए GZip responses handle करता है जिसमें `Accept-Encoding` header में `"gzip"` शामिल हो। + +middleware standard और streaming दोनों responses को handle करेगा। + +{* ../../docs_src/advanced_middleware/tutorial003_py310.py hl[2,6] *} + +निम्नलिखित arguments supported हैं: + +* `minimum_size` - इस minimum size से छोटे responses को GZip न करें, size bytes में है। Default `500` है। +* `compresslevel` - GZip compression के दौरान उपयोग किया जाता है। यह 1 से 9 तक की range में एक integer है। Default `9` है। कम value से compression तेज़ होता है लेकिन file sizes बड़ी होती हैं, जबकि अधिक value से compression धीमा होता है लेकिन file sizes छोटी होती हैं। + +## अन्य middleware { #other-middlewares } + +कई अन्य ASGI middleware हैं। + +उदाहरण के लिए: + +* [Uvicorn का `ProxyHeadersMiddleware`](https://github.com/encode/uvicorn/blob/master/uvicorn/middleware/proxy_headers.py) +* [MessagePack](https://github.com/florimondmanca/msgpack-asgi) + +अन्य उपलब्ध middleware देखने के लिए [Starlette के Middleware docs](https://www.starlette.dev/middleware/) और [ASGI Awesome List](https://github.com/florimondmanca/awesome-asgi) देखें। diff --git a/docs/hi/docs/advanced/openapi-callbacks.md b/docs/hi/docs/advanced/openapi-callbacks.md new file mode 100644 index 000000000..1cdbc823b --- /dev/null +++ b/docs/hi/docs/advanced/openapi-callbacks.md @@ -0,0 +1,186 @@ +# OpenAPI Callbacks { #openapi-callbacks } + +आप एक ऐसी API बना सकते हैं जिसमें एक *path operation* हो जो किसी और के द्वारा बनाई गई *external API* को request trigger कर सके (शायद वही developer जो आपकी API का *उपयोग* करेगा)। + +जब आपकी API app *external API* को call करती है, उस प्रक्रिया को "callback" कहा जाता है। क्योंकि external developer द्वारा लिखा गया software आपकी API को request भेजता है और फिर आपकी API *call back* करती है, यानी किसी *external API* को request भेजती है (जो शायद उसी developer द्वारा बनाई गई थी)। + +इस स्थिति में, आप यह document करना चाह सकते हैं कि वह external API कैसी *होनी चाहिए*। उसमें कौन-सा *path operation* होना चाहिए, उसे कौन-सा body expect करना चाहिए, उसे कौन-सा response लौटाना चाहिए, आदि। + +## Callbacks वाली एक app { #an-app-with-callbacks } + +आइए इसे एक उदाहरण के साथ देखते हैं। + +कल्पना करें कि आप एक ऐसी app develop करते हैं जो invoices बनाने देती है। + +इन invoices में एक `id`, `title` (optional), `customer`, और `total` होगा। + +आपकी API का user (एक external developer) आपकी API में POST request के साथ एक invoice बनाएगा। + +फिर आपकी API (कल्पना करें): + +* invoice को external developer के किसी customer को भेजेगी। +* पैसे collect करेगी। +* API user (external developer) को वापस एक notification भेजेगी। + * यह (*आपकी API* से) उस external developer द्वारा दी गई किसी *external API* को POST request भेजकर किया जाएगा (यही "callback" है)। + +## सामान्य **FastAPI** app { #the-normal-fastapi-app } + +Callback जोड़ने से पहले, पहले देखते हैं कि सामान्य API app कैसी दिखेगी। + +इसमें एक *path operation* होगा जो एक `Invoice` body receive करेगा, और एक query parameter `callback_url` होगा जिसमें callback के लिए URL होगा। + +यह हिस्सा काफ़ी सामान्य है, अधिकतर code शायद आपको पहले से परिचित होगा: + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[7:11,34:51] *} + +/// tip | सुझाव + +`callback_url` query parameter एक Pydantic [Url](https://docs.pydantic.dev/latest/api/networks/) type का उपयोग करता है। + +/// + +केवल नई चीज़ है *path operation decorator* के argument के रूप में `callbacks=invoices_callback_router.routes`। आगे हम देखेंगे कि यह क्या है। + +## Callback को document करना { #documenting-the-callback } + +वास्तविक callback code आपकी अपनी API app पर बहुत अधिक निर्भर करेगा। + +और यह एक app से दूसरी app में काफ़ी अलग हो सकता है। + +यह code की सिर्फ़ एक या दो lines भी हो सकती हैं, जैसे: + +```Python +callback_url = "https://example.com/api/v1/invoices/events/" +httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) +``` + +लेकिन संभवतः callback का सबसे महत्वपूर्ण हिस्सा यह सुनिश्चित करना है कि आपका API user (external developer) *external API* को सही तरह से implement करे, उस data के अनुसार जिसे *आपकी API* callback के request body में भेजने वाली है, आदि। + +तो, अब हम वह code जोड़ेंगे जो document करेगा कि *आपकी API* से callback receive करने के लिए वह *external API* कैसी दिखनी चाहिए। + +यह documentation आपकी API में `/docs` पर Swagger UI में दिखाई देगी, और यह external developers को बताएगी कि *external API* कैसे बनानी है। + +यह उदाहरण callback को स्वयं implement नहीं करता (वह केवल code की एक line हो सकती है), केवल documentation वाला हिस्सा करता है। + +/// tip | सुझाव + +वास्तविक callback सिर्फ़ एक HTTP request है। + +Callback को स्वयं implement करते समय, आप [HTTPX](https://www.python-httpx.org) या [Requests](https://requests.readthedocs.io/) जैसी किसी चीज़ का उपयोग कर सकते हैं। + +/// + +## Callback documentation code लिखें { #write-the-callback-documentation-code } + +यह code आपकी app में execute नहीं होगा, हमें इसकी आवश्यकता केवल यह *document* करने के लिए है कि वह *external API* कैसी दिखनी चाहिए। + +लेकिन, आप पहले से जानते हैं कि **FastAPI** के साथ किसी API के लिए automatic documentation आसानी से कैसे बनाई जाती है। + +इसलिए हम उसी ज्ञान का उपयोग करके document करेंगे कि *external API* कैसी दिखनी चाहिए... उन *path operation(s)* को बनाकर जिन्हें external API को implement करना चाहिए (जिन्हें आपकी API call करेगी)। + +/// tip | सुझाव + +Callback को document करने के लिए code लिखते समय, यह कल्पना करना उपयोगी हो सकता है कि आप वही *external developer* हैं। और इस समय आप *external API* implement कर रहे हैं, *अपनी API* नहीं। + +इस दृष्टिकोण को अस्थायी रूप से अपनाना (*external developer* का) आपको यह अधिक स्पष्ट महसूस कराने में मदद कर सकता है कि उस *external API* के लिए parameters, body के लिए Pydantic model, response के लिए model, आदि कहाँ रखने हैं। + +/// + +### Callback `APIRouter` बनाएँ { #create-a-callback-apirouter } + +पहले एक नया `APIRouter` बनाएँ जिसमें एक या अधिक callbacks होंगे। + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *} + +### Callback *path operation* बनाएँ { #create-the-callback-path-operation } + +Callback *path operation* बनाने के लिए वही `APIRouter` उपयोग करें जो आपने ऊपर बनाया था। + +यह बिल्कुल सामान्य FastAPI *path operation* जैसा दिखना चाहिए: + +* इसमें शायद उस body की declaration होनी चाहिए जिसे इसे receive करना है, जैसे `body: InvoiceEvent`। +* और इसमें उस response की declaration भी हो सकती है जिसे इसे लौटाना चाहिए, जैसे `response_model=InvoiceEventReceived`। + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *} + +सामान्य *path operation* से 2 मुख्य अंतर हैं: + +* इसमें कोई वास्तविक code होना required नहीं है, क्योंकि आपकी app इस code को कभी call नहीं करेगी। इसका उपयोग केवल *external API* को document करने के लिए किया जाता है। इसलिए, function में केवल `pass` हो सकता है। +* *path* में एक [OpenAPI 3 expression](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) (नीचे और देखें) हो सकता है, जहाँ यह *आपकी API* को भेजी गई original request के parameters और parts के साथ variables का उपयोग कर सकता है। + +### Callback path expression { #the-callback-path-expression } + +Callback *path* में एक [OpenAPI 3 expression](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) हो सकता है जो *आपकी API* को भेजी गई original request के parts शामिल कर सकता है। + +इस case में, यह `str` है: + +```Python +"{$callback_url}/invoices/{$request.body.id}" +``` + +तो, यदि आपका API user (external developer) *आपकी API* को request भेजता है: + +``` +https://yourapi.com/invoices/?callback_url=https://www.external.org/events +``` + +इस JSON body के साथ: + +```JSON +{ + "id": "2expen51ve", + "customer": "Mr. Richie Rich", + "total": "9999" +} +``` + +तो *आपकी API* invoice को process करेगी, और बाद में किसी समय, `callback_url` (*external API*) को callback request भेजेगी: + +``` +https://www.external.org/events/invoices/2expen51ve +``` + +ऐसे JSON body के साथ जिसमें कुछ इस तरह होगा: + +```JSON +{ + "description": "Payment celebration", + "paid": true +} +``` + +और यह उस *external API* से इस तरह के JSON body वाले response की अपेक्षा करेगी: + +```JSON +{ + "ok": true +} +``` + +/// tip | सुझाव + +ध्यान दें कि उपयोग किए गए callback URL में `callback_url` (`https://www.external.org/events`) में query parameter के रूप में प्राप्त URL और JSON body के अंदर से invoice `id` (`2expen51ve`) दोनों शामिल हैं। + +/// + +### Callback router जोड़ें { #add-the-callback-router } + +इस समय आपके पास ऊपर बनाए गए callback router में required *callback path operation(s)* हैं (वे operation जिन्हें *external developer* को *external API* में implement करना चाहिए)। + +अब *आपकी API के path operation decorator* में parameter `callbacks` का उपयोग करके उस callback router से attribute `.routes` pass करें: + +{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *} + +/// tip | सुझाव + +ध्यान दें कि आप router स्वयं (`invoices_callback_router`) को `callbacks=` में pass नहीं कर रहे हैं, बल्कि उसकी `.routes` को pass कर रहे हैं, जैसे `invoices_callback_router.routes`। FastAPI उन routes का उपयोग callback OpenAPI documentation generate करने के लिए करेगा। + +/// + +### Docs देखें { #check-the-docs } + +अब आप अपनी app start कर सकते हैं और [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) पर जा सकते हैं। + +आपको अपनी docs में अपने *path operation* के लिए एक "Callbacks" section दिखेगा, जो दिखाता है कि *external API* कैसी दिखनी चाहिए: + + diff --git a/docs/hi/docs/advanced/openapi-webhooks.md b/docs/hi/docs/advanced/openapi-webhooks.md new file mode 100644 index 000000000..65cafd0d6 --- /dev/null +++ b/docs/hi/docs/advanced/openapi-webhooks.md @@ -0,0 +1,55 @@ +# OpenAPI Webhooks { #openapi-webhooks } + +ऐसे मामले होते हैं जहाँ आप अपने API **users** को बताना चाहते हैं कि आपकी app कुछ data के साथ (एक request भेजते हुए) *उनकी* app को कॉल कर सकती है, सामान्यतः किसी प्रकार के **event** की **सूचना** देने के लिए। + +इसका मतलब है कि आपके users द्वारा आपकी API को requests भेजने की सामान्य प्रक्रिया के बजाय, **आपकी API** (या आपकी app) **उनके system को requests भेज** सकती है (उनकी API, उनकी app को)। + +इसे सामान्यतः **webhook** कहा जाता है। + +## Webhooks के चरण { #webhooks-steps } + +सामान्यतः प्रक्रिया यह होती है कि **आप अपने code में define करते हैं** कि आप कौन-सा message भेजेंगे, यानी **request का body**। + +आप यह भी किसी तरीके से define करते हैं कि आपकी app किन **क्षणों** पर वे requests या events भेजेगी। + +और **आपके users** किसी तरीके से (उदाहरण के लिए कहीं किसी web dashboard में) वह **URL** define करते हैं जहाँ आपकी app को वे requests भेजनी चाहिए। + +Webhooks के लिए URLs को register करने की सारी **logic** और वास्तव में उन requests को भेजने का code आपके ऊपर है। आप इसे **अपने खुद के code** में जैसे चाहें वैसे लिखते हैं। + +## **FastAPI** और OpenAPI के साथ webhooks का दस्तावेज़ीकरण { #documenting-webhooks-with-fastapi-and-openapi } + +**FastAPI** के साथ, OpenAPI का उपयोग करते हुए, आप इन webhooks के नाम, आपकी app द्वारा भेजे जा सकने वाले HTTP operations के प्रकार (जैसे `POST`, `PUT`, आदि) और आपकी app द्वारा भेजे जाने वाले request **bodies** define कर सकते हैं। + +इससे आपके users के लिए आपकी **webhook** requests प्राप्त करने के लिए **अपनी APIs implement करना** बहुत आसान हो सकता है, वे शायद अपने कुछ API code को autogenerate भी कर सकें। + +/// note | नोट + +Webhooks OpenAPI 3.1.0 और उससे ऊपर में उपलब्ध हैं, और FastAPI `0.99.0` और उससे ऊपर द्वारा समर्थित हैं। + +/// + +## Webhooks वाली app { #an-app-with-webhooks } + +जब आप एक **FastAPI** application बनाते हैं, तो एक `webhooks` attribute होता है जिसका उपयोग आप *webhooks* define करने के लिए कर सकते हैं, उसी तरह जैसे आप *path operations* define करते हैं, उदाहरण के लिए `@app.webhooks.post()` के साथ। + +{* ../../docs_src/openapi_webhooks/tutorial001_py310.py hl[9:12,15:20] *} + +आप जिन webhooks को define करते हैं वे **OpenAPI** schema और automatic **docs UI** में आ जाएँगे। + +/// note | नोट + +`app.webhooks` object वास्तव में सिर्फ़ एक `APIRouter` है, वही type जिसका उपयोग आप अपनी app को multiple files के साथ structure करते समय करेंगे। + +/// + +ध्यान दें कि webhooks के साथ आप वास्तव में कोई *path* declare नहीं कर रहे हैं (जैसे `/items/`), वहाँ आप जो text pass करते हैं वह केवल webhook का एक **identifier** है (event का नाम), उदाहरण के लिए `@app.webhooks.post("new-subscription")` में, webhook का नाम `new-subscription` है। + +ऐसा इसलिए है क्योंकि उम्मीद की जाती है कि **आपके users** उस वास्तविक **URL path** को किसी और तरीके से define करेंगे जहाँ वे webhook request प्राप्त करना चाहते हैं (जैसे कोई web dashboard)। + +### Docs देखें { #check-the-docs } + +अब आप अपनी app start कर सकते हैं और [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) पर जा सकते हैं। + +आप देखेंगे कि आपके docs में सामान्य *path operations* हैं और अब कुछ **webhooks** भी हैं: + + diff --git a/docs/hi/docs/advanced/path-operation-advanced-configuration.md b/docs/hi/docs/advanced/path-operation-advanced-configuration.md new file mode 100644 index 000000000..1636b4f0e --- /dev/null +++ b/docs/hi/docs/advanced/path-operation-advanced-configuration.md @@ -0,0 +1,166 @@ +# Path Operation की उन्नत Configuration { #path-operation-advanced-configuration } + +## OpenAPI operationId { #openapi-operationid } + +/// warning | चेतावनी + +अगर आप OpenAPI में "expert" नहीं हैं, तो शायद आपको इसकी ज़रूरत नहीं है। + +/// + +आप अपने *path operation* में उपयोग किए जाने वाले OpenAPI `operationId` को parameter `operation_id` के साथ सेट कर सकते हैं। + +आपको यह सुनिश्चित करना होगा कि यह प्रत्येक operation के लिए unique हो। + +{* ../../docs_src/path_operation_advanced_configuration/tutorial001_py310.py hl[6] *} + +### *path operation function* के नाम को operationId के रूप में उपयोग करना { #using-the-path-operation-function-name-as-the-operationid } + +अगर आप अपने APIs के function नामों को `operationId`s के रूप में उपयोग करना चाहते हैं, तो आप `FastAPI` को एक custom `generate_unique_id_function` पास कर सकते हैं। + +यह function प्रत्येक `APIRoute` प्राप्त करता है और उस path operation के लिए उपयोग करने वाला `operationId` return करता है। + +{* ../../docs_src/path_operation_advanced_configuration/tutorial002_py310.py hl[2,5:6,9] *} + +/// warning | चेतावनी + +अगर आप ऐसा करते हैं, तो आपको यह सुनिश्चित करना होगा कि आपके प्रत्येक *path operation functions* का नाम unique हो। + +भले ही वे अलग-अलग modules (Python files) में हों। + +/// + +## OpenAPI से बाहर रखना { #exclude-from-openapi } + +किसी *path operation* को generated OpenAPI schema से बाहर रखने के लिए (और इस प्रकार, automatic documentation systems से भी), parameter `include_in_schema` का उपयोग करें और इसे `False` पर सेट करें: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial003_py310.py hl[6] *} + +## Docstring से उन्नत description { #advanced-description-from-docstring } + +आप OpenAPI के लिए किसी *path operation function* की docstring से उपयोग की जाने वाली lines को सीमित कर सकते हैं। + +एक `\f` (एक escaped "form feed" character) जोड़ने से **FastAPI** इस बिंदु पर OpenAPI के लिए उपयोग किए जाने वाले output को truncate कर देता है। + +यह documentation में नहीं दिखेगा, लेकिन अन्य tools (जैसे Sphinx) बाकी हिस्से का उपयोग कर सकेंगे। + +{* ../../docs_src/path_operation_advanced_configuration/tutorial004_py310.py hl[17:27] *} + +## अतिरिक्त Responses { #additional-responses } + +आपने शायद देखा होगा कि किसी *path operation* के लिए `response_model` और `status_code` कैसे declare किए जाते हैं। + +यह किसी *path operation* के मुख्य response के बारे में metadata define करता है। + +आप उनके models, status codes आदि के साथ अतिरिक्त responses भी declare कर सकते हैं। + +इसके बारे में documentation में यहाँ एक पूरा chapter है, आप इसे [OpenAPI में अतिरिक्त Responses](additional-responses.md) पर पढ़ सकते हैं। + +## OpenAPI Extra { #openapi-extra } + +जब आप अपने application में कोई *path operation* declare करते हैं, तो **FastAPI** उस *path operation* के बारे में relevant metadata को automatically generate करता है, जिसे OpenAPI schema में शामिल किया जाता है। + +/// note | तकनीकी विवरण + +OpenAPI specification में इसे [Operation Object](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#operation-object) कहा जाता है। + +/// + +इसमें *path operation* के बारे में सारी जानकारी होती है और इसका उपयोग automatic documentation generate करने के लिए किया जाता है। + +इसमें `tags`, `parameters`, `requestBody`, `responses` आदि शामिल होते हैं। + +यह *path operation*-specific OpenAPI schema सामान्यतः **FastAPI** द्वारा automatically generate किया जाता है, लेकिन आप इसे extend भी कर सकते हैं। + +/// tip | सुझाव + +यह एक low level extension point है। + +अगर आपको केवल अतिरिक्त responses declare करने की ज़रूरत है, तो ऐसा करने का एक अधिक सुविधाजनक तरीका [OpenAPI में अतिरिक्त Responses](additional-responses.md) के साथ है। + +/// + +आप parameter `openapi_extra` का उपयोग करके किसी *path operation* के लिए OpenAPI schema को extend कर सकते हैं। + +### OpenAPI Extensions { #openapi-extensions } + +यह `openapi_extra` उपयोगी हो सकता है, उदाहरण के लिए, [OpenAPI Extensions](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#specificationExtensions) declare करने के लिए: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial005_py310.py hl[6] *} + +अगर आप automatic API docs खोलते हैं, तो आपका extension specific *path operation* के नीचे दिखाई देगा। + + + +और अगर आप resulting OpenAPI (आपकी API में `/openapi.json` पर) देखते हैं, तो आपको अपना extension specific *path operation* के हिस्से के रूप में भी दिखाई देगा: + +```JSON hl_lines="22" +{ + "openapi": "3.1.0", + "info": { + "title": "FastAPI", + "version": "0.1.0" + }, + "paths": { + "/items/": { + "get": { + "summary": "Read Items", + "operationId": "read_items_items__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + } + }, + "x-aperture-labs-portal": "blue" + } + } + } +} +``` + +### Custom OpenAPI *path operation* schema { #custom-openapi-path-operation-schema } + +`openapi_extra` में मौजूद dictionary को *path operation* के लिए automatically generated OpenAPI schema के साथ deeply merge किया जाएगा। + +तो, आप automatically generated schema में अतिरिक्त data जोड़ सकते हैं। + +उदाहरण के लिए, आप FastAPI की Pydantic के साथ automatic features का उपयोग किए बिना, अपने code से request को read और validate करने का निर्णय ले सकते हैं, लेकिन फिर भी आप OpenAPI schema में request को define करना चाह सकते हैं। + +आप यह `openapi_extra` के साथ कर सकते हैं: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial006_py310.py hl[19:36, 39:40] *} + +इस उदाहरण में, हमने कोई Pydantic model declare नहीं किया। वास्तव में, request body को JSON के रूप में parsed भी नहीं किया गया है, इसे सीधे `bytes` के रूप में read किया गया है, और function `magic_data_reader()` किसी तरीके से इसे parse करने का ज़िम्मेदार होगा। + +फिर भी, हम request body के लिए expected schema declare कर सकते हैं। + +### Custom OpenAPI content type { #custom-openapi-content-type } + +इसी trick का उपयोग करके, आप JSON Schema define करने के लिए Pydantic model का उपयोग कर सकते हैं, जिसे फिर *path operation* के लिए custom OpenAPI schema section में शामिल किया जाता है। + +और आप ऐसा तब भी कर सकते हैं जब request में data type JSON न हो। + +उदाहरण के लिए, इस application में हम Pydantic models से JSON Schema निकालने के लिए FastAPI की integrated functionality या JSON के लिए automatic validation का उपयोग नहीं करते हैं। वास्तव में, हम request content type को JSON नहीं, बल्कि YAML के रूप में declare कर रहे हैं: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[15:20, 22] *} + +फिर भी, हालांकि हम default integrated functionality का उपयोग नहीं कर रहे हैं, हम अभी भी उस data के लिए JSON Schema manually generate करने के लिए Pydantic model का उपयोग कर रहे हैं जिसे हम YAML में receive करना चाहते हैं। + +फिर हम request को सीधे उपयोग करते हैं, और body को `bytes` के रूप में extract करते हैं। इसका मतलब है कि FastAPI request payload को JSON के रूप में parse करने की कोशिश भी नहीं करेगा। + +और फिर अपने code में, हम उस YAML content को सीधे parse करते हैं, और फिर हम YAML content को validate करने के लिए फिर से उसी Pydantic model का उपयोग कर रहे हैं: + +{* ../../docs_src/path_operation_advanced_configuration/tutorial007_py310.py hl[24:31] *} + +/// tip | सुझाव + +यहाँ हम उसी Pydantic model को reuse करते हैं। + +लेकिन इसी तरह, हम इसे किसी और तरीके से भी validate कर सकते थे। + +/// diff --git a/docs/hi/docs/advanced/response-change-status-code.md b/docs/hi/docs/advanced/response-change-status-code.md new file mode 100644 index 000000000..3ef2f1b3f --- /dev/null +++ b/docs/hi/docs/advanced/response-change-status-code.md @@ -0,0 +1,31 @@ +# Response - Status Code बदलें { #response-change-status-code } + +आपने शायद पहले पढ़ा होगा कि आप एक default [Response Status Code](../tutorial/response-status-code.md) सेट कर सकते हैं। + +लेकिन कुछ मामलों में आपको default से अलग status code लौटाना पड़ता है। + +## उपयोग का मामला { #use-case } + +उदाहरण के लिए, कल्पना करें कि आप default रूप से "OK" `200` का HTTP status code लौटाना चाहते हैं। + +लेकिन अगर data मौजूद नहीं था, तो आप उसे बनाना चाहते हैं, और "CREATED" `201` का HTTP status code लौटाना चाहते हैं। + +लेकिन फिर भी आप `response_model` के साथ लौटाए गए data को filter और convert कर पाने में सक्षम रहना चाहते हैं। + +ऐसे मामलों के लिए, आप `Response` parameter का उपयोग कर सकते हैं। + +## `Response` parameter का उपयोग करें { #use-a-response-parameter } + +आप अपनी *path operation function* में `Response` type का parameter घोषित कर सकते हैं (जैसा कि आप cookies और headers के लिए कर सकते हैं)। + +और फिर आप उस *temporary* response object में `status_code` सेट कर सकते हैं। + +{* ../../docs_src/response_change_status_code/tutorial001_py310.py hl[1,9,12] *} + +और फिर आप अपनी ज़रूरत का कोई भी object लौटा सकते हैं, जैसा कि आप सामान्य रूप से करते हैं (एक `dict`, एक database model, आदि)। + +और अगर आपने `response_model` घोषित किया है, तो यह आपके लौटाए गए object को filter और convert करने के लिए अभी भी उपयोग किया जाएगा। + +**FastAPI** उस *temporary* response का उपयोग status code (साथ ही cookies और headers) निकालने के लिए करेगा, और उन्हें अंतिम response में डाल देगा जिसमें आपके द्वारा लौटाया गया value होगा, जिसे किसी भी `response_model` द्वारा filter किया गया होगा। + +आप dependencies में भी `Response` parameter घोषित कर सकते हैं, और उनमें status code सेट कर सकते हैं। लेकिन ध्यान रखें कि आख़िरी बार जो सेट किया जाएगा, वही प्रभावी होगा। diff --git a/docs/hi/docs/advanced/response-cookies.md b/docs/hi/docs/advanced/response-cookies.md new file mode 100644 index 000000000..ccd65dc0f --- /dev/null +++ b/docs/hi/docs/advanced/response-cookies.md @@ -0,0 +1,51 @@ +# Response Cookies { #response-cookies } + +## `Response` parameter का उपयोग करें { #use-a-response-parameter } + +आप अपने *path operation function* में `Response` प्रकार का parameter घोषित कर सकते हैं। + +और फिर आप उस *temporary* response object में cookies set कर सकते हैं। + +{* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *} + +और फिर आप अपनी ज़रूरत का कोई भी object return कर सकते हैं, जैसा कि आप सामान्य रूप से करते हैं (एक `dict`, database model, आदि)। + +और अगर आपने `response_model` घोषित किया है, तो आपके द्वारा return किए गए object को filter और convert करने के लिए उसका अभी भी उपयोग किया जाएगा। + +**FastAPI** उस *temporary* response का उपयोग cookies (साथ ही headers और status code) निकालने के लिए करेगा, और उन्हें final response में डाल देगा जिसमें आपके द्वारा return किया गया value होगा, किसी भी `response_model` द्वारा filter किया हुआ। + +आप dependencies में भी `Response` parameter घोषित कर सकते हैं, और उनमें cookies (और headers) set कर सकते हैं। + +## सीधे `Response` return करें { #return-a-response-directly } + +आप अपने code में सीधे `Response` return करते समय भी cookies बना सकते हैं। + +ऐसा करने के लिए, आप [सीधे Response Return करें](response-directly.md) में बताए अनुसार एक response बना सकते हैं। + +फिर उसमें Cookies set करें, और फिर उसे return करें: + +{* ../../docs_src/response_cookies/tutorial001_py310.py hl[10:12] *} + +/// tip | सुझाव + +ध्यान रखें कि अगर आप `Response` parameter का उपयोग करने के बजाय सीधे response return करते हैं, तो FastAPI उसे सीधे return करेगा। + +इसलिए, आपको यह सुनिश्चित करना होगा कि आपका data सही प्रकार का है। उदाहरण के लिए, अगर आप `JSONResponse` return कर रहे हैं, तो वह JSON के साथ compatible हो। + +और यह भी कि आप कोई ऐसा data नहीं भेज रहे हैं जिसे `response_model` द्वारा filter किया जाना चाहिए था। + +/// + +### अधिक जानकारी { #more-info } + +/// note | तकनीकी विवरण + +आप `from starlette.responses import Response` या `from starlette.responses import JSONResponse` का भी उपयोग कर सकते हैं। + +**FastAPI** आपकी सुविधा के लिए, developer के रूप में, वही `starlette.responses` `fastapi.responses` के रूप में प्रदान करता है। लेकिन उपलब्ध अधिकांश responses सीधे Starlette से आते हैं। + +और क्योंकि `Response` का उपयोग अक्सर headers और cookies set करने के लिए किया जा सकता है, **FastAPI** इसे `fastapi.Response` पर भी प्रदान करता है। + +/// + +सभी उपलब्ध parameters और options देखने के लिए, [Starlette में documentation](https://www.starlette.dev/responses/#set-cookie) देखें। diff --git a/docs/hi/docs/advanced/response-directly.md b/docs/hi/docs/advanced/response-directly.md new file mode 100644 index 000000000..1f91a875e --- /dev/null +++ b/docs/hi/docs/advanced/response-directly.md @@ -0,0 +1,83 @@ +# सीधे एक Response लौटाएँ { #return-a-response-directly } + +जब आप **FastAPI** *path operation* बनाते हैं, तो सामान्यतः आप उससे कोई भी data लौटा सकते हैं: एक `dict`, एक `list`, एक Pydantic model, एक database model, आदि। + +अगर आप [Response Model](../tutorial/response-model.md) declare करते हैं, तो FastAPI Pydantic का उपयोग करके data को JSON में serialize करने के लिए उसका उपयोग करेगा। + +अगर आप response model declare नहीं करते, तो FastAPI [JSON Compatible Encoder](../tutorial/encoder.md) में समझाए गए `jsonable_encoder` का उपयोग करेगा और उसे एक `JSONResponse` में रखेगा। + +आप सीधे एक `JSONResponse` भी बना सकते हैं और उसे लौटा सकते हैं। + +/// tip | सुझाव + +आम तौर पर सीधे `JSONResponse` लौटाने की तुलना में [Response Model](../tutorial/response-model.md) का उपयोग करने पर performance काफी बेहतर होगी, क्योंकि उस तरीके से यह Rust में Pydantic का उपयोग करके data serialize करता है। + +/// + +## एक `Response` लौटाएँ { #return-a-response } + +आप एक `Response` या उसकी कोई भी sub-class लौटा सकते हैं। + +/// note | नोट + +`JSONResponse` खुद `Response` की एक sub-class है। + +/// + +और जब आप एक `Response` लौटाते हैं, तो **FastAPI** उसे सीधे pass कर देगा। + +यह Pydantic models के साथ कोई data conversion नहीं करेगा, contents को किसी भी type में convert नहीं करेगा, आदि। + +यह आपको बहुत अधिक **flexibility** देता है। आप कोई भी data type लौटा सकते हैं, किसी भी data declaration या validation को override कर सकते हैं, आदि। + +यह आपको बहुत अधिक **responsibility** भी देता है। आपको यह सुनिश्चित करना होगा कि आप जो data लौटा रहे हैं वह सही है, सही format में है, वह serialize किया जा सकता है, आदि। + +## `Response` में `jsonable_encoder` का उपयोग करना { #using-the-jsonable-encoder-in-a-response } + +क्योंकि **FastAPI** आपके लौटाए गए `Response` में कोई बदलाव नहीं करता, आपको सुनिश्चित करना होगा कि उसके contents इसके लिए तैयार हैं। + +उदाहरण के लिए, आप किसी Pydantic model को पहले `dict` में convert किए बिना `JSONResponse` में नहीं रख सकते, जिसमें सभी data types (जैसे `datetime`, `UUID`, आदि) JSON-compatible types में convert किए गए हों। + +ऐसे मामलों के लिए, response को pass करने से पहले आप अपने data को convert करने के लिए `jsonable_encoder` का उपयोग कर सकते हैं: + +{* ../../docs_src/response_directly/tutorial001_py310.py hl[5:6,20:21] *} + +/// note | तकनीकी विवरण + +आप `from starlette.responses import JSONResponse` का भी उपयोग कर सकते हैं। + +**FastAPI** आपकी सुविधा के लिए, developer के रूप में, वही `starlette.responses` `fastapi.responses` के रूप में उपलब्ध कराता है। लेकिन उपलब्ध अधिकांश responses सीधे Starlette से आते हैं। + +/// + +## custom `Response` लौटाना { #returning-a-custom-response } + +ऊपर दिया गया उदाहरण वे सभी हिस्से दिखाता है जिनकी आपको जरूरत है, लेकिन यह अभी बहुत उपयोगी नहीं है, क्योंकि आप सीधे `item` लौटा सकते थे, और **FastAPI** उसे आपके लिए `JSONResponse` में रख देता, उसे `dict` में convert करता, आदि। यह सब default रूप से होता है। + +अब, देखते हैं कि आप इसका उपयोग custom response लौटाने के लिए कैसे कर सकते हैं। + +मान लें कि आप एक [XML](https://en.wikipedia.org/wiki/XML) response लौटाना चाहते हैं। + +आप अपना XML content एक string में रख सकते हैं, उसे `Response` में रख सकते हैं, और उसे लौटा सकते हैं: + +{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *} + +## Response Model कैसे काम करता है { #how-a-response-model-works } + +जब आप किसी path operation में [Response Model - Return Type](../tutorial/response-model.md) declare करते हैं, तो **FastAPI** Pydantic का उपयोग करके data को JSON में serialize करने के लिए उसका उपयोग करेगा। + +{* ../../docs_src/response_model/tutorial001_01_py310.py hl[16,21] *} + +क्योंकि यह Rust side पर होगा, performance regular Python और `JSONResponse` class के साथ किए जाने की तुलना में काफी बेहतर होगी। + +`response_model` या return type का उपयोग करते समय, FastAPI data को convert करने के लिए `jsonable_encoder` का उपयोग नहीं करेगा (जो धीमा होता), और न ही `JSONResponse` class का उपयोग करेगा। + +इसके बजाय यह response model (या return type) का उपयोग करके Pydantic के साथ generate किए गए JSON bytes लेता है और JSON के लिए सही media type (`application/json`) के साथ सीधे एक `Response` लौटाता है। + +## नोट्स { #notes } + +जब आप सीधे एक `Response` लौटाते हैं, तो उसका data अपने-आप validate, convert (serialize), या document नहीं किया जाता। + +लेकिन आप फिर भी उसे [OpenAPI में अतिरिक्त Responses](additional-responses.md) में बताए अनुसार document कर सकते हैं। + +बाद के sections में आप देख सकते हैं कि automatic data conversion, documentation, आदि रखते हुए इन custom `Response`s का उपयोग/declare कैसे करें। diff --git a/docs/hi/docs/advanced/response-headers.md b/docs/hi/docs/advanced/response-headers.md new file mode 100644 index 000000000..9d62e2f47 --- /dev/null +++ b/docs/hi/docs/advanced/response-headers.md @@ -0,0 +1,41 @@ +# Response Headers { #response-headers } + +## `Response` parameter का उपयोग करें { #use-a-response-parameter } + +आप अपने *path operation function* में `Response` प्रकार का parameter घोषित कर सकते हैं (जैसा कि आप cookies के लिए कर सकते हैं)। + +और फिर आप उस *अस्थायी* response object में headers सेट कर सकते हैं। + +{* ../../docs_src/response_headers/tutorial002_py310.py hl[1, 7:8] *} + +और फिर आप अपनी ज़रूरत का कोई भी object return कर सकते हैं, जैसा कि आप सामान्य रूप से करते हैं (एक `dict`, database model, आदि)। + +और अगर आपने `response_model` घोषित किया है, तो वह अब भी आपके return किए गए object को filter और convert करने के लिए उपयोग किया जाएगा। + +**FastAPI** headers (साथ ही cookies और status code) निकालने के लिए उस *अस्थायी* response का उपयोग करेगा, और उन्हें अंतिम response में डाल देगा जिसमें आपके द्वारा return किया गया value होता है, जिसे किसी भी `response_model` द्वारा filter किया गया होता है। + +आप dependencies में भी `Response` parameter घोषित कर सकते हैं, और उनमें headers (और cookies) सेट कर सकते हैं। + +## सीधे `Response` return करें { #return-a-response-directly } + +जब आप सीधे `Response` return करते हैं, तब भी आप headers जोड़ सकते हैं। + +[सीधे Response Return करें](response-directly.md) में वर्णित तरीके से response बनाएँ और headers को एक अतिरिक्त parameter के रूप में पास करें: + +{* ../../docs_src/response_headers/tutorial001_py310.py hl[10:12] *} + +/// note | तकनीकी विवरण + +आप `from starlette.responses import Response` या `from starlette.responses import JSONResponse` का भी उपयोग कर सकते हैं। + +**FastAPI** आपकी, developer की, सुविधा के लिए वही `starlette.responses` `fastapi.responses` के रूप में प्रदान करता है। लेकिन उपलब्ध अधिकांश responses सीधे Starlette से आते हैं। + +और क्योंकि `Response` का उपयोग अक्सर headers और cookies सेट करने के लिए किया जा सकता है, **FastAPI** इसे `fastapi.Response` पर भी प्रदान करता है। + +/// + +## Custom Headers { #custom-headers } + +ध्यान रखें कि custom proprietary headers को [`X-` prefix का उपयोग करके](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers) जोड़ा जा सकता है। + +लेकिन अगर आपके पास custom headers हैं जिन्हें आप चाहते हैं कि browser में कोई client देख सके, तो आपको उन्हें अपनी CORS configurations में जोड़ना होगा ([CORS (Cross-Origin Resource Sharing)](../tutorial/cors.md) में और पढ़ें), इसके लिए [Starlette के CORS docs](https://www.starlette.dev/middleware/#corsmiddleware) में documented parameter `expose_headers` का उपयोग करें। diff --git a/docs/hi/docs/advanced/security/http-basic-auth.md b/docs/hi/docs/advanced/security/http-basic-auth.md new file mode 100644 index 000000000..172694ef9 --- /dev/null +++ b/docs/hi/docs/advanced/security/http-basic-auth.md @@ -0,0 +1,107 @@ +# HTTP Basic Auth { #http-basic-auth } + +सबसे सरल मामलों के लिए, आप HTTP Basic Auth का उपयोग कर सकते हैं। + +HTTP Basic Auth में, application एक header की अपेक्षा करता है जिसमें username और password होता है। + +अगर उसे यह नहीं मिलता, तो यह HTTP 401 "Unauthorized" error लौटाता है। + +और `WWW-Authenticate` header लौटाता है जिसका value `Basic` होता है, और एक optional `realm` parameter होता है। + +यह browser को username और password के लिए integrated prompt दिखाने को कहता है। + +फिर, जब आप वह username और password टाइप करते हैं, तो browser उन्हें header में अपने-आप भेज देता है। + +## Simple HTTP Basic Auth { #simple-http-basic-auth } + +* `HTTPBasic` और `HTTPBasicCredentials` import करें। +* `HTTPBasic` का उपयोग करके एक "`security` scheme" बनाएँ। +* अपने *path operation* में dependency के साथ उस `security` का उपयोग करें। +* यह `HTTPBasicCredentials` type का एक object लौटाता है: + * इसमें भेजे गए `username` और `password` होते हैं। + +{* ../../docs_src/security/tutorial006_an_py310.py hl[4,8,12] *} + +जब आप पहली बार URL खोलने की कोशिश करते हैं (या docs में "Execute" button पर क्लिक करते हैं), तो browser आपसे आपका username और password पूछेगा: + + + +## Username जाँचें { #check-the-username } + +यहाँ एक अधिक complete example है। + +यह जाँचने के लिए dependency का उपयोग करें कि username और password सही हैं या नहीं। + +इसके लिए, username और password जाँचने के लिए Python standard module [`secrets`](https://docs.python.org/3/library/secrets.html) का उपयोग करें। + +`secrets.compare_digest()` को `bytes` या ऐसा `str` लेना होता है जिसमें केवल ASCII characters (English वाले) हों, इसका मतलब है कि यह `á` जैसे characters के साथ काम नहीं करेगा, जैसे `Sebastián` में। + +इसे handle करने के लिए, हम पहले `username` और `password` को UTF-8 से encode करके `bytes` में convert करते हैं। + +फिर हम `secrets.compare_digest()` का उपयोग करके यह सुनिश्चित कर सकते हैं कि `credentials.username` `"stanleyjobson"` है, और `credentials.password` `"swordfish"` है। + +{* ../../docs_src/security/tutorial007_an_py310.py hl[1,12:24] *} + +यह इसके समान होगा: + +```Python +if not (credentials.username == "stanleyjobson") or not (credentials.password == "swordfish"): + # कोई error लौटाएँ + ... +``` + +लेकिन `secrets.compare_digest()` का उपयोग करने से यह "timing attacks" नाम के attacks के एक type के विरुद्ध सुरक्षित रहेगा। + +### Timing Attacks { #timing-attacks } + +लेकिन "timing attack" क्या होता है? + +मान लीजिए कुछ attackers username और password का अनुमान लगाने की कोशिश कर रहे हैं। + +और वे username `johndoe` और password `love123` के साथ एक request भेजते हैं। + +तब आपकी application में Python code कुछ इस तरह के बराबर होगा: + +```Python +if "johndoe" == "stanleyjobson" and "love123" == "swordfish": + ... +``` + +लेकिन जैसे ही Python `johndoe` में पहले `j` की तुलना `stanleyjobson` में पहले `s` से करता है, यह `False` लौटा देगा, क्योंकि उसे पहले से पता है कि ये दोनों strings समान नहीं हैं, यह सोचते हुए कि "बाकी अक्षरों की तुलना करके और computation खर्च करने की जरूरत नहीं है"। और आपकी application कहेगी "Incorrect username or password"। + +लेकिन फिर attackers username `stanleyjobsox` और password `love123` के साथ कोशिश करते हैं। + +और आपका application code कुछ ऐसा करता है: + +```Python +if "stanleyjobsox" == "stanleyjobson" and "love123" == "swordfish": + ... +``` + +Python को यह समझने से पहले कि दोनों strings समान नहीं हैं, `stanleyjobsox` और `stanleyjobson` दोनों में पूरे `stanleyjobso` की तुलना करनी पड़ेगी। इसलिए "Incorrect username or password" का reply वापस देने में कुछ extra microseconds लगेंगे। + +#### जवाब देने में लगा समय attackers की मदद करता है { #the-time-to-answer-helps-the-attackers } + +उस समय, यह देखकर कि server ने "Incorrect username or password" response भेजने में कुछ microseconds ज्यादा लिए, attackers जान जाएँगे कि उन्होंने _कुछ_ सही पाया है, शुरुआती अक्षरों में से कुछ सही थे। + +और फिर वे यह जानते हुए फिर कोशिश कर सकते हैं कि यह शायद `johndoe` की तुलना में `stanleyjobsox` से ज्यादा मिलता-जुलता है। + +#### एक "professional" attack { #a-professional-attack } + +बेशक, attackers यह सब हाथ से नहीं करेंगे, वे इसे करने के लिए एक program लिखेंगे, संभवतः प्रति सेकंड हजारों या लाखों tests के साथ। और उन्हें एक समय में बस एक extra सही अक्षर मिलेगा। + +लेकिन ऐसा करते हुए, कुछ minutes या hours में attackers ने हमारी application की "help" से सही username और password का अनुमान लगा लिया होगा, सिर्फ जवाब देने में लगे समय का उपयोग करके। + +#### इसे `secrets.compare_digest()` से ठीक करें { #fix-it-with-secrets-compare-digest } + +लेकिन हमारे code में हम वास्तव में `secrets.compare_digest()` का उपयोग कर रहे हैं। + +संक्षेप में, `stanleyjobsox` की तुलना `stanleyjobson` से करने में उतना ही समय लगेगा जितना `johndoe` की तुलना `stanleyjobson` से करने में लगता है। और password के लिए भी वही। + +इस तरह, अपने application code में `secrets.compare_digest()` का उपयोग करके, यह security attacks की इस पूरी range के विरुद्ध सुरक्षित रहेगा। + +### Error लौटाएँ { #return-the-error } + +यह detect करने के बाद कि credentials incorrect हैं, status code 401 (वही जो तब लौटाया जाता है जब कोई credentials provide नहीं किए जाते) के साथ एक `HTTPException` लौटाएँ और browser को login prompt फिर से दिखाने के लिए `WWW-Authenticate` header जोड़ें: + +{* ../../docs_src/security/tutorial007_an_py310.py hl[26:30] *} diff --git a/docs/hi/docs/advanced/security/index.md b/docs/hi/docs/advanced/security/index.md new file mode 100644 index 000000000..cd5d222c6 --- /dev/null +++ b/docs/hi/docs/advanced/security/index.md @@ -0,0 +1,19 @@ +# उन्नत सुरक्षा { #advanced-security } + +## अतिरिक्त Features { #additional-features } + +[Tutorial - User Guide: Security](../../tutorial/security/index.md) में शामिल चीज़ों के अलावा सुरक्षा संभालने के लिए कुछ अतिरिक्त features हैं। + +/// tip | सुझाव + +अगले sections **ज़रूरी नहीं कि "उन्नत" ही हों**। + +और यह संभव है कि आपके use case के लिए समाधान उनमें से किसी एक में हो। + +/// + +## पहले Tutorial पढ़ें { #read-the-tutorial-first } + +अगले sections मानकर चलते हैं कि आपने मुख्य [Tutorial - User Guide: Security](../../tutorial/security/index.md) पहले ही पढ़ लिया है। + +वे सभी समान concepts पर आधारित हैं, लेकिन कुछ अतिरिक्त functionalities की अनुमति देते हैं। diff --git a/docs/hi/docs/advanced/security/oauth2-scopes.md b/docs/hi/docs/advanced/security/oauth2-scopes.md new file mode 100644 index 000000000..1bf01f366 --- /dev/null +++ b/docs/hi/docs/advanced/security/oauth2-scopes.md @@ -0,0 +1,274 @@ +# OAuth2 scopes { #oauth2-scopes } + +आप **FastAPI** के साथ OAuth2 scopes सीधे उपयोग कर सकते हैं, वे निर्बाध रूप से काम करने के लिए एकीकृत हैं। + +यह आपको OAuth2 standard का पालन करते हुए, आपकी OpenAPI application (और API docs) में एक अधिक fine-grained permission system रखने की अनुमति देगा। + +Scopes के साथ OAuth2 वह mechanism है जिसे कई बड़े authentication providers, जैसे Facebook, Google, GitHub, Microsoft, X (Twitter), आदि उपयोग करते हैं। वे इसका उपयोग users और applications को विशिष्ट permissions देने के लिए करते हैं। + +हर बार जब आप Facebook, Google, GitHub, Microsoft, X (Twitter) के साथ "log in with" करते हैं, वह application scopes के साथ OAuth2 का उपयोग कर रही होती है। + +इस section में आप देखेंगे कि अपनी **FastAPI** application में उसी scopes वाले OAuth2 के साथ authentication और authorization को कैसे manage करें। + +/// warning | चेतावनी + +यह थोड़ा-बहुत advanced section है। यदि आप अभी शुरू कर रहे हैं, तो आप इसे छोड़ सकते हैं। + +आपको अनिवार्य रूप से OAuth2 scopes की आवश्यकता नहीं है, और आप authentication और authorization को जैसे चाहें handle कर सकते हैं। + +लेकिन scopes के साथ OAuth2 को आपकी API (OpenAPI के साथ) और आपकी API docs में अच्छी तरह integrate किया जा सकता है। + +फिर भी, आप उन scopes, या किसी भी अन्य security/authorization requirement को अपने code में अपनी आवश्यकता के अनुसार enforce करते हैं। + +कई मामलों में, scopes के साथ OAuth2 overkill हो सकता है। + +लेकिन यदि आप जानते हैं कि आपको इसकी आवश्यकता है, या आप curious हैं, तो पढ़ते रहें। + +/// + +## OAuth2 scopes और OpenAPI { #oauth2-scopes-and-openapi } + +OAuth2 specification "scopes" को spaces से अलग की गई strings की list के रूप में define करती है। + +इनमें से प्रत्येक string का content किसी भी format में हो सकता है, लेकिन उसमें spaces नहीं होने चाहिए। + +ये scopes "permissions" को दर्शाते हैं। + +OpenAPI में (जैसे API docs), आप "security schemes" define कर सकते हैं। + +जब इनमें से कोई security scheme OAuth2 का उपयोग करती है, तो आप scopes declare और उपयोग भी कर सकते हैं। + +प्रत्येक "scope" बस एक string है (spaces के बिना)। + +वे सामान्यतः विशिष्ट security permissions declare करने के लिए उपयोग किए जाते हैं, उदाहरण के लिए: + +* `users:read` या `users:write` आम examples हैं। +* `instagram_basic` Facebook / Instagram द्वारा उपयोग किया जाता है। +* `https://www.googleapis.com/auth/drive` Google द्वारा उपयोग किया जाता है। + +/// note | नोट + +OAuth2 में "scope" बस एक string है जो required विशिष्ट permission declare करती है। + +इससे फर्क नहीं पड़ता कि इसमें `:` जैसे अन्य characters हैं या यह एक URL है। + +वे details implementation specific हैं। + +OAuth2 के लिए वे बस strings हैं। + +/// + +## Global view { #global-view } + +पहले, आइए जल्दी से देखें कि मुख्य **Tutorial - User Guide** में [Password के साथ OAuth2 (और hashing), JWT tokens के साथ Bearer](../../tutorial/security/oauth2-jwt.md) के examples से कौन से parts बदलते हैं। अब OAuth2 scopes का उपयोग करते हुए: + +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *} + +अब आइए उन बदलावों को step by step review करें। + +## OAuth2 Security scheme { #oauth2-security-scheme } + +पहला बदलाव यह है कि अब हम OAuth2 security scheme को दो उपलब्ध scopes, `me` और `items`, के साथ declare कर रहे हैं। + +`scopes` parameter एक `dict` receive करता है जिसमें प्रत्येक scope key के रूप में और description value के रूप में होती है: + +{* ../../docs_src/security/tutorial005_an_py310.py hl[63:66] *} + +क्योंकि अब हम उन scopes को declare कर रहे हैं, वे API docs में तब दिखाई देंगे जब आप log-in/authorize करेंगे। + +और आप select कर सकेंगे कि आप किन scopes को access देना चाहते हैं: `me` और `items`। + +यह वही mechanism है जिसका उपयोग तब होता है जब आप Facebook, Google, GitHub, आदि के साथ log in करते समय permissions देते हैं: + + + +## Scopes के साथ JWT token { #jwt-token-with-scopes } + +अब, token *path operation* को modify करें ताकि requested scopes return हों। + +हम अभी भी वही `OAuth2PasswordRequestForm` उपयोग कर रहे हैं। इसमें `scopes` property शामिल है जिसमें `str` की `list` होती है, और request में received प्रत्येक scope होता है। + +और हम scopes को JWT token के part के रूप में return करते हैं। + +/// danger | खतरा + +सरलता के लिए, यहाँ हम received scopes को सीधे token में जोड़ रहे हैं। + +लेकिन आपकी application में, security के लिए, आपको सुनिश्चित करना चाहिए कि आप केवल वे scopes जोड़ें जिन्हें user वास्तव में रख सकता है, या जिन्हें आपने predefine किया है। + +/// + +{* ../../docs_src/security/tutorial005_an_py310.py hl[157] *} + +## *path operations* और dependencies में scopes declare करें { #declare-scopes-in-path-operations-and-dependencies } + +अब हम declare करते हैं कि `/users/me/items/` के लिए *path operation* को scope `items` required है। + +इसके लिए, हम `fastapi` से `Security` import और उपयोग करते हैं। + +आप dependencies declare करने के लिए `Security` का उपयोग कर सकते हैं (बिल्कुल `Depends` की तरह), लेकिन `Security` एक parameter `scopes` भी receive करता है जिसमें scopes (strings) की list होती है। + +इस case में, हम dependency function `get_current_active_user` को `Security` में pass करते हैं (उसी तरह जैसे हम `Depends` के साथ करते)। + +लेकिन हम scopes की एक `list` भी pass करते हैं, इस case में केवल एक scope के साथ: `items` (इसमें और भी हो सकते थे)। + +और dependency function `get_current_active_user` sub-dependencies भी declare कर सकता है, न केवल `Depends` के साथ बल्कि `Security` के साथ भी। अपना sub-dependency function (`get_current_user`) और अधिक scope requirements declare करते हुए। + +इस case में, इसे scope `me` required है (इसे एक से अधिक scope required हो सकते थे)। + +/// note | नोट + +आपको अलग-अलग जगहों पर अलग-अलग scopes जोड़ना अनिवार्य नहीं है। + +हम यहाँ यह demonstrate करने के लिए कर रहे हैं कि **FastAPI** अलग-अलग levels पर declared scopes को कैसे handle करता है। + +/// + +{* ../../docs_src/security/tutorial005_an_py310.py hl[5,141,172] *} + +/// note | तकनीकी विवरण + +`Security` वास्तव में `Depends` का subclass है, और इसमें केवल एक extra parameter है जिसे हम बाद में देखेंगे। + +लेकिन `Depends` के बजाय `Security` का उपयोग करके, **FastAPI** जान जाएगा कि यह security scopes declare कर सकता है, उन्हें internally उपयोग कर सकता है, और API को OpenAPI के साथ document कर सकता है। + +लेकिन जब आप `fastapi` से `Query`, `Path`, `Depends`, `Security` और अन्य import करते हैं, तो वे वास्तव में functions हैं जो special classes return करते हैं। + +/// + +## `SecurityScopes` का उपयोग करें { #use-securityscopes } + +अब dependency `get_current_user` को update करें। + +यह वही है जिसका उपयोग ऊपर की dependencies द्वारा किया जाता है। + +यहीं हम पहले बनाई गई उसी OAuth2 scheme का उपयोग कर रहे हैं, इसे dependency के रूप में declare करते हुए: `oauth2_scheme`। + +क्योंकि इस dependency function की अपनी कोई scope requirements नहीं हैं, हम `oauth2_scheme` के साथ `Depends` उपयोग कर सकते हैं, जब हमें security scopes specify करने की आवश्यकता नहीं है तो हमें `Security` उपयोग करने की आवश्यकता नहीं है। + +हम `SecurityScopes` type का एक special parameter भी declare करते हैं, जिसे `fastapi.security` से import किया गया है। + +यह `SecurityScopes` class `Request` के समान है (`Request` का उपयोग request object को सीधे प्राप्त करने के लिए किया गया था)। + +{* ../../docs_src/security/tutorial005_an_py310.py hl[9,106] *} + +## `scopes` का उपयोग करें { #use-the-scopes } + +Parameter `security_scopes` का type `SecurityScopes` होगा। + +इसमें property `scopes` होगी जिसमें एक list होगी, जिसमें स्वयं और इसे sub-dependency के रूप में उपयोग करने वाली सभी dependencies द्वारा required सभी scopes शामिल होंगे। इसका मतलब है, सभी "dependants"... यह confusing लग सकता है, इसे नीचे फिर से समझाया गया है। + +`security_scopes` object (`SecurityScopes` class का) एक `scope_str` attribute भी provide करता है जिसमें एक single string होती है, जिसमें वे scopes spaces से अलग होते हैं (हम इसका उपयोग करेंगे)। + +हम एक `HTTPException` बनाते हैं जिसे हम बाद में कई points पर reuse (`raise`) कर सकते हैं। + +इस exception में, हम required scopes (यदि कोई हों) को spaces से अलग की गई string के रूप में शामिल करते हैं (`scope_str` का उपयोग करके)। हम scopes वाली उस string को `WWW-Authenticate` header में रखते हैं (यह spec का part है)। + +{* ../../docs_src/security/tutorial005_an_py310.py hl[106,108:116] *} + +## `username` और data shape verify करें { #verify-the-username-and-data-shape } + +हम verify करते हैं कि हमें `username` मिलता है, और scopes extract करते हैं। + +और फिर हम उस data को Pydantic model के साथ validate करते हैं (`ValidationError` exception को catch करते हुए), और यदि JWT token पढ़ने या Pydantic के साथ data validate करने में error मिलता है, तो हम पहले बनाया हुआ `HTTPException` raise करते हैं। + +इसके लिए, हम Pydantic model `TokenData` को नई property `scopes` के साथ update करते हैं। + +Pydantic के साथ data validate करके हम यह सुनिश्चित कर सकते हैं कि हमारे पास, उदाहरण के लिए, scopes के साथ बिल्कुल `str` की `list` और `username` के साथ `str` है। + +उदाहरण के लिए, `dict`, या कुछ और नहीं, क्योंकि यह बाद में किसी point पर application को break कर सकता है, जिससे यह security risk बन सकता है। + +हम यह भी verify करते हैं कि हमारे पास उस username वाला user है, और यदि नहीं, तो हम वही exception raise करते हैं जो हमने पहले बनाया था। + +{* ../../docs_src/security/tutorial005_an_py310.py hl[47,117:129] *} + +## `scopes` verify करें { #verify-the-scopes } + +अब हम verify करते हैं कि इस dependency और सभी dependants (जिसमें *path operations* शामिल हैं) द्वारा required सभी scopes, received token में provided scopes में शामिल हैं, अन्यथा `HTTPException` raise करते हैं। + +इसके लिए, हम `security_scopes.scopes` का उपयोग करते हैं, जिसमें इन सभी scopes की `list` `str` के रूप में होती है। + +{* ../../docs_src/security/tutorial005_an_py310.py hl[130:136] *} + +## Dependency tree और scopes { #dependency-tree-and-scopes } + +आइए इस dependency tree और scopes को फिर से review करें। + +क्योंकि `get_current_active_user` dependency में `get_current_user` sub-dependency के रूप में है, `get_current_active_user` पर declared scope `"me"` required scopes की उस list में शामिल होगा जो `get_current_user` को pass किए गए `security_scopes.scopes` में होती है। + +*path operation* स्वयं भी एक scope, `"items"`, declare करता है, इसलिए यह भी `get_current_user` को pass किए गए `security_scopes.scopes` की list में होगा। + +Dependencies और scopes की hierarchy इस तरह दिखती है: + +* *path operation* `read_own_items` में है: + * Dependency के साथ required scopes `["items"]`: + * `get_current_active_user`: + * Dependency function `get_current_active_user` में है: + * Dependency के साथ required scopes `["me"]`: + * `get_current_user`: + * Dependency function `get_current_user` में है: + * स्वयं द्वारा required कोई scopes नहीं। + * `oauth2_scheme` का उपयोग करने वाली dependency। + * `SecurityScopes` type का एक `security_scopes` parameter: + * इस `security_scopes` parameter में property `scopes` है जिसमें ऊपर declared इन सभी scopes वाली `list` है, इसलिए: + * *path operation* `read_own_items` के लिए `security_scopes.scopes` में `["me", "items"]` होगा। + * *path operation* `read_users_me` के लिए `security_scopes.scopes` में `["me"]` होगा, क्योंकि यह dependency `get_current_active_user` में declared है। + * *path operation* `read_system_status` के लिए `security_scopes.scopes` में `[]` (कुछ नहीं) होगा, क्योंकि उसने `scopes` के साथ कोई `Security` declare नहीं किया, और उसकी dependency, `get_current_user`, भी कोई `scopes` declare नहीं करती। + +/// tip | सुझाव + +यहाँ महत्वपूर्ण और "magic" बात यह है कि प्रत्येक *path operation* के लिए `get_current_user` के पास check करने हेतु `scopes` की अलग list होगी। + +यह सब उस specific *path operation* के dependency tree में प्रत्येक *path operation* और प्रत्येक dependency में declared `scopes` पर निर्भर करता है। + +/// + +## `SecurityScopes` के बारे में अधिक details { #more-details-about-securityscopes } + +आप `SecurityScopes` का उपयोग किसी भी point पर, और multiple जगहों पर कर सकते हैं, इसका "root" dependency पर होना ज़रूरी नहीं है। + +इसमें हमेशा current `Security` dependencies और **उस specific** *path operation* तथा **उस specific** dependency tree के सभी dependants में declared security scopes होंगे। + +क्योंकि `SecurityScopes` में dependants द्वारा declared सभी scopes होंगे, आप इसका उपयोग यह verify करने के लिए कर सकते हैं कि token में required scopes हैं, एक central dependency function में, और फिर अलग-अलग *path operations* में अलग-अलग scope requirements declare कर सकते हैं। + +उन्हें प्रत्येक *path operation* के लिए independently check किया जाएगा। + +## इसे check करें { #check-it } + +यदि आप API docs खोलते हैं, तो आप authenticate कर सकते हैं और specify कर सकते हैं कि आप किन scopes को authorize करना चाहते हैं। + + + +यदि आप कोई scope select नहीं करते हैं, तो आप "authenticated" होंगे, लेकिन जब आप `/users/me/` या `/users/me/items/` access करने की कोशिश करेंगे तो आपको error मिलेगा कि आपके पास पर्याप्त permissions नहीं हैं। आप फिर भी `/status/` access कर पाएंगे। + +और यदि आप scope `me` select करते हैं लेकिन scope `items` नहीं, तो आप `/users/me/` access कर पाएंगे लेकिन `/users/me/items/` नहीं। + +ऐसा ही किसी third party application के साथ होगा जो user द्वारा provided token के साथ इन *path operations* में से किसी एक को access करने की कोशिश करती, यह इस पर निर्भर करता है कि user ने application को कितनी permissions दीं। + +## Third party integrations के बारे में { #about-third-party-integrations } + +इस example में हम OAuth2 "password" flow का उपयोग कर रहे हैं। + +यह तब appropriate है जब हम अपनी ही application में log in कर रहे हों, शायद अपने ही frontend के साथ। + +क्योंकि हम इस पर भरोसा कर सकते हैं कि यह `username` और `password` receive करे, क्योंकि हम इसे control करते हैं। + +लेकिन यदि आप ऐसी OAuth2 application बना रहे हैं जिससे दूसरे connect करेंगे (अर्थात, यदि आप Facebook, Google, GitHub, आदि के बराबर authentication provider बना रहे हैं) तो आपको अन्य flows में से किसी एक का उपयोग करना चाहिए। + +सबसे common implicit flow है। + +सबसे secure code flow है, लेकिन इसे implement करना अधिक complex है क्योंकि इसमें अधिक steps required हैं। क्योंकि यह अधिक complex है, कई providers अंततः implicit flow suggest करते हैं। + +/// note | नोट + +यह common है कि प्रत्येक authentication provider अपने flows को अलग तरीके से name करता है, ताकि इसे अपने brand का part बना सके। + +लेकिन अंततः, वे वही OAuth2 standard implement कर रहे होते हैं। + +/// + +**FastAPI** में इन सभी OAuth2 authentication flows के लिए utilities `fastapi.security.oauth2` में शामिल हैं। + +## Decorator `dependencies` में `Security` { #security-in-decorator-dependencies } + +जिस तरह आप decorator के `dependencies` parameter में `Depends` की `list` define कर सकते हैं (जैसा कि [path operation decorators में Dependencies](../../tutorial/dependencies/dependencies-in-path-operation-decorators.md) में समझाया गया है), आप वहाँ `scopes` के साथ `Security` भी उपयोग कर सकते हैं। diff --git a/docs/hi/docs/advanced/settings.md b/docs/hi/docs/advanced/settings.md new file mode 100644 index 000000000..0c4d3c061 --- /dev/null +++ b/docs/hi/docs/advanced/settings.md @@ -0,0 +1,302 @@ +# Settings और Environment Variables { #settings-and-environment-variables } + +कई मामलों में आपकी application को कुछ बाहरी settings या configurations की ज़रूरत हो सकती है, उदाहरण के लिए secret keys, database credentials, email services के लिए credentials, आदि। + +इनमें से ज़्यादातर settings variable होती हैं (बदल सकती हैं), जैसे database URLs। और कई sensitive हो सकती हैं, जैसे secrets। + +इसी कारण उन्हें आम तौर पर environment variables में दिया जाता है जिन्हें application पढ़ती है। + +/// tip | सुझाव + +Environment variables को समझने के लिए आप [Environment Variables](../environment-variables.md) पढ़ सकते हैं। + +/// + +## Types और validation { #types-and-validation } + +ये environment variables केवल text strings को handle कर सकते हैं, क्योंकि ये Python के बाहर होते हैं और इन्हें दूसरे programs और system के बाकी हिस्सों के साथ compatible होना होता है (और अलग-अलग operating systems, जैसे Linux, Windows, और macOS के साथ भी)। + +इसका मतलब है कि Python में किसी environment variable से पढ़ी गई कोई भी value एक `str` होगी, और किसी अलग type में कोई भी conversion या कोई भी validation code में करनी होगी। + +## Pydantic `Settings` { #pydantic-settings } + +सौभाग्य से, Pydantic environment variables से आने वाली इन settings को handle करने के लिए एक बेहतरीन utility देता है: [Pydantic: Settings management](https://docs.pydantic.dev/latest/concepts/pydantic_settings/)। + +### `pydantic-settings` install करें { #install-pydantic-settings } + +सबसे पहले, सुनिश्चित करें कि आप अपना [virtual environment](../virtual-environments.md) बनाते हैं, उसे activate करते हैं, और फिर `pydantic-settings` package install करते हैं: + +
+ +```console +$ pip install pydantic-settings +---> 100% +``` + +
+ +जब आप `all` extras को install करते हैं, तो यह भी शामिल आता है: + +
+ +```console +$ pip install "fastapi[all]" +---> 100% +``` + +
+ +### `Settings` object बनाएँ { #create-the-settings-object } + +Pydantic से `BaseSettings` import करें और एक sub-class बनाएँ, बिल्कुल Pydantic model की तरह। + +Pydantic models की तरह ही, आप type annotations के साथ class attributes घोषित करते हैं, और संभवतः default values भी। + +आप वे सभी validation features और tools इस्तेमाल कर सकते हैं जिन्हें आप Pydantic models के लिए इस्तेमाल करते हैं, जैसे अलग-अलग data types और `Field()` के साथ अतिरिक्त validations। + +{* ../../docs_src/settings/tutorial001_py310.py hl[2,5:8,11] *} + +/// tip | सुझाव + +अगर आप जल्दी copy और paste करने के लिए कुछ चाहते हैं, तो यह example इस्तेमाल न करें, नीचे वाला आखिरी example इस्तेमाल करें। + +/// + +फिर, जब आप उस `Settings` class का instance बनाते हैं (इस case में, `settings` object में), Pydantic environment variables को case-insensitive तरीके से पढ़ेगा, इसलिए upper-case variable `APP_NAME` भी attribute `app_name` के लिए पढ़ा जाएगा। + +इसके बाद यह data को convert और validate करेगा। इसलिए, जब आप उस `settings` object का उपयोग करेंगे, तो आपके पास उन types का data होगा जिन्हें आपने घोषित किया था (जैसे `items_per_user` एक `int` होगा)। + +### `settings` का उपयोग करें { #use-the-settings } + +फिर आप अपनी application में नए `settings` object का उपयोग कर सकते हैं: + +{* ../../docs_src/settings/tutorial001_py310.py hl[18:20] *} + +### Server चलाएँ { #run-the-server } + +इसके बाद, आप configurations को environment variables के रूप में pass करते हुए server चलाएँगे, उदाहरण के लिए आप `ADMIN_EMAIL` और `APP_NAME` set कर सकते हैं: + +
+ +```console +$ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.py + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +/// tip | सुझाव + +एक ही command के लिए कई env vars set करने के लिए बस उन्हें space से अलग करें, और उन सभी को command से पहले रखें। + +/// + +और फिर `admin_email` setting `"deadpool@example.com"` पर set हो जाएगी। + +`app_name` `"ChimichangApp"` होगा। + +और `items_per_user` अपनी default value `50` बनाए रखेगा। + +## किसी दूसरे module में Settings { #settings-in-another-module } + +आप उन settings को किसी दूसरे module file में रख सकते हैं, जैसा आपने [Bigger Applications - Multiple Files](../tutorial/bigger-applications.md) में देखा था। + +उदाहरण के लिए, आपके पास `config.py` file हो सकती है: + +{* ../../docs_src/settings/app01_py310/config.py *} + +और फिर उसे `main.py` file में उपयोग करें: + +{* ../../docs_src/settings/app01_py310/main.py hl[3,11:13] *} + +/// tip | सुझाव + +आपको एक `__init__.py` file की भी ज़रूरत होगी, जैसा आपने [Bigger Applications - Multiple Files](../tutorial/bigger-applications.md) में देखा था। + +/// + +## Dependency में Settings { #settings-in-a-dependency } + +कुछ मौकों पर settings को dependency से देना उपयोगी हो सकता है, बजाय इसके कि `settings` के साथ एक global object हो जिसे हर जगह इस्तेमाल किया जाए। + +यह testing के दौरान विशेष रूप से उपयोगी हो सकता है, क्योंकि dependency को अपनी custom settings से override करना बहुत आसान है। + +### Config file { #the-config-file } + +पिछले example से आगे बढ़ते हुए, आपकी `config.py` file इस तरह दिख सकती है: + +{* ../../docs_src/settings/app02_an_py310/config.py hl[10] *} + +ध्यान दें कि अब हम default instance `settings = Settings()` नहीं बनाते। + +### Main app file { #the-main-app-file } + +अब हम एक dependency बनाते हैं जो नया `config.Settings()` return करती है। + +{* ../../docs_src/settings/app02_an_py310/main.py hl[6,12:13] *} + +/// tip | सुझाव + +हम थोड़ी देर में `@lru_cache` पर चर्चा करेंगे। + +अभी के लिए आप मान सकते हैं कि `get_settings()` एक normal function है। + +/// + +और फिर हम इसे *path operation function* से dependency के रूप में require कर सकते हैं और जहाँ भी ज़रूरत हो वहाँ इस्तेमाल कर सकते हैं। + +{* ../../docs_src/settings/app02_an_py310/main.py hl[17,19:21] *} + +### Settings और testing { #settings-and-testing } + +फिर testing के दौरान `get_settings` के लिए dependency override बनाकर अलग settings object देना बहुत आसान होगा: + +{* ../../docs_src/settings/app02_an_py310/test_main.py hl[9:10,13,21] *} + +Dependency override में हम नया `Settings` object बनाते समय `admin_email` के लिए नई value set करते हैं, और फिर उस नए object को return करते हैं। + +फिर हम test कर सकते हैं कि इसका उपयोग हुआ है। + +## `.env` file पढ़ना { #reading-a-env-file } + +अगर आपके पास कई settings हैं जो संभवतः बहुत बदलती हैं, शायद अलग-अलग environments में, तो उन्हें एक file में रखना और फिर वहाँ से ऐसे पढ़ना उपयोगी हो सकता है जैसे वे environment variables हों। + +यह practice इतनी आम है कि इसका एक नाम है, ये environment variables आम तौर पर `.env` file में रखे जाते हैं, और file को "dotenv" कहा जाता है। + +/// tip | सुझाव + +dot (`.`) से शुरू होने वाली file Unix-like systems, जैसे Linux और macOS में hidden file होती है। + +लेकिन dotenv file का वास्तव में वही exact filename होना ज़रूरी नहीं है। + +/// + +Pydantic के पास external library का उपयोग करके इस प्रकार की files से पढ़ने के लिए support है। आप [Pydantic Settings: Dotenv (.env) support](https://docs.pydantic.dev/latest/concepts/pydantic_settings/#dotenv-env-support) पर और पढ़ सकते हैं। + +/// tip | सुझाव + +इसे काम करने के लिए, आपको `pip install python-dotenv` करना होगा। + +/// + +### `.env` file { #the-env-file } + +आपके पास इस तरह की `.env` file हो सकती है: + +```bash +ADMIN_EMAIL="deadpool@example.com" +APP_NAME="ChimichangApp" +``` + +### `.env` से settings पढ़ें { #read-settings-from-env } + +और फिर अपनी `config.py` को update करें: + +{* ../../docs_src/settings/app03_an_py310/config.py hl[9] *} + +/// tip | सुझाव + +`model_config` attribute केवल Pydantic configuration के लिए उपयोग किया जाता है। आप [Pydantic: Concepts: Configuration](https://docs.pydantic.dev/latest/concepts/config/) पर और पढ़ सकते हैं। + +/// + +यहाँ हम आपकी Pydantic `Settings` class के अंदर config `env_file` define करते हैं, और value को उस dotenv file के filename पर set करते हैं जिसे हम उपयोग करना चाहते हैं। + +### `lru_cache` के साथ `Settings` को केवल एक बार बनाना { #creating-the-settings-only-once-with-lru-cache } + +Disk से file पढ़ना सामान्यतः costly (slow) operation होता है, इसलिए आप शायद इसे केवल एक बार करना चाहेंगे और फिर हर request के लिए पढ़ने के बजाय उसी settings object को reuse करना चाहेंगे। + +लेकिन हर बार जब हम करते हैं: + +```Python +Settings() +``` + +तो एक नया `Settings` object बनेगा, और बनते समय यह `.env` file को फिर से पढ़ेगा। + +अगर dependency function बस ऐसी होती: + +```Python +def get_settings(): + return Settings() +``` + +तो हम हर request के लिए वह object बनाते, और हर request के लिए `.env` file पढ़ते। ⚠️ + +लेकिन क्योंकि हम ऊपर `@lru_cache` decorator इस्तेमाल कर रहे हैं, `Settings` object केवल एक बार बनाया जाएगा, पहली बार जब इसे call किया जाएगा। ✔️ + +{* ../../docs_src/settings/app03_an_py310/main.py hl[1,11] *} + +फिर अगले requests के लिए dependencies में `get_settings()` की किसी भी बाद की call पर, `get_settings()` के internal code को execute करने और नया `Settings` object बनाने के बजाय, यह वही object return करेगा जो पहली call पर return किया गया था, बार-बार। + +#### `lru_cache` Technical Details { #lru-cache-technical-details } + +`@lru_cache` जिस function को decorate करता है उसे modify करता है ताकि वह हर बार function का code execute करके फिर से compute करने के बजाय वही value return करे जो पहली बार return की गई थी। + +इसलिए, उसके नीचे वाला function arguments के प्रत्येक combination के लिए एक बार execute होगा। और फिर उन arguments के प्रत्येक combination द्वारा return की गई values बार-बार उपयोग की जाएँगी, जब भी function को ठीक उसी arguments combination के साथ call किया जाएगा। + +उदाहरण के लिए, अगर आपके पास एक function है: + +```Python +@lru_cache +def say_hi(name: str, salutation: str = "Ms."): + return f"Hello {salutation} {name}" +``` + +आपका program इस तरह execute हो सकता है: + +```mermaid +sequenceDiagram + +participant code as Code +participant function as say_hi() +participant execute as Execute function + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Camila") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Camila") + function ->> code: return stored result + end + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Rick") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 0, .1) + code ->> function: say_hi(name="Rick", salutation="Mr.") + function ->> execute: execute function code + execute ->> code: return the result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Rick") + function ->> code: return stored result + end + + rect rgba(0, 255, 255, .1) + code ->> function: say_hi(name="Camila") + function ->> code: return stored result + end +``` + +हमारी dependency `get_settings()` के case में, function कोई arguments भी नहीं लेती, इसलिए यह हमेशा वही value return करती है। + +इस तरह, यह लगभग ऐसे behave करती है जैसे यह बस एक global variable हो। लेकिन क्योंकि यह dependency function का उपयोग करती है, इसलिए हम testing के लिए इसे आसानी से override कर सकते हैं। + +`@lru_cache` `functools` का हिस्सा है, जो Python की standard library का हिस्सा है। आप इसके बारे में [Python docs for `@lru_cache`](https://docs.python.org/3/library/functools.html#functools.lru_cache) में और पढ़ सकते हैं। + +## Recap { #recap } + +आप अपनी application की settings या configurations को handle करने के लिए Pydantic Settings का उपयोग कर सकते हैं, Pydantic models की पूरी power के साथ। + +* Dependency का उपयोग करके आप testing को सरल बना सकते हैं। +* आप इसके साथ `.env` files का उपयोग कर सकते हैं। +* `@lru_cache` का उपयोग करने से आप हर request के लिए dotenv file को बार-बार पढ़ने से बच सकते हैं, साथ ही testing के दौरान इसे override करने की अनुमति भी मिलती है। diff --git a/docs/hi/docs/advanced/stream-data.md b/docs/hi/docs/advanced/stream-data.md new file mode 100644 index 000000000..f1dd15de5 --- /dev/null +++ b/docs/hi/docs/advanced/stream-data.md @@ -0,0 +1,117 @@ +# Data Stream करें { #stream-data } + +अगर आप ऐसा data stream करना चाहते हैं जिसे JSON के रूप में संरचित किया जा सके, तो आपको [JSON Lines Stream करें](../tutorial/stream-json-lines.md)। + +लेकिन अगर आप **शुद्ध binary data** या strings stream करना चाहते हैं, तो यह आप ऐसे कर सकते हैं। + +/// note | नोट + +FastAPI 0.134.0 में जोड़ा गया। + +/// + +## उपयोग के मामले { #use-cases } + +आप इसका उपयोग तब कर सकते हैं जब आप शुद्ध strings stream करना चाहते हों, उदाहरण के लिए सीधे किसी **AI LLM** service के output से। + +आप इसका उपयोग **बड़ी binary files** stream करने के लिए भी कर सकते हैं, जहाँ आप data के प्रत्येक chunk को पढ़ते समय stream करते हैं, बिना पूरे data को एक साथ memory में पढ़े। + +आप इसी तरह **video** या **audio** भी stream कर सकते हैं, यह process और send करते समय generate भी किया जा सकता है। + +## `yield` के साथ एक `StreamingResponse` { #a-streamingresponse-with-yield } + +अगर आप अपने *path operation function* में `response_class=StreamingResponse` declare करते हैं, तो आप data के प्रत्येक chunk को क्रम से भेजने के लिए `yield` का उपयोग कर सकते हैं। + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[1:23] hl[20,23] *} + +FastAPI data के प्रत्येक chunk को `StreamingResponse` को जैसा है वैसा ही देगा, यह उसे JSON या किसी समान चीज़ में convert करने की कोशिश नहीं करेगा। + +### Non-async *path operation functions* { #non-async-path-operation-functions } + +आप regular `def` functions (`async` के बिना) का भी उपयोग कर सकते हैं, और उसी तरह `yield` का उपयोग कर सकते हैं। + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[26:29] hl[27] *} + +### Annotation नहीं { #no-annotation } + +Streaming binary data के लिए आपको return type annotation declare करने की वास्तव में आवश्यकता नहीं है। + +क्योंकि FastAPI data को Pydantic के साथ JSON में convert करने या किसी भी तरह serialize करने की कोशिश नहीं करेगा, इस मामले में type annotation केवल आपके editor और tools के उपयोग के लिए है, FastAPI इसका उपयोग नहीं करेगा। + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} + +इसका मतलब यह भी है कि `StreamingResponse` के साथ आपके पास type annotations से स्वतंत्र होकर data bytes को ठीक वैसे produce और encode करने की **स्वतंत्रता** और **ज़िम्मेदारी** है, जैसे उन्हें भेजा जाना चाहिए। 🤓 + +### Bytes Stream करें { #stream-bytes } + +मुख्य उपयोग मामलों में से एक strings के बजाय `bytes` stream करना होगा, और आप निश्चित रूप से ऐसा कर सकते हैं। + +{* ../../docs_src/stream_data/tutorial001_py310.py ln[44:47] hl[47] *} + +## एक Custom `PNGStreamingResponse` { #a-custom-pngstreamingresponse } + +ऊपर के उदाहरणों में, data bytes stream किए गए थे, लेकिन response में `Content-Type` header नहीं था, इसलिए client को पता नहीं था कि उसे किस प्रकार का data मिल रहा है। + +आप `StreamingResponse` की एक custom sub-class बना सकते हैं जो `Content-Type` header को उस प्रकार के data पर set करती है जिसे आप stream कर रहे हैं। + +उदाहरण के लिए, आप एक `PNGStreamingResponse` बना सकते हैं जो `media_type` attribute का उपयोग करके `Content-Type` header को `image/png` पर set करता है: + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[6,19:20] hl[20] *} + +फिर आप अपने *path operation function* में `response_class=PNGStreamingResponse` में इस नई class का उपयोग कर सकते हैं: + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[23:27] hl[23] *} + +### एक File का Simulation करें { #simulate-a-file } + +इस उदाहरण में, हम `io.BytesIO` के साथ एक file simulate कर रहे हैं, जो एक file-like object है जो केवल memory में रहता है, लेकिन हमें वही interface उपयोग करने देता है। + +उदाहरण के लिए, हम इसके contents consume करने के लिए इस पर iterate कर सकते हैं, जैसे हम किसी file के साथ कर सकते हैं। + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[1:27] hl[3,12:13,25] *} + +/// note | तकनीकी विवरण + +अन्य दो variables, `image_base64` और `binary_image`, Base64 में encoded एक image हैं, और फिर bytes में convert किए गए हैं, ताकि फिर उन्हें `io.BytesIO` को pass किया जा सके। + +सिर्फ इसलिए ताकि इस उदाहरण के लिए यह उसी file में रह सके और आप इसे copy करके जैसा है वैसा ही run कर सकें। 🥚 + +/// + +`with` block का उपयोग करके, हम यह सुनिश्चित करते हैं कि generator function (`yield` वाला function) पूरा होने के बाद file-like object बंद हो जाए। यानी, response भेजना पूरा होने के बाद। + +इस विशिष्ट उदाहरण में यह उतना महत्वपूर्ण नहीं होगा क्योंकि यह एक fake in-memory file है (`io.BytesIO` के साथ), लेकिन एक वास्तविक file के साथ, यह सुनिश्चित करना महत्वपूर्ण होगा कि इसके साथ काम पूरा होने के बाद file बंद हो जाए। + +### Files और Async { #files-and-async } + +अधिकांश मामलों में, file-like objects default रूप से async और await के साथ compatible नहीं होते। + +उदाहरण के लिए, उनके पास `await file.read()` या `async for chunk in file` नहीं होता। + +और कई मामलों में, उन्हें पढ़ना एक blocking operation होगा (जो event loop को block कर सकता है), क्योंकि उन्हें disk या network से पढ़ा जाता है। + +/// note | नोट + +ऊपर दिया गया उदाहरण वास्तव में एक exception है, क्योंकि `io.BytesIO` object पहले से memory में है, इसलिए उसे पढ़ना किसी चीज़ को block नहीं करेगा। + +लेकिन कई मामलों में किसी file या file-like object को पढ़ना block करेगा। + +/// + +event loop को block करने से बचने के लिए, आप बस *path operation function* को `async def` के बजाय regular `def` के साथ declare कर सकते हैं, इस तरह FastAPI इसे main loop को block करने से बचाने के लिए threadpool worker पर run करेगा। + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[30:34] hl[31] *} + +/// tip | सुझाव + +अगर आपको किसी async function के अंदर से blocking code call करना हो, या किसी blocking function के अंदर से async function call करना हो, तो आप [Asyncer](https://asyncer.tiangolo.com) का उपयोग कर सकते हैं, जो FastAPI की एक sibling library है। + +/// + +### `yield from` { #yield-from } + +जब आप किसी चीज़ पर iterate कर रहे हों, जैसे किसी file-like object पर, और फिर प्रत्येक item के लिए `yield` कर रहे हों, तो आप प्रत्येक item को सीधे yield करने और `for` loop को skip करने के लिए `yield from` का भी उपयोग कर सकते हैं। + +यह FastAPI के लिए विशेष नहीं है, यह सिर्फ Python है, लेकिन यह जानने लायक एक अच्छा trick है। 😎 + +{* ../../docs_src/stream_data/tutorial002_py310.py ln[37:40] hl[40] *} diff --git a/docs/hi/docs/advanced/strict-content-type.md b/docs/hi/docs/advanced/strict-content-type.md new file mode 100644 index 000000000..a63081024 --- /dev/null +++ b/docs/hi/docs/advanced/strict-content-type.md @@ -0,0 +1,88 @@ +# सख्त Content-Type जाँच { #strict-content-type-checking } + +default रूप से, **FastAPI** JSON request bodies के लिए सख्त `Content-Type` header जाँच का उपयोग करता है, इसका मतलब है कि body को JSON के रूप में parse करने के लिए JSON requests में वैध `Content-Type` header (जैसे `application/json`) **होना ही चाहिए**। + +## CSRF जोखिम { #csrf-risk } + +यह default व्यवहार एक बहुत विशिष्ट परिस्थिति में **Cross-Site Request Forgery (CSRF)** हमलों के एक वर्ग से सुरक्षा प्रदान करता है। + +ये हमले इस बात का फायदा उठाते हैं कि browsers scripts को बिना कोई CORS preflight check किए requests भेजने देते हैं, जब वे: + +* `Content-Type` header नहीं रखते (जैसे `Blob` body के साथ `fetch()` का उपयोग करना) +* और कोई authentication credentials नहीं भेजते। + +इस प्रकार का हमला मुख्य रूप से तब relevant होता है जब: + +* application स्थानीय रूप से चल रही हो (जैसे `localhost` पर) या किसी internal network में +* और application में कोई authentication न हो, वह यह मानती हो कि उसी network से आने वाली कोई भी request भरोसेमंद हो सकती है। + +## उदाहरण हमला { #example-attack } + +कल्पना करें कि आप एक local AI agent चलाने का तरीका बनाते हैं। + +यह यहाँ एक API प्रदान करता है + +``` +http://localhost:8000/v1/agents/multivac +``` + +यहाँ एक frontend भी है + +``` +http://localhost:8000 +``` + +/// tip | सुझाव + +ध्यान दें कि दोनों का host समान है। + +/// + +फिर frontend का उपयोग करके आप AI agent से अपनी ओर से काम करवा सकते हैं। + +क्योंकि यह **स्थानीय रूप से** चल रहा है, और खुले internet पर नहीं है, आप **कोई authentication setup न करने** का निर्णय लेते हैं, बस local network तक access पर भरोसा करते हुए। + +फिर आपके users में से कोई इसे install करके locally चला सकता है। + +फिर वे कोई malicious website खोल सकते हैं, जैसे कुछ इस तरह + +``` +https://evilhackers.example.com +``` + +और वह malicious website `Blob` body के साथ `fetch()` का उपयोग करके local API पर requests भेजती है + +``` +http://localhost:8000/v1/agents/multivac +``` + +भले ही malicious website और local app का host अलग हो, browser CORS preflight request trigger नहीं करेगा क्योंकि: + +* यह बिना किसी authentication के चल रहा है, इसे कोई credentials भेजने की जरूरत नहीं है। +* browser को लगता है कि यह JSON नहीं भेज रहा है (`Content-Type` header गायब होने के कारण)। + +फिर malicious website local AI agent से user के ex-boss को गुस्से भरे messages भेजवा सकती है... या उससे भी बुरा। 😅 + +## खुला Internet { #open-internet } + +अगर आपकी app खुले internet पर है, तो आप "network पर भरोसा" नहीं करेंगे और किसी को भी बिना authentication के privileged requests भेजने नहीं देंगे। + +Attackers सीधे आपकी API पर requests भेजने के लिए script चला सकते हैं, browser interaction की कोई जरूरत नहीं, इसलिए आप शायद पहले से ही किसी भी privileged endpoints को secure कर रहे होंगे। + +उस स्थिति में **यह हमला / जोखिम आप पर लागू नहीं होता**। + +यह जोखिम और हमला मुख्य रूप से तब relevant होता है जब app **local network** पर चलती है और वही **एकमात्र मानी गई सुरक्षा** होती है। + +## Content-Type के बिना Requests की अनुमति देना { #allowing-requests-without-content-type } + +अगर आपको ऐसे clients को support करना है जो `Content-Type` header नहीं भेजते, तो आप `strict_content_type=False` set करके strict checking disable कर सकते हैं: + +{* ../../docs_src/strict_content_type/tutorial001_py310.py hl[4] *} + +इस setting के साथ, जिन requests में `Content-Type` header नहीं होगा, उनकी body JSON के रूप में parse की जाएगी, जो FastAPI के पुराने versions जैसा ही व्यवहार है। + +/// note | नोट + +यह व्यवहार और configuration FastAPI 0.132.0 में जोड़ा गया था। + +/// diff --git a/docs/hi/docs/advanced/sub-applications.md b/docs/hi/docs/advanced/sub-applications.md new file mode 100644 index 000000000..3f4ea6da7 --- /dev/null +++ b/docs/hi/docs/advanced/sub-applications.md @@ -0,0 +1,67 @@ +# Sub Applications - Mounts { #sub-applications-mounts } + +अगर आपको दो स्वतंत्र FastAPI applications चाहिए, जिनका अपना स्वतंत्र OpenAPI और अपनी docs UIs हों, तो आप एक मुख्य app रख सकते हैं और एक (या अधिक) sub-application(s) को "mount" कर सकते हैं। + +## **FastAPI** application को Mount करना { #mounting-a-fastapi-application } + +"Mounting" का मतलब है किसी विशिष्ट path में पूरी तरह "स्वतंत्र" application जोड़ना, जो फिर उस path के अंतर्गत सब कुछ handle करने का ध्यान रखता है, उस sub-application में घोषित _path operations_ के साथ। + +### Top-level application { #top-level-application } + +सबसे पहले, मुख्य, top-level **FastAPI** application और उसके *path operations* बनाएँ: + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[3, 6:8] *} + +### Sub-application { #sub-application } + +फिर, अपनी sub-application और उसके *path operations* बनाएँ। + +यह sub-application बस एक और standard FastAPI application है, लेकिन यही वह है जिसे "mounted" किया जाएगा: + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 14:16] *} + +### Sub-application को mount करें { #mount-the-sub-application } + +अपने top-level application, `app`, में sub-application, `subapi`, को mount करें। + +इस मामले में, इसे path `/subapi` पर mount किया जाएगा: + +{* ../../docs_src/sub_applications/tutorial001_py310.py hl[11, 19] *} + +### Automatic API docs देखें { #check-the-automatic-api-docs } + +अब, `fastapi` command चलाएँ: + +
+ +```console +$ fastapi dev + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +और docs को [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) पर खोलें। + +आप मुख्य app के लिए automatic API docs देखेंगे, जिसमें केवल उसके अपने _path operations_ शामिल होंगे: + + + +और फिर, sub-application के लिए docs को [http://127.0.0.1:8000/subapi/docs](http://127.0.0.1:8000/subapi/docs) पर खोलें। + +आप sub-application के लिए automatic API docs देखेंगे, जिसमें केवल उसके अपने _path operations_ शामिल होंगे, सभी सही sub-path prefix `/subapi` के अंतर्गत: + + + +अगर आप दोनों user interfaces में से किसी के साथ interact करने की कोशिश करते हैं, तो वे सही तरह काम करेंगे, क्योंकि browser हर specific app या sub-app से बात कर पाएगा। + +### तकनीकी विवरण: `root_path` { #technical-details-root-path } + +जब आप ऊपर बताए गए तरीके से कोई sub-application mount करते हैं, तो FastAPI sub-application के लिए mount path communicate करने का ध्यान रखेगा, ASGI specification के एक mechanism का उपयोग करके जिसे `root_path` कहा जाता है। + +इस तरह, sub-application को पता होगा कि docs UI के लिए उस path prefix का उपयोग करना है। + +और sub-application की अपनी mounted sub-applications भी हो सकती हैं और सब कुछ सही तरह काम करेगा, क्योंकि FastAPI इन सभी `root_path`s को अपने आप handle करता है। + +आप `root_path` के बारे में और इसे स्पष्ट रूप से कैसे उपयोग करें, यह [Behind a Proxy](behind-a-proxy.md) वाले section में और सीखेंगे। diff --git a/docs/hi/docs/advanced/templates.md b/docs/hi/docs/advanced/templates.md new file mode 100644 index 000000000..b16ef4a6e --- /dev/null +++ b/docs/hi/docs/advanced/templates.md @@ -0,0 +1,126 @@ +# Templates { #templates } + +आप **FastAPI** के साथ अपनी पसंद का कोई भी template engine उपयोग कर सकते हैं। + +एक आम विकल्प Jinja2 है, वही जिसे Flask और अन्य tools उपयोग करते हैं। + +इसे आसानी से configure करने के लिए utilities उपलब्ध हैं जिन्हें आप सीधे अपने **FastAPI** application में उपयोग कर सकते हैं (Starlette द्वारा प्रदान की गई)। + +## Dependencies install करें { #install-dependencies } + +सुनिश्चित करें कि आप एक [virtual environment](../virtual-environments.md) बनाएँ, उसे activate करें, और `jinja2` install करें: + +
+ +```console +$ pip install jinja2 + +---> 100% +``` + +
+ +## `Jinja2Templates` का उपयोग करना { #using-jinja2templates } + +* `Jinja2Templates` import करें। +* एक `templates` object बनाएँ जिसे आप बाद में फिर से उपयोग कर सकें। +* उस *path operation* में एक `Request` parameter declare करें जो एक template return करेगा। +* आपने जो `templates` बनाया है, उसका उपयोग करके एक `TemplateResponse` render और return करें; template का नाम, request object, और key-value pairs वाली एक "context" dictionary pass करें, जिनका उपयोग Jinja2 template के अंदर किया जाएगा। + +{* ../../docs_src/templates/tutorial001_py310.py hl[4,11,15:18] *} + +/// note | नोट + +FastAPI 0.108.0, Starlette 0.29.0 से पहले, `name` पहला parameter था। + +साथ ही, उससे पहले के versions में, `request` object को Jinja2 के context में key-value pairs के हिस्से के रूप में pass किया जाता था। + +/// + +/// tip | सुझाव + +`response_class=HTMLResponse` declare करने से docs UI यह जान पाएगा कि response HTML होगा। + +/// + +/// note | तकनीकी विवरण + +आप `from starlette.templating import Jinja2Templates` भी उपयोग कर सकते हैं। + +**FastAPI** आपकी सुविधा के लिए, developer के रूप में, वही `starlette.templating` `fastapi.templating` के रूप में प्रदान करता है। लेकिन उपलब्ध अधिकांश responses सीधे Starlette से आते हैं। `Request` और `StaticFiles` के साथ भी यही है। + +/// + +## Templates लिखना { #writing-templates } + +फिर आप `templates/item.html` पर एक template लिख सकते हैं, उदाहरण के लिए: + +```jinja hl_lines="7" +{!../../docs_src/templates/templates/item.html!} +``` + +### Template Context Values { #template-context-values } + +उस HTML में जिसमें यह शामिल है: + +{% raw %} + +```jinja +Item ID: {{ id }} +``` + +{% endraw %} + +...यह आपके द्वारा pass किए गए "context" `dict` से लिया गया `id` दिखाएगा: + +```Python +{"id": id} +``` + +उदाहरण के लिए, `42` की ID के साथ, यह render होगा: + +```html +Item ID: 42 +``` + +### Template `url_for` Arguments { #template-url-for-arguments } + +आप template के अंदर `url_for()` का भी उपयोग कर सकते हैं, यह arguments के रूप में वही arguments लेता है जो आपके *path operation function* द्वारा उपयोग किए जाते। + +इसलिए, इस section के साथ: + +{% raw %} + +```jinja + +``` + +{% endraw %} + +...यह उसी URL का link generate करेगा जिसे *path operation function* `read_item(id=id)` handle करेगा। + +उदाहरण के लिए, `42` की ID के साथ, यह render होगा: + +```html + +``` + +## Templates और static files { #templates-and-static-files } + +आप template के अंदर `url_for()` का भी उपयोग कर सकते हैं, और इसे, उदाहरण के लिए, उन `StaticFiles` के साथ उपयोग कर सकते हैं जिन्हें आपने `name="static"` के साथ mount किया है। + +```jinja hl_lines="4" +{!../../docs_src/templates/templates/item.html!} +``` + +इस उदाहरण में, यह `static/styles.css` पर मौजूद CSS file से link करेगा: + +```CSS hl_lines="4" +{!../../docs_src/templates/static/styles.css!} +``` + +और क्योंकि आप `StaticFiles` उपयोग कर रहे हैं, वह CSS file आपके **FastAPI** application द्वारा URL `/static/styles.css` पर automatic रूप से serve की जाएगी। + +## अधिक विवरण { #more-details } + +अधिक विवरण के लिए, जिसमें templates को test करना भी शामिल है, [templates पर Starlette के docs](https://www.starlette.dev/templates/) देखें। diff --git a/docs/hi/docs/advanced/testing-dependencies.md b/docs/hi/docs/advanced/testing-dependencies.md new file mode 100644 index 000000000..f8eb0f312 --- /dev/null +++ b/docs/hi/docs/advanced/testing-dependencies.md @@ -0,0 +1,53 @@ +# Overrides के साथ Dependencies की Testing { #testing-dependencies-with-overrides } + +## Testing के दौरान dependencies को override करना { #overriding-dependencies-during-testing } + +कुछ scenarios होते हैं जहाँ आप testing के दौरान किसी dependency को override करना चाह सकते हैं। + +आप नहीं चाहते कि original dependency चले (और न ही उसकी कोई sub-dependencies चलें)। + +इसके बजाय, आप एक अलग dependency देना चाहते हैं जो केवल tests के दौरान इस्तेमाल होगी (संभवतः केवल कुछ खास tests में), और वह एक ऐसा value देगी जिसे वहाँ इस्तेमाल किया जा सके जहाँ original dependency का value इस्तेमाल किया जाता था। + +### Use cases: external service { #use-cases-external-service } + +एक उदाहरण यह हो सकता है कि आपके पास एक external authentication provider हो जिसे आपको call करना हो। + +आप उसे एक token भेजते हैं और वह एक authenticated user लौटाता है। + +यह provider आपसे प्रति request शुल्क ले सकता है, और इसे call करने में tests के लिए एक fixed mock user रखने की तुलना में कुछ अतिरिक्त समय लग सकता है। + +आप शायद external provider को एक बार test करना चाहेंगे, लेकिन हर चलने वाले test के लिए उसे call करना जरूरी नहीं होगा। + +इस मामले में, आप उस dependency को override कर सकते हैं जो उस provider को call करती है, और अपनी tests के लिए एक custom dependency इस्तेमाल कर सकते हैं जो एक mock user लौटाती है। + +### `app.dependency_overrides` attribute का उपयोग करें { #use-the-app-dependency-overrides-attribute } + +इन मामलों के लिए, आपकी **FastAPI** application में एक attribute `app.dependency_overrides` होता है, यह एक simple `dict` है। + +Testing के लिए किसी dependency को override करने के लिए, आप key के रूप में original dependency (एक function) रखते हैं, और value के रूप में अपना dependency override (दूसरा function) रखते हैं। + +और फिर **FastAPI** original dependency की बजाय उस override को call करेगा। + +{* ../../docs_src/dependency_testing/tutorial001_an_py310.py hl[26:27,30] *} + +/// tip | सुझाव + +आप अपनी **FastAPI** application में कहीं भी इस्तेमाल की गई dependency के लिए dependency override set कर सकते हैं। + +Original dependency किसी *path operation function*, किसी *path operation decorator* (जब आप return value का उपयोग नहीं करते), किसी `.include_router()` call आदि में इस्तेमाल हो सकती है। + +FastAPI फिर भी उसे override कर पाएगा। + +/// + +फिर आप `app.dependency_overrides` को एक खाली `dict` पर set करके अपने overrides reset कर सकते हैं (उन्हें हटा सकते हैं): + +```Python +app.dependency_overrides = {} +``` + +/// tip | सुझाव + +यदि आप किसी dependency को केवल कुछ tests के दौरान override करना चाहते हैं, तो आप test की शुरुआत में (test function के अंदर) override set कर सकते हैं और अंत में (test function के अंत में) उसे reset कर सकते हैं। + +/// diff --git a/docs/hi/docs/advanced/testing-events.md b/docs/hi/docs/advanced/testing-events.md new file mode 100644 index 000000000..3f09fe193 --- /dev/null +++ b/docs/hi/docs/advanced/testing-events.md @@ -0,0 +1,12 @@ +# Testing Events: lifespan और startup - shutdown { #testing-events-lifespan-and-startup-shutdown } + +जब आपको अपने tests में `lifespan` चलाने की ज़रूरत हो, तो आप `with` statement के साथ `TestClient` का उपयोग कर सकते हैं: + +{* ../../docs_src/app_testing/tutorial004_py310.py hl[9:15,18,27:28,30:32,41:43] *} + + +आप इसके बारे में अधिक विवरण ["आधिकारिक Starlette documentation site में tests में lifespan चलाना।"](https://www.starlette.dev/lifespan/#running-lifespan-in-tests) में पढ़ सकते हैं। + +deprecated `startup` और `shutdown` event के लिए, आप `TestClient` का उपयोग इस प्रकार कर सकते हैं: + +{* ../../docs_src/app_testing/tutorial003_py310.py hl[9:12,20:24] *} diff --git a/docs/hi/docs/advanced/testing-websockets.md b/docs/hi/docs/advanced/testing-websockets.md new file mode 100644 index 000000000..470b079a8 --- /dev/null +++ b/docs/hi/docs/advanced/testing-websockets.md @@ -0,0 +1,13 @@ +# WebSockets की Testing { #testing-websockets } + +आप WebSockets को test करने के लिए उसी `TestClient` का उपयोग कर सकते हैं। + +इसके लिए, आप `TestClient` को एक `with` statement में उपयोग करते हैं, WebSocket से connect करते हुए: + +{* ../../docs_src/app_testing/tutorial002_py310.py hl[27:31] *} + +/// note | नोट + +अधिक जानकारी के लिए, Starlette की documentation में [WebSockets की testing](https://www.starlette.dev/testclient/#testing-websocket-sessions) देखें। + +/// diff --git a/docs/hi/docs/advanced/using-request-directly.md b/docs/hi/docs/advanced/using-request-directly.md new file mode 100644 index 000000000..8110e550f --- /dev/null +++ b/docs/hi/docs/advanced/using-request-directly.md @@ -0,0 +1,56 @@ +# Request को सीधे इस्तेमाल करना { #using-the-request-directly } + +अब तक, आप request के जिन हिस्सों की ज़रूरत है, उन्हें उनके types के साथ declare करते रहे हैं। + +Data लेना: + +* path से parameters के रूप में। +* Headers। +* Cookies। +* आदि। + +और ऐसा करके, **FastAPI** उस data को validate कर रहा है, उसे convert कर रहा है और आपकी API के लिए documentation अपने-आप generate कर रहा है। + +लेकिन ऐसी स्थितियाँ होती हैं जहाँ आपको `Request` object को सीधे access करने की ज़रूरत हो सकती है। + +## `Request` object के बारे में विवरण { #details-about-the-request-object } + +क्योंकि **FastAPI** असल में नीचे से **Starlette** है, जिसके ऊपर कई tools की एक layer है, इसलिए जब ज़रूरत हो, आप Starlette के [`Request`](https://www.starlette.dev/requests/) object को सीधे इस्तेमाल कर सकते हैं। + +इसका मतलब यह भी होगा कि अगर आप `Request` object से सीधे data लेते हैं (उदाहरण के लिए, body पढ़ते हैं), तो FastAPI उसे validate, convert या document नहीं करेगा (OpenAPI के साथ, automatic API user interface के लिए)। + +हालाँकि कोई भी अन्य parameter जो सामान्य रूप से declare किया गया हो (उदाहरण के लिए, Pydantic model के साथ body), वह फिर भी validate, convert, annotate आदि होगा। + +लेकिन कुछ विशिष्ट मामले हैं जहाँ `Request` object लेना उपयोगी होता है। + +## `Request` object को सीधे इस्तेमाल करें { #use-the-request-object-directly } + +मान लीजिए कि आप अपनी *path operation function* के अंदर client का IP address/host लेना चाहते हैं। + +इसके लिए आपको request को सीधे access करना होगा। + +{* ../../docs_src/using_request_directly/tutorial001_py310.py hl[1,7:8] *} + +`Request` type वाले *path operation function* parameter को declare करके, **FastAPI** जान जाएगा कि उस parameter में `Request` pass करना है। + +/// tip | सुझाव + +ध्यान दें कि इस मामले में, हम request parameter के साथ एक path parameter declare कर रहे हैं। + +इसलिए, path parameter extract किया जाएगा, validate किया जाएगा, specified type में convert किया जाएगा और OpenAPI के साथ annotate किया जाएगा। + +इसी तरह, आप किसी भी अन्य parameter को सामान्य रूप से declare कर सकते हैं, और साथ ही `Request` भी प्राप्त कर सकते हैं। + +/// + +## `Request` documentation { #request-documentation } + +आप [`Request` object के बारे में official Starlette documentation site](https://www.starlette.dev/requests/) पर और विवरण पढ़ सकते हैं। + +/// note | तकनीकी विवरण + +आप `from starlette.requests import Request` भी इस्तेमाल कर सकते हैं। + +**FastAPI** इसे सीधे सिर्फ आपकी, developer की, सुविधा के लिए प्रदान करता है। लेकिन यह सीधे Starlette से आता है। + +/// diff --git a/docs/hi/docs/advanced/websockets.md b/docs/hi/docs/advanced/websockets.md new file mode 100644 index 000000000..9e761a900 --- /dev/null +++ b/docs/hi/docs/advanced/websockets.md @@ -0,0 +1,186 @@ +# WebSockets { #websockets } + +आप **FastAPI** के साथ [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) का उपयोग कर सकते हैं। + +## `websockets` install करें { #install-websockets } + +सुनिश्चित करें कि आप एक [virtual environment](../virtual-environments.md) बनाएँ, उसे activate करें, और `websockets` install करें (एक Python library जो "WebSocket" protocol का उपयोग आसान बनाती है): + +
+ +```console +$ pip install websockets + +---> 100% +``` + +
+ +## WebSockets client { #websockets-client } + +### production में { #in-production } + +आपके production system में, संभवतः आपके पास React, Vue.js या Angular जैसे आधुनिक framework से बना frontend होगा। + +और अपने backend के साथ WebSockets का उपयोग करके संवाद करने के लिए आप संभवतः अपने frontend की utilities का उपयोग करेंगे। + +या आपके पास एक native mobile application हो सकती है जो सीधे native code में आपके WebSocket backend से संवाद करती हो। + +या आपके पास WebSocket endpoint से संवाद करने का कोई और तरीका हो सकता है। + +--- + +लेकिन इस उदाहरण के लिए, हम कुछ JavaScript के साथ एक बहुत सरल HTML document का उपयोग करेंगे, सब कुछ एक लंबी string के अंदर। + +बेशक, यह optimal नहीं है और आप इसे production के लिए उपयोग नहीं करेंगे। + +production में आपके पास ऊपर दिए गए विकल्पों में से एक होगा। + +लेकिन WebSockets के server-side पर ध्यान केंद्रित करने और एक working उदाहरण पाने का यह सबसे सरल तरीका है: + +{* ../../docs_src/websockets_/tutorial001_py310.py hl[2,6:38,41:43] *} + +## एक `websocket` बनाएँ { #create-a-websocket } + +अपने **FastAPI** application में, एक `websocket` बनाएँ: + +{* ../../docs_src/websockets_/tutorial001_py310.py hl[1,46:47] *} + +/// note | तकनीकी विवरण + +आप `from starlette.websockets import WebSocket` का भी उपयोग कर सकते हैं। + +**FastAPI** वही `WebSocket` सीधे उपलब्ध कराता है, सिर्फ़ आपकी सुविधा के लिए, developer के रूप में। लेकिन यह सीधे Starlette से आता है। + +/// + +## messages का await करें और messages भेजें { #await-for-messages-and-send-messages } + +अपने WebSocket route में आप messages के लिए `await` कर सकते हैं और messages भेज सकते हैं। + +{* ../../docs_src/websockets_/tutorial001_py310.py hl[48:52] *} + +आप binary, text, और JSON data receive और send कर सकते हैं। + +## इसे आज़माएँ { #try-it } + +अपना code `main.py` file में रखें और फिर अपना application चलाएँ: + +
+ +```console +$ fastapi dev + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +अपने browser में [http://127.0.0.1:8000](http://127.0.0.1:8000) खोलें। + +आपको ऐसा एक सरल page दिखेगा: + + + +आप input box में messages टाइप कर सकते हैं, और उन्हें भेज सकते हैं: + + + +और WebSockets के साथ आपका **FastAPI** application जवाब देगा: + + + +आप कई messages भेज (और receive कर) सकते हैं: + + + +और वे सभी उसी WebSocket connection का उपयोग करेंगे। + +## `Depends` और अन्य का उपयोग { #using-depends-and-others } + +WebSocket endpoints में आप `fastapi` से import कर सकते हैं और उपयोग कर सकते हैं: + +* `Depends` +* `Security` +* `Cookie` +* `Header` +* `Path` +* `Query` + +वे अन्य FastAPI endpoints/*path operations* की तरह ही काम करते हैं: + +{* ../../docs_src/websockets_/tutorial002_an_py310.py hl[68:69,82] *} + +/// note | नोट + +क्योंकि यह एक WebSocket है, इसलिए `HTTPException` raise करना वास्तव में उचित नहीं है, इसके बजाय हम `WebSocketException` raise करते हैं। + +आप [specification में परिभाषित valid codes](https://tools.ietf.org/html/rfc6455#section-7.4.1) में से एक closing code का उपयोग कर सकते हैं। + +/// + +### dependencies के साथ WebSockets आज़माएँ { #try-the-websockets-with-dependencies } + +अपना application चलाएँ: + +
+ +```console +$ fastapi dev + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +अपने browser में [http://127.0.0.1:8000](http://127.0.0.1:8000) खोलें। + +वहाँ आप सेट कर सकते हैं: + +* path में उपयोग किया गया "Item ID"। +* query parameter के रूप में उपयोग किया गया "Token"। + +/// tip | सुझाव + +ध्यान दें कि query `token` को एक dependency द्वारा handle किया जाएगा। + +/// + +इसके साथ आप WebSocket connect कर सकते हैं और फिर messages भेज और receive कर सकते हैं: + + + +## disconnections और कई clients को handle करना { #handling-disconnections-and-multiple-clients } + +जब WebSocket connection बंद होता है, तो `await websocket.receive_text()` एक `WebSocketDisconnect` exception raise करेगा, जिसे आप इस उदाहरण की तरह catch और handle कर सकते हैं। + +{* ../../docs_src/websockets_/tutorial003_py310.py hl[79:81] *} + +इसे आज़माने के लिए: + +* app को कई browser tabs में खोलें। +* उनसे messages लिखें। +* फिर tabs में से एक को बंद करें। + +इससे `WebSocketDisconnect` exception raise होगा, और बाकी सभी clients को ऐसा message मिलेगा: + +``` +Client #1596980209979 left the chat +``` + +/// tip | सुझाव + +ऊपर दिया गया app एक minimal और सरल उदाहरण है, जो दिखाता है कि कई WebSocket connections को messages कैसे handle और broadcast किए जाएँ। + +लेकिन ध्यान रखें कि, चूँकि सब कुछ memory में, एक ही list में handle किया जाता है, यह केवल तब तक काम करेगा जब तक process चल रहा है, और केवल एक single process के साथ काम करेगा। + +अगर आपको कुछ ऐसा चाहिए जिसे FastAPI के साथ integrate करना आसान हो लेकिन जो अधिक robust हो, Redis, PostgreSQL या अन्य द्वारा supported हो, तो [encode/broadcaster](https://github.com/encode/broadcaster) देखें। + +/// + +## अधिक जानकारी { #more-info } + +विकल्पों के बारे में अधिक जानने के लिए, इनके लिए Starlette का documentation देखें: + +* [`WebSocket` class](https://www.starlette.dev/websockets/)। +* [Class-based WebSocket handling](https://www.starlette.dev/endpoints/#websocketendpoint)। diff --git a/docs/hi/docs/advanced/wsgi.md b/docs/hi/docs/advanced/wsgi.md new file mode 100644 index 000000000..1ea60d4e9 --- /dev/null +++ b/docs/hi/docs/advanced/wsgi.md @@ -0,0 +1,51 @@ +# WSGI शामिल करना - Flask, Django, अन्य { #including-wsgi-flask-django-others } + +आप WSGI applications को mount कर सकते हैं, जैसा आपने [Sub Applications - Mounts](sub-applications.md), [Proxy के पीछे](behind-a-proxy.md) में देखा। + +इसके लिए, आप `WSGIMiddleware` का उपयोग कर सकते हैं और इसे अपनी WSGI application को wrap करने के लिए इस्तेमाल कर सकते हैं, उदाहरण के लिए, Flask, Django, आदि। + +## `WSGIMiddleware` का उपयोग करना { #using-wsgimiddleware } + +/// note | नोट + +इसके लिए `a2wsgi` install करना required है, उदाहरण के लिए `pip install a2wsgi` के साथ। + +/// + +आपको `a2wsgi` से `WSGIMiddleware` import करना होगा। + +फिर WSGI (जैसे Flask) app को middleware के साथ wrap करें। + +और फिर उसे किसी path के अंतर्गत mount करें। + +{* ../../docs_src/wsgi/tutorial001_py310.py hl[1,3,23] *} + +/// note | नोट + +पहले, `fastapi.middleware.wsgi` से `WSGIMiddleware` का उपयोग करने की सलाह दी जाती थी, लेकिन अब यह deprecated है। + +इसके बजाय `a2wsgi` package का उपयोग करने की सलाह दी जाती है। उपयोग वही रहता है। + +बस यह सुनिश्चित करें कि आपके पास `a2wsgi` package install है और आप `a2wsgi` से `WSGIMiddleware` को सही ढंग से import करते हैं। + +/// + +## इसे जाँचें { #check-it } + +अब, path `/v1/` के अंतर्गत हर request को Flask application द्वारा handle किया जाएगा। + +और बाकी को **FastAPI** द्वारा handle किया जाएगा। + +यदि आप इसे run करते हैं और [http://localhost:8000/v1/](http://localhost:8000/v1/) पर जाते हैं, तो आपको Flask से response दिखाई देगा: + +```txt +Hello, World from Flask! +``` + +और यदि आप [http://localhost:8000/v2](http://localhost:8000/v2) पर जाते हैं, तो आपको FastAPI से response दिखाई देगा: + +```JSON +{ + "message": "Hello World" +} +``` diff --git a/docs/hi/docs/deployment/cloud.md b/docs/hi/docs/deployment/cloud.md new file mode 100644 index 000000000..f4c6087d3 --- /dev/null +++ b/docs/hi/docs/deployment/cloud.md @@ -0,0 +1,24 @@ +# Cloud Providers पर FastAPI Deploy करें { #deploy-fastapi-on-cloud-providers } + +आप अपनी FastAPI application deploy करने के लिए वस्तुतः **किसी भी cloud provider** का उपयोग कर सकते हैं। + +अधिकांश मामलों में, मुख्य cloud providers के पास उनके साथ FastAPI deploy करने के लिए guides होती हैं। + +## FastAPI Cloud { #fastapi-cloud } + +**[FastAPI Cloud](https://fastapicloud.com)** को **FastAPI** के पीछे मौजूद उसी author और team ने बनाया है। + +यह न्यूनतम प्रयास के साथ API को **build**, **deploy**, और **access** करने की प्रक्रिया को सरल बनाता है। + +यह FastAPI के साथ apps बनाने वाले उसी **developer experience** को उन्हें cloud पर **deploy** करने में भी लाता है। 🎉 + +FastAPI Cloud, *FastAPI and friends* open source projects का प्राथमिक sponsor और funding provider है। ✨ + +## Cloud Providers - Sponsors { #cloud-providers-sponsors } + +कुछ अन्य cloud providers भी ✨ [**FastAPI को sponsor करते हैं**](https://github.com/sponsors/tiangolo) ✨। 🙇 + +आप उनकी guides का पालन करने और उनकी services आज़माने के लिए उन पर भी विचार कर सकते हैं: + +* [Render](https://docs.render.com/deploy-fastapi?utm_source=deploydoc&utm_medium=referral&utm_campaign=fastapi) +* [Railway](https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi) diff --git a/docs/hi/docs/deployment/concepts.md b/docs/hi/docs/deployment/concepts.md new file mode 100644 index 000000000..de085e34b --- /dev/null +++ b/docs/hi/docs/deployment/concepts.md @@ -0,0 +1,321 @@ +# Deployments की अवधारणाएँ { #deployments-concepts } + +जब आप एक **FastAPI** application, या वास्तव में किसी भी प्रकार की web API, deploy करते हैं, तो कई अवधारणाएँ होती हैं जिनकी आपको शायद परवाह होगी, और उनका उपयोग करके आप अपनी application को **deploy करने** का **सबसे उपयुक्त** तरीका ढूँढ सकते हैं। + +कुछ महत्वपूर्ण अवधारणाएँ हैं: + +* सुरक्षा - HTTPS +* startup पर चलना +* Restarts +* Replication (चल रहे processes की संख्या) +* Memory +* शुरू करने से पहले के पिछले steps + +हम देखेंगे कि ये **deployments** को कैसे प्रभावित करेंगे। + +अंत में, अंतिम उद्देश्य यह है कि आप अपने **API clients को serve** कर सकें, वह भी ऐसे तरीके से जो **सुरक्षित** हो, **disruptions से बचाए**, और **compute resources** (जैसे remote servers/virtual machines) का यथासंभव कुशलता से उपयोग करे। 🚀 + +मैं यहाँ इन **अवधारणाओं** के बारे में थोड़ा और बताऊँगा, और उम्मीद है कि इससे आपको वह **intuition** मिलेगी जिसकी आपको अपनी API को बहुत अलग-अलग environments में deploy करने का निर्णय लेने के लिए आवश्यकता होगी, संभवतः ऐसे **future** environments में भी जो अभी मौजूद नहीं हैं। + +इन अवधारणाओं पर विचार करके, आप **अपनी खुद की APIs** को deploy करने का सबसे अच्छा तरीका **evaluate और design** कर पाएँगे। + +अगले chapters में, मैं आपको FastAPI applications deploy करने के लिए अधिक **ठोस recipes** दूँगा। + +लेकिन अभी के लिए, आइए इन महत्वपूर्ण **conceptual ideas** को देखें। ये अवधारणाएँ किसी भी अन्य प्रकार की web API पर भी लागू होती हैं। 💡 + +## सुरक्षा - HTTPS { #security-https } + +[HTTPS के बारे में पिछले chapter](https.md) में हमने सीखा कि HTTPS आपकी API के लिए encryption कैसे प्रदान करता है। + +हमने यह भी देखा कि HTTPS सामान्यतः आपके application server से **external** एक component, एक **TLS Termination Proxy**, द्वारा प्रदान किया जाता है। + +और **HTTPS certificates renew** करने का प्रभारी कुछ होना चाहिए, यह वही component हो सकता है या कुछ अलग भी हो सकता है। + +### HTTPS के लिए उदाहरण Tools { #example-tools-for-https } + +TLS Termination Proxy के रूप में आप जिन tools का उपयोग कर सकते हैं, उनमें से कुछ हैं: + +* Traefik + * Certificate renewals को अपने-आप संभालता है ✨ +* Caddy + * Certificate renewals को अपने-आप संभालता है ✨ +* Nginx + * Certificate renewals के लिए Certbot जैसे external component के साथ +* HAProxy + * Certificate renewals के लिए Certbot जैसे external component के साथ +* Nginx जैसे Ingress Controller के साथ Kubernetes + * Certificate renewals के लिए cert-manager जैसे external component के साथ +* Cloud provider द्वारा उनकी services के हिस्से के रूप में internally संभाला गया (नीचे पढ़ें 👇) + +एक और विकल्प यह है कि आप एक **cloud service** का उपयोग कर सकते हैं जो HTTPS setup करने सहित अधिक काम करती है। इसमें कुछ restrictions हो सकती हैं या आपसे अधिक charge लिया जा सकता है, आदि। लेकिन उस स्थिति में, आपको स्वयं TLS Termination Proxy setup नहीं करना पड़ेगा। + +अगले chapters में मैं आपको कुछ ठोस उदाहरण दिखाऊँगा। + +--- + +फिर विचार करने के लिए अगले concepts उस program के बारे में हैं जो आपकी वास्तविक API चला रहा है (जैसे Uvicorn)। + +## Program और Process { #program-and-process } + +हम चल रहे "**process**" के बारे में बहुत बात करेंगे, इसलिए यह स्पष्ट होना उपयोगी है कि इसका क्या अर्थ है, और "**program**" शब्द से इसका क्या अंतर है। + +### Program क्या है { #what-is-a-program } + +**Program** शब्द का उपयोग आम तौर पर कई चीजों का वर्णन करने के लिए किया जाता है: + +* वह **code** जो आप लिखते हैं, **Python files**। +* वह **file** जिसे operating system द्वारा **execute** किया जा सकता है, उदाहरण के लिए: `python`, `python.exe` या `uvicorn`। +* कोई विशेष program जब वह operating system पर **चल रहा** हो, CPU का उपयोग कर रहा हो, और memory में चीजें store कर रहा हो। इसे **process** भी कहा जाता है। + +### Process क्या है { #what-is-a-process } + +**Process** शब्द सामान्यतः अधिक विशिष्ट तरीके से उपयोग किया जाता है, केवल उस चीज़ के लिए जो operating system में चल रही होती है (जैसे ऊपर के अंतिम point में): + +* कोई विशेष program जब वह operating system पर **चल रहा** हो। + * यह न तो file को refer करता है, न code को, यह **विशेष रूप से** उस चीज़ को refer करता है जिसे operating system द्वारा **execute** और manage किया जा रहा है। +* कोई भी program, कोई भी code, **केवल तभी कुछ कर सकता है** जब उसे **execute** किया जा रहा हो। यानी, जब कोई **process चल रहा** हो। +* Process को आपके द्वारा, या operating system द्वारा **terminate** (या "kill") किया जा सकता है। उस point पर, वह चलना/execute होना बंद कर देता है, और वह **अब कुछ नहीं कर सकता**। +* आपके computer पर चल रही प्रत्येक application के पीछे कोई process होता है, प्रत्येक running program, प्रत्येक window, आदि। और computer चालू होने पर सामान्यतः कई processes **एक ही समय में** चल रहे होते हैं। +* **एक ही program** के **multiple processes** एक ही समय में चल सकते हैं। + +यदि आप अपने operating system में "task manager" या "system monitor" (या समान tools) देखते हैं, तो आप उनमें से कई processes चलते हुए देख पाएँगे। + +और, उदाहरण के लिए, आप शायद देखेंगे कि एक ही browser program (Firefox, Chrome, Edge, आदि) को चलाने वाले multiple processes हैं। वे सामान्यतः प्रति tab एक process चलाते हैं, साथ में कुछ अन्य extra processes भी। + + + +--- + +अब जब हम **process** और **program** शब्दों के बीच अंतर जानते हैं, तो deployments के बारे में बात जारी रखते हैं। + +## startup पर चलना { #running-on-startup } + +अधिकांश मामलों में, जब आप एक web API बनाते हैं, तो आप चाहते हैं कि वह **हमेशा चलती रहे**, बिना interruption के, ताकि आपके clients हमेशा उसे access कर सकें। यह निश्चित रूप से तब तक है जब तक आपके पास कोई विशेष कारण न हो कि आप उसे केवल कुछ स्थितियों में ही चलाना चाहते हैं, लेकिन अधिकांश समय आप चाहते हैं कि वह लगातार चलती रहे और **available** रहे। + +### Remote Server में { #in-a-remote-server } + +जब आप एक remote server (एक cloud server, एक virtual machine, आदि) setup करते हैं, तो सबसे सरल चीज़ जो आप कर सकते हैं वह है `fastapi run` (जो Uvicorn का उपयोग करता है) या कुछ समान, manually, ठीक उसी तरह जैसे आप local development करते समय करते हैं। + +और यह काम करेगा और **development के दौरान** उपयोगी होगा। + +लेकिन यदि server से आपका connection खो जाता है, तो **running process** शायद मर जाएगा। + +और यदि server restart होता है (उदाहरण के लिए updates के बाद, या cloud provider से migrations के बाद) तो आप शायद **इसे notice नहीं करेंगे**। और इसके कारण, आपको यह भी पता नहीं चलेगा कि आपको process को manually restart करना है। इसलिए, आपकी API बस dead ही रहेगी। 😱 + +### Startup पर Automatically चलाना { #run-automatically-on-startup } + +सामान्यतः, आप शायद चाहेंगे कि server program (जैसे Uvicorn) server startup पर automatically start हो, और किसी **human intervention** की आवश्यकता के बिना, ताकि आपकी API के साथ हमेशा एक process चल रहा हो (जैसे Uvicorn आपकी FastAPI app चला रहा हो)। + +### अलग Program { #separate-program } + +इसे हासिल करने के लिए, आपके पास सामान्यतः एक **अलग program** होगा जो सुनिश्चित करेगा कि आपकी application startup पर चले। और कई मामलों में, यह यह भी सुनिश्चित करेगा कि अन्य components या applications भी चलें, उदाहरण के लिए, एक database। + +### Startup पर चलाने के लिए उदाहरण Tools { #example-tools-to-run-at-startup } + +इस काम को करने वाले tools के कुछ उदाहरण हैं: + +* Docker +* Kubernetes +* Docker Compose +* Docker in Swarm Mode +* Systemd +* Supervisor +* Cloud provider द्वारा उनकी services के हिस्से के रूप में internally संभाला गया +* अन्य... + +अगले chapters में मैं आपको अधिक ठोस उदाहरण दूँगा। + +## Restarts { #restarts } + +यह सुनिश्चित करने जैसा कि आपकी application startup पर चले, आप शायद यह भी सुनिश्चित करना चाहेंगे कि failures के बाद उसे **restart** किया जाए। + +### हम गलतियाँ करते हैं { #we-make-mistakes } + +हम, मनुष्य के रूप में, हर समय **गलतियाँ** करते हैं। Software में लगभग *हमेशा* अलग-अलग जगहों पर **bugs** छिपे होते हैं। 🐛 + +और हम developers उन bugs को खोजते हुए और नई features implement करते हुए code को बेहतर बनाते रहते हैं (संभवतः नए bugs भी जोड़ते हुए 😅)। + +### छोटे Errors Automatically संभाले जाते हैं { #small-errors-automatically-handled } + +FastAPI के साथ web APIs बनाते समय, यदि हमारे code में कोई error है, तो FastAPI सामान्यतः उसे उस single request तक सीमित रखेगा जिसने error trigger किया। 🛡 + +Client को उस request के लिए **500 Internal Server Error** मिलेगा, लेकिन application पूरी तरह crash होने के बजाय अगली requests के लिए काम करती रहेगी। + +### बड़े Errors - Crashes { #bigger-errors-crashes } + +फिर भी, ऐसे मामले हो सकते हैं जहाँ हम कुछ code लिखते हैं जो **पूरी application को crash** कर देता है, जिससे Uvicorn और Python crash हो जाते हैं। 💥 + +और फिर भी, आप शायद नहीं चाहेंगे कि application केवल इसलिए dead रहे क्योंकि एक जगह error था, आप शायद चाहेंगे कि वह कम से कम उन *path operations* के लिए **चलती रहे** जो broken नहीं हैं। + +### Crash के बाद Restart { #restart-after-crash } + +लेकिन उन मामलों में जहाँ वास्तव में खराब errors running **process** को crash कर देते हैं, आप चाहेंगे कि एक external component process को **restart** करने का प्रभारी हो, कम से कम कुछ बार... + +/// tip | सुझाव + +...हालाँकि यदि पूरी application बस **तुरंत crash** हो रही है तो शायद उसे हमेशा restart करते रहने का कोई अर्थ नहीं है। लेकिन ऐसे मामलों में, आप शायद इसे development के दौरान, या कम से कम deployment के ठीक बाद notice करेंगे। + +तो आइए मुख्य मामलों पर focus करें, जहाँ यह **future** में कुछ विशेष मामलों में पूरी तरह crash हो सकती है, और फिर भी उसे restart करना समझ में आता है। + +/// + +आप शायद चाहेंगे कि आपकी application को restart करने का प्रभारी एक **external component** हो, क्योंकि उस point तक, Uvicorn और Python वाली वही application पहले ही crash हो चुकी होती है, इसलिए उसी app के उसी code में ऐसा कुछ नहीं होता जो इसके बारे में कुछ कर सके। + +### Automatically Restart करने के लिए उदाहरण Tools { #example-tools-to-restart-automatically } + +अधिकांश मामलों में, वही tool जो **startup पर program चलाने** के लिए उपयोग होता है, automatic **restarts** संभालने के लिए भी उपयोग होता है। + +उदाहरण के लिए, इसे ये संभाल सकते हैं: + +* Docker +* Kubernetes +* Docker Compose +* Docker in Swarm Mode +* Systemd +* Supervisor +* Cloud provider द्वारा उनकी services के हिस्से के रूप में internally संभाला गया +* अन्य... + +## Replication - Processes और Memory { #replication-processes-and-memory } + +FastAPI application के साथ, Uvicorn चलाने वाले `fastapi` command जैसे server program का उपयोग करते हुए, उसे **एक process** में एक बार चलाना multiple clients को concurrently serve कर सकता है। + +लेकिन कई मामलों में, आप एक ही समय में कई worker processes चलाना चाहेंगे। + +### Multiple Processes - Workers { #multiple-processes-workers } + +यदि आपके पास single process द्वारा handle किए जा सकने से अधिक clients हैं (उदाहरण के लिए यदि virtual machine बहुत बड़ी नहीं है) और server के CPU में **multiple cores** हैं, तो आप एक ही application के साथ **multiple processes** एक ही समय में चला सकते हैं, और सभी requests को उनके बीच distribute कर सकते हैं। + +जब आप उसी API program के **multiple processes** चलाते हैं, तो उन्हें आम तौर पर **workers** कहा जाता है। + +### Worker Processes और Ports { #worker-processes-and-ports } + +Docs [About HTTPS](https.md) से याद करें कि server में port और IP address के एक combination पर केवल एक process listen कर सकता है? + +यह अभी भी सही है। + +इसलिए, एक ही समय में **multiple processes** रखने में सक्षम होने के लिए, एक **single process port पर listening** होना चाहिए जो फिर communication को किसी तरीके से प्रत्येक worker process तक transmit करे। + +### प्रति Process Memory { #memory-per-process } + +अब, जब program memory में चीजें load करता है, उदाहरण के लिए, किसी variable में machine learning model, या किसी बड़े file की contents किसी variable में, तो वह सब server की **memory (RAM) का थोड़ा हिस्सा consume** करता है। + +और multiple processes सामान्यतः **कोई memory share नहीं करते**। इसका मतलब है कि प्रत्येक running process की अपनी चीजें, variables, और memory होती है। और यदि आप अपने code में बड़ी मात्रा में memory consume कर रहे हैं, तो **प्रत्येक process** उतनी ही memory consume करेगा। + +### Server Memory { #server-memory } + +उदाहरण के लिए, यदि आपका code **1 GB size** वाला Machine Learning model load करता है, तो जब आप अपनी API के साथ एक process चलाते हैं, तो वह कम से कम 1 GB RAM consume करेगा। और यदि आप **4 processes** (4 workers) start करते हैं, तो प्रत्येक 1 GB RAM consume करेगा। इसलिए कुल मिलाकर, आपकी API **4 GB RAM** consume करेगी। + +और यदि आपके remote server या virtual machine में केवल 3 GB RAM है, तो 4 GB से अधिक RAM load करने की कोशिश problems पैदा करेगी। 🚨 + +### Multiple Processes - एक उदाहरण { #multiple-processes-an-example } + +इस उदाहरण में, एक **Manager Process** है जो दो **Worker Processes** start और control करता है। + +यह Manager Process शायद IP में **port** पर listen करने वाला होगा। और यह सभी communication को worker processes तक transmit करेगा। + +वे worker processes वे होंगे जो आपकी application चला रहे होंगे, वे **request** प्राप्त करने और **response** return करने के लिए मुख्य computations करेंगे, और वे RAM में variables में डाली गई कोई भी चीज़ load करेंगे। + + + +और निश्चित रूप से, उसी machine पर आपकी application के अलावा शायद **अन्य processes** भी चल रहे होंगे। + +एक दिलचस्प detail यह है कि प्रत्येक process द्वारा **उपयोग किए गए CPU** का percentage समय के साथ बहुत **बदल** सकता है, लेकिन **memory (RAM)** सामान्यतः कम या ज्यादा **stable** रहती है। + +यदि आपके पास एक API है जो हर बार comparable amount की computations करती है और आपके पास बहुत सारे clients हैं, तो **CPU utilization** शायद *stable भी रहेगा* (लगातार तेजी से ऊपर-नीचे जाने के बजाय)। + +### Replication Tools और Strategies के उदाहरण { #examples-of-replication-tools-and-strategies } + +इसे हासिल करने के कई approaches हो सकते हैं, और मैं अगले chapters में specific strategies के बारे में अधिक बताऊँगा, उदाहरण के लिए Docker और containers के बारे में बात करते समय। + +विचार करने की मुख्य constraint यह है कि **public IP** में **port** को handle करने वाला एक **single** component होना चाहिए। और फिर उसके पास replicated **processes/workers** तक communication **transmit** करने का कोई तरीका होना चाहिए। + +यहाँ कुछ संभावित combinations और strategies हैं: + +* **Uvicorn** `--workers` के साथ + * एक Uvicorn **process manager** **IP** और **port** पर listen करेगा, और यह **multiple Uvicorn worker processes** start करेगा। +* **Kubernetes** और अन्य distributed **container systems** + * **Kubernetes** layer में कुछ **IP** और **port** पर listen करेगा। Replication **multiple containers** रखने से होगी, प्रत्येक में **एक Uvicorn process** चल रहा होगा। +* **Cloud services** जो यह आपके लिए संभालती हैं + * Cloud service शायद **आपके लिए replication handle** करेगी। यह संभवतः आपको **चलाने के लिए process**, या उपयोग करने के लिए **container image** define करने देगी, किसी भी स्थिति में, यह बहुत संभवतः **एक single Uvicorn process** होगा, और cloud service उसे replicate करने की प्रभारी होगी। + +/// tip | सुझाव + +यदि **containers**, Docker, या Kubernetes के बारे में इनमें से कुछ items अभी अधिक समझ में नहीं आते हैं तो चिंता न करें। + +मैं future chapter में container images, Docker, Kubernetes, आदि के बारे में अधिक बताऊँगा: [Containers में FastAPI - Docker](docker.md)। + +/// + +## शुरू करने से पहले के पिछले Steps { #previous-steps-before-starting } + +कई मामले ऐसे होते हैं जहाँ आप अपनी application **start करने से पहले** कुछ steps perform करना चाहते हैं। + +उदाहरण के लिए, आप **database migrations** चलाना चाह सकते हैं। + +लेकिन अधिकांश मामलों में, आप इन steps को केवल **एक बार** perform करना चाहेंगे। + +इसलिए, आप application start करने से पहले उन **previous steps** को perform करने के लिए एक **single process** रखना चाहेंगे। + +और आपको यह सुनिश्चित करना होगा कि उन previous steps को चलाने वाला एक ही process हो, *भले ही* बाद में आप application के लिए **multiple processes** (multiple workers) start करें। यदि वे steps **multiple processes** द्वारा चलाए गए, तो वे उन्हें **parallel** में चलाकर काम को **duplicate** कर देंगे, और यदि steps database migration जैसी delicate चीज़ हैं, तो वे एक-दूसरे के साथ conflicts पैदा कर सकते हैं। + +बेशक, कुछ मामले ऐसे होते हैं जहाँ previous steps को multiple times चलाने में कोई समस्या नहीं होती, उस स्थिति में इसे handle करना बहुत आसान होता है। + +/// tip | सुझाव + +साथ ही, ध्यान रखें कि आपके setup पर निर्भर करते हुए, कुछ मामलों में आपकी application start करने से पहले आपको **शायद किसी previous steps की आवश्यकता भी न हो**। + +उस स्थिति में, आपको इनमें से किसी भी चीज़ की चिंता नहीं करनी होगी। 🤷 + +/// + +### Previous Steps Strategies के उदाहरण { #examples-of-previous-steps-strategies } + +यह इस बात पर **बहुत अधिक निर्भर** करेगा कि आप **अपना system कैसे deploy** करते हैं, और यह शायद programs start करने, restarts handle करने, आदि के तरीके से जुड़ा होगा। + +यहाँ कुछ संभावित ideas हैं: + +* Kubernetes में एक "Init Container" जो आपके app container से पहले चलता है +* एक bash script जो previous steps चलाती है और फिर आपकी application start करती है + * आपको फिर भी *उस* bash script को start/restart करने, errors detect करने, आदि का तरीका चाहिए होगा। + +/// tip | सुझाव + +Containers के साथ ऐसा करने के लिए मैं future chapter में अधिक ठोस उदाहरण दूँगा: [Containers में FastAPI - Docker](docker.md)। + +/// + +## Resource Utilization { #resource-utilization } + +आपके server(s) एक **resource** हैं, जिन्हें आप अपने programs के साथ consume या **utilize** कर सकते हैं, CPUs पर computation time और उपलब्ध RAM memory का उपयोग करके। + +आप system resources का कितना हिस्सा consume/utilize करना चाहते हैं? "बहुत ज्यादा नहीं" सोचना आसान हो सकता है, लेकिन वास्तव में, आप शायद **crash किए बिना जितना संभव हो उतना** consume करना चाहेंगे। + +यदि आप 3 servers के लिए भुगतान कर रहे हैं लेकिन उनकी RAM और CPU का केवल थोड़ा सा उपयोग कर रहे हैं, तो आप शायद **पैसा बर्बाद कर रहे हैं** 💸, और शायद **server की electric power बर्बाद कर रहे हैं** 🌎, आदि। + +उस स्थिति में, केवल 2 servers रखना और उनके resources (CPU, memory, disk, network bandwidth, आदि) का उच्च percentage उपयोग करना बेहतर हो सकता है। + +दूसरी ओर, यदि आपके पास 2 servers हैं और आप उनके **CPU और RAM का 100%** उपयोग कर रहे हैं, तो किसी point पर एक process अधिक memory माँगेगा, और server को disk को "memory" के रूप में उपयोग करना पड़ेगा (जो हजारों गुना धीमा हो सकता है), या वह **crash** भी हो सकता है। या किसी process को कुछ computation करनी हो सकती है और उसे CPU के फिर से free होने तक wait करना पड़ेगा। + +इस मामले में, **एक extra server** लेना और उस पर कुछ processes चलाना बेहतर होगा ताकि उन सभी के पास **पर्याप्त RAM और CPU time** हो। + +यह भी संभावना है कि किसी कारण से आपकी API के usage में **spike** हो। शायद यह viral हो गई, या शायद कुछ अन्य services या bots इसका उपयोग शुरू कर दें। और आप उन मामलों में safe रहने के लिए extra resources रखना चाह सकते हैं। + +आप target करने के लिए एक **arbitrary number** रख सकते हैं, उदाहरण के लिए, resource utilization का **50% से 90% के बीच** कुछ। बात यह है कि ये शायद वे मुख्य चीजें हैं जिन्हें आप measure करना और अपने deployments tweak करने के लिए उपयोग करना चाहेंगे। + +आप अपने server में उपयोग किए गए CPU और RAM या प्रत्येक process द्वारा उपयोग की गई मात्रा देखने के लिए `htop` जैसे simple tools का उपयोग कर सकते हैं। या आप अधिक complex monitoring tools का उपयोग कर सकते हैं, जो servers में distributed हो सकते हैं, आदि। + +## Recap { #recap } + +आपने यहाँ कुछ मुख्य अवधारणाएँ पढ़ी हैं जिन्हें अपनी application को कैसे deploy करना है, यह तय करते समय आपको शायद ध्यान में रखना होगा: + +* सुरक्षा - HTTPS +* startup पर चलना +* Restarts +* Replication (चल रहे processes की संख्या) +* Memory +* शुरू करने से पहले के पिछले steps + +इन ideas को समझना और उन्हें apply करना आपको अपने deployments configure और tweak करते समय कोई भी decisions लेने के लिए आवश्यक intuition देना चाहिए। 🤓 + +अगले sections में, मैं आपको उन संभावित strategies के अधिक ठोस उदाहरण दूँगा जिनका आप पालन कर सकते हैं। 🚀 diff --git a/docs/hi/docs/deployment/docker.md b/docs/hi/docs/deployment/docker.md new file mode 100644 index 000000000..6e8bea03a --- /dev/null +++ b/docs/hi/docs/deployment/docker.md @@ -0,0 +1,618 @@ +# Containers में FastAPI - Docker { #fastapi-in-containers-docker } + +FastAPI applications deploy करते समय एक आम तरीका **Linux container image** बनाना है। यह सामान्यतः [**Docker**](https://www.docker.com/) का उपयोग करके किया जाता है। फिर आप उस container image को कुछ संभावित तरीकों में से किसी एक में deploy कर सकते हैं। + +Linux containers का उपयोग करने के कई लाभ हैं, जिनमें **security**, **replicability**, **simplicity**, और अन्य शामिल हैं। + +/// tip | टिप + +जल्दी में हैं और यह सब पहले से जानते हैं? नीचे दिए गए [`Dockerfile` पर जाएँ 👇](#build-a-docker-image-for-fastapi). + +/// + +
+Dockerfile Preview 👀 + +```Dockerfile +FROM python:3.14 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +COPY ./app /code/app + +CMD ["fastapi", "run", "app/main.py", "--port", "80"] + +# यदि Nginx या Traefik जैसे proxy के पीछे चला रहे हैं तो --proxy-headers जोड़ें +# CMD ["fastapi", "run", "app/main.py", "--port", "80", "--proxy-headers"] +``` + +
+ +## Container क्या है { #what-is-a-container } + +Containers (मुख्य रूप से Linux containers) applications को उनकी सभी dependencies और आवश्यक files सहित package करने का एक बहुत **lightweight** तरीका हैं, जबकि उन्हें उसी system में दूसरे containers (दूसरी applications या components) से isolated रखा जाता है। + +Linux containers host (machine, virtual machine, cloud server, आदि) के उसी Linux kernel का उपयोग करके चलते हैं। इसका मतलब बस इतना है कि वे बहुत lightweight होते हैं (पूरे operating system को emulate करने वाली full virtual machines की तुलना में)। + +इस तरह, containers **कम resources** consume करते हैं, लगभग उतने ही जितने processes को सीधे चलाने में लगते हैं (virtual machine बहुत अधिक consume करेगी)। + +Containers के अपने **isolated** running processes (आमतौर पर सिर्फ एक process), file system, और network भी होते हैं, जिससे deployment, security, development, आदि सरल हो जाते हैं। + +## Container Image क्या है { #what-is-a-container-image } + +एक **container** एक **container image** से चलाया जाता है। + +Container image उन सभी files, environment variables, और default command/program का **static** version होता है जो container में मौजूद होना चाहिए। यहाँ **Static** का मतलब है कि container **image** चल नहीं रही है, execute नहीं हो रही है, यह सिर्फ packaged files और metadata है। + +"**container image**" जो stored static contents है, उसके विपरीत, "**container**" सामान्यतः running instance को संदर्भित करता है, वह चीज़ जो **execute** हो रही है। + +जब **container** start होकर running होता है (**container image** से start किया गया), तो यह files, environment variables, आदि बना या बदल सकता है। वे बदलाव केवल उस container में मौजूद होंगे, लेकिन underlying container image में persist नहीं होंगे (disk पर save नहीं होंगे)। + +Container image की तुलना **program** file और contents से की जा सकती है, जैसे `python` और कोई file `main.py`। + +और **container** स्वयं (**container image** के विपरीत) image का वास्तविक running instance है, जिसकी तुलना **process** से की जा सकती है। वास्तव में, container केवल तब running होता है जब उसमें **process running** हो (और आमतौर पर यह केवल एक single process होता है)। जब उसमें कोई process running नहीं रहता, तो container stop हो जाता है। + +## Container Images { #container-images } + +Docker **container images** और **containers** बनाने और manage करने के मुख्य tools में से एक रहा है। + +और एक public [Docker Hub](https://hub.docker.com/) है जिसमें कई tools, environments, databases, और applications के लिए पहले से बनी **official container images** हैं। + +उदाहरण के लिए, एक official [Python Image](https://hub.docker.com/_/python) है। + +और databases जैसी अलग-अलग चीज़ों के लिए कई अन्य images हैं, उदाहरण के लिए: + +* [PostgreSQL](https://hub.docker.com/_/postgres) +* [MySQL](https://hub.docker.com/_/mysql) +* [MongoDB](https://hub.docker.com/_/mongo) +* [Redis](https://hub.docker.com/_/redis), आदि। + +पहले से बनी container image का उपयोग करके अलग-अलग tools को **combine** और use करना बहुत आसान है। उदाहरण के लिए, नया database try करने के लिए। अधिकतर मामलों में, आप **official images** का उपयोग कर सकते हैं, और उन्हें सिर्फ environment variables से configure कर सकते हैं। + +इस तरह, कई मामलों में आप containers और Docker के बारे में सीख सकते हैं और उस knowledge को कई अलग-अलग tools और components के साथ reuse कर सकते हैं। + +तो, आप अलग-अलग चीज़ों के साथ **multiple containers** चलाएँगे, जैसे database, Python application, React frontend application वाला web server, और उन्हें उनके internal network के माध्यम से connect करेंगे। + +सभी container management systems (जैसे Docker या Kubernetes) में ये networking features integrated होते हैं। + +## Containers और Processes { #containers-and-processes } + +एक **container image** सामान्यतः अपने metadata में default program या command शामिल करती है जिसे **container** start होने पर run किया जाना चाहिए, और उस program को pass किए जाने वाले parameters। यह बहुत हद तक वैसा ही है जैसा command line में होता। + +जब कोई **container** start होता है, तो वह उस command/program को run करेगा (हालाँकि आप इसे override करके कोई अलग command/program run करवा सकते हैं)। + +Container तब तक running रहता है जब तक **main process** (command या program) running रहता है। + +Container में सामान्यतः **single process** होता है, लेकिन main process से subprocesses start करना भी संभव है, और इस तरह उसी container में **multiple processes** हो सकते हैं। + +लेकिन **कम से कम एक running process** के बिना running container होना संभव नहीं है। यदि main process stop हो जाता है, तो container stop हो जाता है। + +## FastAPI के लिए Docker Image बनाएँ { #build-a-docker-image-for-fastapi } + +ठीक है, अब कुछ बनाते हैं! 🚀 + +मैं आपको दिखाऊँगा कि **official Python** image पर आधारित FastAPI के लिए **scratch से** **Docker image** कैसे बनाएँ। + +यह वही है जो आप **अधिकतर मामलों** में करना चाहेंगे, उदाहरण के लिए: + +* **Kubernetes** या समान tools का उपयोग करते समय +* **Raspberry Pi** पर चलाते समय +* ऐसा cloud service उपयोग करते समय जो आपके लिए container image run करेगा, आदि। + +### Package Requirements { #package-requirements } + +आपकी application के लिए **package requirements** सामान्यतः किसी file में होंगे। + +यह मुख्य रूप से उस tool पर निर्भर करेगा जिसका उपयोग आप उन requirements को **install** करने के लिए करते हैं। + +इसे करने का सबसे आम तरीका है `requirements.txt` file रखना, जिसमें package names और उनके versions हों, प्रति line एक। + +आप versions की ranges set करने के लिए निश्चित रूप से वही ideas उपयोग करेंगे जो आपने [FastAPI versions के बारे में](versions.md) में पढ़े हैं। + +उदाहरण के लिए, आपका `requirements.txt` ऐसा दिख सकता है: + +``` +fastapi[standard]>=0.113.0,<0.114.0 +pydantic>=2.7.0,<3.0.0 +``` + +और आप सामान्यतः उन package dependencies को `pip` से install करेंगे, उदाहरण के लिए: + +
+ +```console +$ pip install -r requirements.txt +---> 100% +Successfully installed fastapi pydantic +``` + +
+ +/// note | नोट + +Package dependencies define और install करने के लिए अन्य formats और tools भी हैं। + +/// + +### **FastAPI** Code बनाएँ { #create-the-fastapi-code } + +* एक `app` directory बनाएँ और उसमें enter करें। +* एक खाली file `__init__.py` बनाएँ। +* एक `main.py` file बनाएँ जिसमें हो: + +```Python +from fastapi import FastAPI + +app = FastAPI() + + +@app.get("/") +def read_root(): + return {"Hello": "World"} + + +@app.get("/items/{item_id}") +def read_item(item_id: int, q: str | None = None): + return {"item_id": item_id, "q": q} +``` + +### Dockerfile { #dockerfile } + +अब उसी project directory में एक file `Dockerfile` बनाएँ जिसमें हो: + +```{ .dockerfile .annotate } +# (1)! +FROM python:3.14 + +# (2)! +WORKDIR /code + +# (3)! +COPY ./requirements.txt /code/requirements.txt + +# (4)! +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +# (5)! +COPY ./app /code/app + +# (6)! +CMD ["fastapi", "run", "app/main.py", "--port", "80"] +``` + +1. Official Python base image से start करें। + +2. Current working directory को `/code` पर set करें। + + यही वह जगह है जहाँ हम `requirements.txt` file और `app` directory रखेंगे। + +3. Requirements वाली file को `/code` directory में copy करें। + + पहले **केवल** requirements वाली file copy करें, बाकी code नहीं। + + क्योंकि यह file **अक्सर change नहीं होती**, Docker इसे detect करेगा और इस step के लिए **cache** का उपयोग करेगा, जिससे अगले step के लिए भी cache enable हो जाएगा। + +4. Requirements file में package dependencies install करें। + + `--no-cache-dir` option `pip` को बताता है कि downloaded packages को locally save न करे, क्योंकि यह केवल तब उपयोगी होता जब `pip` को उन्हीं packages को install करने के लिए फिर से run किया जाना हो, लेकिन containers के साथ काम करते समय ऐसा मामला नहीं है। + + /// note | नोट + + `--no-cache-dir` केवल `pip` से संबंधित है, इसका Docker या containers से कोई संबंध नहीं है। + + /// + + `--upgrade` option `pip` को बताता है कि यदि packages पहले से installed हैं तो उन्हें upgrade करे। + + क्योंकि पिछला step जिसमें file copy की गई थी **Docker cache** द्वारा detect किया जा सकता है, इसलिए यह step भी available होने पर **Docker cache का उपयोग** करेगा। + + इस step में cache का उपयोग development के दौरान image बार-बार build करते समय आपका बहुत **समय** **बचाएगा**, हर बार सभी dependencies को **download और install** करने के बजाय। + +5. `./app` directory को `/code` directory के अंदर copy करें। + + क्योंकि इसमें सारा code है, और यही वह चीज़ है जो **सबसे अधिक बार change होती** है, Docker **cache** इस या किसी भी **आगे के steps** के लिए आसानी से उपयोग नहीं होगा। + + इसलिए, container image build times optimize करने के लिए इसे `Dockerfile` के **end के पास** रखना महत्वपूर्ण है। + +6. **command** set करें ताकि `fastapi run` उपयोग हो, जो अंदर से Uvicorn का उपयोग करता है। + + `CMD` strings की list लेता है, इन strings में से प्रत्येक वही है जिसे आप command line में spaces से अलग करके type करेंगे। + + यह command **current working directory** से run होगा, वही `/code` directory जिसे आपने ऊपर `WORKDIR /code` से set किया है। + +/// tip | टिप + +Code में प्रत्येक number bubble पर click करके review करें कि हर line क्या करती है। 👆 + +/// + +/// warning | चेतावनी + +नीचे समझाए अनुसार, `CMD` instruction का **exec form** **हमेशा** use करना सुनिश्चित करें। + +/// + +#### `CMD` उपयोग करें - Exec Form { #use-cmd-exec-form } + +[`CMD`](https://docs.docker.com/reference/dockerfile/#cmd) Docker instruction दो forms में लिखा जा सकता है: + +✅ **Exec** form: + +```Dockerfile +# ✅ यह करें +CMD ["fastapi", "run", "app/main.py", "--port", "80"] +``` + +⛔️ **Shell** form: + +```Dockerfile +# ⛔️ यह न करें +CMD fastapi run app/main.py --port 80 +``` + +यह सुनिश्चित करने के लिए कि FastAPI gracefully shutdown कर सके और [lifespan events](../advanced/events.md) trigger हों, हमेशा **exec** form use करें। + +आप इसके बारे में [shell और exec form के लिए Docker docs](https://docs.docker.com/reference/dockerfile/#shell-and-exec-form) में और पढ़ सकते हैं। + +`docker compose` का उपयोग करते समय यह काफी noticeable हो सकता है। अधिक technical details के लिए यह Docker Compose FAQ section देखें: [मेरी services को recreate या stop होने में 10 seconds क्यों लगते हैं?](https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop). + +#### Directory Structure { #directory-structure } + +अब आपके पास ऐसी directory structure होनी चाहिए: + +``` +. +├── app +│   ├── __init__.py +│ └── main.py +├── Dockerfile +└── requirements.txt +``` + +#### TLS Termination Proxy के पीछे { #behind-a-tls-termination-proxy } + +यदि आप अपना container Nginx या Traefik जैसे TLS Termination Proxy (load balancer) के पीछे चला रहे हैं, तो option `--proxy-headers` जोड़ें, यह Uvicorn (FastAPI CLI के माध्यम से) को बताएगा कि उस proxy द्वारा भेजे गए headers पर trust करे, जो उसे बताता है कि application HTTPS के पीछे चल रही है, आदि। + +```Dockerfile +CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"] +``` + +#### Docker Cache { #docker-cache } + +इस `Dockerfile` में एक महत्वपूर्ण trick है, हम पहले **केवल dependencies वाली file** copy करते हैं, बाकी code नहीं। मैं आपको बताता हूँ क्यों। + +```Dockerfile +COPY ./requirements.txt /code/requirements.txt +``` + +Docker और अन्य tools इन container images को **incrementally build** करते हैं, **एक layer के ऊपर दूसरी layer** जोड़ते हुए, `Dockerfile` के top से शुरू करके और `Dockerfile` के प्रत्येक instruction द्वारा बनाई गई कोई भी files जोड़ते हुए। + +Docker और समान tools image build करते समय **internal cache** भी use करते हैं, यदि कोई file पिछली बार container image build करने के बाद से change नहीं हुई है, तो वह file को फिर से copy करने और scratch से नई layer बनाने के बजाय पिछली बार बनाई गई **उसी layer को reuse** करेगा। + +सिर्फ files copy करने से बचना जरूरी नहीं कि चीज़ों को बहुत बेहतर कर दे, लेकिन क्योंकि उसने उस step के लिए cache use किया, वह **अगले step के लिए cache use** कर सकता है। उदाहरण के लिए, वह उस instruction के लिए cache use कर सकता है जो dependencies install करता है: + +```Dockerfile +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt +``` + +Package requirements वाली file **अक्सर change नहीं होगी**। इसलिए, केवल उस file को copy करके, Docker उस step के लिए **cache use** कर पाएगा। + +और फिर, Docker उन dependencies को download और install करने वाले **अगले step के लिए cache use** कर पाएगा। और यहीं हम **बहुत समय बचाते हैं**। ✨ ...और इंतज़ार की बोरियत से बचते हैं। 😪😆 + +Package dependencies को download और install करने में **minutes लग सकते हैं**, लेकिन **cache** का उपयोग करने में अधिकतम **seconds** लगेंगे। + +और क्योंकि development के दौरान आप अपने code changes काम कर रहे हैं या नहीं यह check करने के लिए container image बार-बार build करेंगे, इससे बहुत सारा जमा हुआ समय बचेगा। + +फिर, `Dockerfile` के end के पास, हम सारा code copy करते हैं। क्योंकि यही वह चीज़ है जो **सबसे अधिक बार change होती** है, हम इसे end के पास रखते हैं, क्योंकि लगभग हमेशा इस step के बाद कुछ भी cache use नहीं कर पाएगा। + +```Dockerfile +COPY ./app /code/app +``` + +### Docker Image Build करें { #build-the-docker-image } + +अब जब सभी files अपनी जगह पर हैं, चलिए container image build करते हैं। + +* Project directory में जाएँ (जहाँ आपका `Dockerfile` है, जिसमें आपकी `app` directory है)। +* अपनी FastAPI image build करें: + +
+ +```console +$ docker build -t myimage . + +---> 100% +``` + +
+ +/// tip | टिप + +अंत में `.` पर ध्यान दें, यह `./` के equivalent है, यह Docker को container image build करने के लिए use की जाने वाली directory बताता है। + +इस मामले में, यह वही current directory (`.`) है। + +/// + +### Docker Container Start करें { #start-the-docker-container } + +* अपनी image पर आधारित container run करें: + +
+ +```console +$ docker run -d --name mycontainer -p 80:80 myimage +``` + +
+ +## इसे Check करें { #check-it } + +आप इसे अपने Docker container के URL में check कर पाएँगे, उदाहरण के लिए: [http://192.168.99.100/items/5?q=somequery](http://192.168.99.100/items/5?q=somequery) या [http://127.0.0.1/items/5?q=somequery](http://127.0.0.1/items/5?q=somequery) (या equivalent, अपने Docker host का उपयोग करके)। + +आपको कुछ ऐसा दिखेगा: + +```JSON +{"item_id": 5, "q": "somequery"} +``` + +## Interactive API docs { #interactive-api-docs } + +अब आप [http://192.168.99.100/docs](http://192.168.99.100/docs) या [http://127.0.0.1/docs](http://127.0.0.1/docs) (या equivalent, अपने Docker host का उपयोग करके) पर जा सकते हैं। + +आप automatic interactive API documentation देखेंगे ([Swagger UI](https://github.com/swagger-api/swagger-ui) द्वारा provided): + +![Swagger UI](https://fastapi.tiangolo.com/img/index/index-01-swagger-ui-simple.png) + +## Alternative API docs { #alternative-api-docs } + +और आप [http://192.168.99.100/redoc](http://192.168.99.100/redoc) या [http://127.0.0.1/redoc](http://127.0.0.1/redoc) (या equivalent, अपने Docker host का उपयोग करके) पर भी जा सकते हैं। + +आप alternative automatic documentation देखेंगे ([ReDoc](https://github.com/Rebilly/ReDoc) द्वारा provided): + +![ReDoc](https://fastapi.tiangolo.com/img/index/index-02-redoc-simple.png) + +## Single-File FastAPI के साथ Docker Image बनाएँ { #build-a-docker-image-with-a-single-file-fastapi } + +यदि आपकी FastAPI एक single file है, उदाहरण के लिए, `./app` directory के बिना `main.py`, तो आपकी file structure ऐसी दिख सकती है: + +``` +. +├── Dockerfile +├── main.py +└── requirements.txt +``` + +फिर आपको बस `Dockerfile` के अंदर file copy करने के लिए संबंधित paths बदलने होंगे: + +```{ .dockerfile .annotate hl_lines="10 13" } +FROM python:3.14 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +# (1)! +COPY ./main.py /code/ + +# (2)! +CMD ["fastapi", "run", "main.py", "--port", "80"] +``` + +1. `main.py` file को सीधे `/code` directory में copy करें (बिना किसी `./app` directory के)। + +2. Single file `main.py` में अपनी application serve करने के लिए `fastapi run` use करें। + +जब आप file को `fastapi run` में pass करते हैं, तो यह automatically detect करेगा कि यह single file है और किसी package का हिस्सा नहीं है, और यह जान जाएगा कि इसे कैसे import करना है और आपकी FastAPI app को serve करना है। 😎 + +## Deployment Concepts { #deployment-concepts } + +आइए containers के संदर्भ में फिर से उन्हीं कुछ [Deployment Concepts](concepts.md) के बारे में बात करें। + +Containers मुख्य रूप से application को **build और deploy** करने की process को सरल बनाने का tool हैं, लेकिन वे इन **deployment concepts** को handle करने के लिए कोई particular approach enforce नहीं करते, और कई संभावित strategies हैं। + +**अच्छी खबर** यह है कि हर अलग strategy के साथ सभी deployment concepts को cover करने का एक तरीका है। 🎉 + +आइए इन **deployment concepts** को containers के संदर्भ में review करें: + +* HTTPS +* startup पर Running +* Restarts +* Replication (running processes की संख्या) +* Memory +* Start करने से पहले previous steps + +## HTTPS { #https } + +यदि हम FastAPI application के लिए सिर्फ **container image** (और बाद में running **container**) पर focus करें, तो HTTPS सामान्यतः किसी अन्य tool द्वारा **externally** handle किया जाएगा। + +यह कोई दूसरा container हो सकता है, उदाहरण के लिए [Traefik](https://traefik.io/) के साथ, जो **HTTPS** और **certificates** की **automatic** acquisition handle करता है। + +/// tip | टिप + +Traefik के Docker, Kubernetes, और अन्य के साथ integrations हैं, इसलिए इसके साथ अपने containers के लिए HTTPS set up और configure करना बहुत आसान है। + +/// + +वैकल्पिक रूप से, HTTPS को किसी cloud provider द्वारा उनकी services में से एक के रूप में handle किया जा सकता है (application अभी भी container में चल रही हो)। + +## Startup पर Running और Restarts { #running-on-startup-and-restarts } + +सामान्यतः कोई दूसरा tool आपके container को **start और run** करने के लिए charge में होता है। + +यह सीधे **Docker**, **Docker Compose**, **Kubernetes**, कोई **cloud service**, आदि हो सकता है। + +अधिकतर (या सभी) मामलों में, startup पर container run करने और failures पर restarts enable करने के लिए एक simple option होता है। उदाहरण के लिए, Docker में यह command line option `--restart` है। + +Containers का उपयोग किए बिना, applications को startup पर और restarts के साथ run कराना cumbersome और difficult हो सकता है। लेकिन **containers के साथ काम करते समय** अधिकतर मामलों में यह functionality default रूप से शामिल होती है। ✨ + +## Replication - Processes की संख्या { #replication-number-of-processes } + +यदि आपके पास machines का cluster है जिसमें **Kubernetes**, Docker Swarm Mode, Nomad, या multiple machines पर distributed containers manage करने के लिए कोई अन्य similar complex system है, तो आप शायद प्रत्येक container में **process manager** (जैसे workers के साथ Uvicorn) उपयोग करने के बजाय **cluster level** पर **replication handle** करना चाहेंगे। + +Kubernetes जैसे distributed container management systems में incoming requests के लिए **load balancing** support करते हुए **containers की replication** handle करने का कोई integrated तरीका सामान्यतः होता है। सब **cluster level** पर। + +उन मामलों में, आप शायद ऊपर [समझाए अनुसार](#dockerfile) **scratch से Docker image** build करना चाहेंगे, अपनी dependencies install करके, और multiple Uvicorn workers उपयोग करने के बजाय **single Uvicorn process** run करना चाहेंगे। + +### Load Balancer { #load-balancer } + +Containers का उपयोग करते समय, आपके पास सामान्यतः कोई component होगा जो **main port पर listening** कर रहा होगा। संभवतः यह कोई दूसरा container हो सकता है जो **HTTPS** handle करने के लिए **TLS Termination Proxy** भी हो, या कोई similar tool। + +क्योंकि यह component requests का **load** लेगा और उसे workers में (उम्मीद है) **balanced** तरीके से distribute करेगा, इसे सामान्यतः **Load Balancer** भी कहा जाता है। + +/// tip | टिप + +HTTPS के लिए उपयोग किया गया वही **TLS Termination Proxy** component शायद **Load Balancer** भी होगा। + +/// + +और containers के साथ काम करते समय, उन्हें start और manage करने के लिए आप जो system use करते हैं, उसमें उस **load balancer** (जो **TLS Termination Proxy** भी हो सकता है) से आपकी app वाले container(s) तक **network communication** (जैसे HTTP requests) transmit करने के internal tools पहले से होंगे। + +### One Load Balancer - Multiple Worker Containers { #one-load-balancer-multiple-worker-containers } + +**Kubernetes** या similar distributed container management systems के साथ काम करते समय, उनके internal networking mechanisms का उपयोग main **port** पर listening करने वाले single **load balancer** को communication (requests) आपकी app चला रहे संभवतः **multiple containers** तक transmit करने देगा। + +आपकी app चला रहे इन containers में से प्रत्येक में सामान्यतः **सिर्फ एक process** होगा (जैसे आपकी FastAPI application चलाने वाला Uvicorn process)। वे सभी **identical containers** होंगे, वही चीज़ चला रहे होंगे, लेकिन प्रत्येक का अपना process, memory, आदि होगा। इस तरह आप CPU के **different cores** में, या यहाँ तक कि **different machines** में **parallelization** का लाभ उठाएँगे। + +और **load balancer** वाला distributed container system requests को आपकी app वाले प्रत्येक container तक **बारी-बारी से distribute** करेगा। इसलिए, प्रत्येक request आपकी app चला रहे multiple **replicated containers** में से किसी एक द्वारा handle की जा सकती है। + +और सामान्यतः यह **load balancer** आपके cluster में *other* apps पर जाने वाली requests handle कर पाएगा (जैसे अलग domain पर, या अलग URL path prefix के तहत), और उस communication को आपके cluster में चल रही *उस other* application के सही containers तक transmit करेगा। + +### प्रति Container एक Process { #one-process-per-container } + +इस तरह के scenario में, आप शायद **प्रति container एक single (Uvicorn) process** रखना चाहेंगे, क्योंकि आप पहले से ही cluster level पर replication handle कर रहे होंगे। + +तो, इस मामले में, आप container में multiple workers **नहीं** रखना चाहेंगे, उदाहरण के लिए `--workers` command line option के साथ। आप प्रति container बस **single Uvicorn process** रखना चाहेंगे (लेकिन शायद multiple containers)। + +Container के अंदर एक और process manager रखना (जैसा multiple workers के साथ होगा) केवल **unnecessary complexity** जोड़ेगा, जिसे आप बहुत संभव है कि अपने cluster system के साथ पहले से संभाल रहे हैं। + +### Multiple Processes वाले Containers और Special Cases { #containers-with-multiple-processes-and-special-cases } + +बेशक, ऐसे **special cases** हैं जहाँ आप अंदर कई **Uvicorn worker processes** वाला **container** रखना चाह सकते हैं। + +उन मामलों में, आप run किए जाने वाले workers की संख्या set करने के लिए `--workers` command line option उपयोग कर सकते हैं: + +```{ .dockerfile .annotate } +FROM python:3.14 + +WORKDIR /code + +COPY ./requirements.txt /code/requirements.txt + +RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt + +COPY ./app /code/app + +# (1)! +CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] +``` + +1. यहाँ हम workers की संख्या 4 पर set करने के लिए `--workers` command line option उपयोग करते हैं। + +यहाँ कुछ examples हैं कि यह कब meaningful हो सकता है: + +#### एक Simple App { #a-simple-app } + +यदि आपकी application **इतनी simple** है कि आप इसे **single server** पर run कर सकते हैं, cluster पर नहीं, तो आप container में process manager चाह सकते हैं। + +#### Docker Compose { #docker-compose } + +आप **Docker Compose** के साथ **single server** (cluster नहीं) पर deploy कर रहे हो सकते हैं, इसलिए shared network और **load balancing** preserve करते हुए containers की replication (Docker Compose के साथ) manage करने का आसान तरीका आपके पास नहीं होगा। + +फिर आप **single container** रखना चाह सकते हैं जिसमें **process manager** अंदर **कई worker processes** start करे। + +--- + +मुख्य बात यह है कि इनमें से **कोई भी** ऐसी **पत्थर पर लिखी rules** नहीं हैं जिन्हें आपको आँख बंद करके follow करना हो। आप इन ideas का उपयोग **अपने use case का evaluate** करने और अपने system के लिए best approach तय करने के लिए कर सकते हैं, यह check करते हुए कि इन concepts को कैसे manage करना है: + +* Security - HTTPS +* startup पर Running +* Restarts +* Replication (running processes की संख्या) +* Memory +* Start करने से पहले previous steps + +## Memory { #memory } + +यदि आप **प्रति container single process** run करते हैं, तो उन containers में से प्रत्येक (यदि replicated हैं तो एक से अधिक) द्वारा consumed memory की quantity कमोबेश well-defined, stable, और limited होगी। + +और फिर आप अपने container management system (उदाहरण के लिए **Kubernetes** में) की configurations में वही memory limits और requirements set कर सकते हैं। इस तरह वह उन containers द्वारा आवश्यक memory की मात्रा, और cluster में machines में available मात्रा को ध्यान में रखते हुए **available machines** में **containers replicate** कर पाएगा। + +यदि आपकी application **simple** है, तो यह शायद **problem नहीं होगी**, और आपको hard memory limits specify करने की आवश्यकता नहीं हो सकती। लेकिन यदि आप **बहुत memory use** कर रहे हैं (उदाहरण के लिए **machine learning** models के साथ), तो आपको check करना चाहिए कि आप कितनी memory consume कर रहे हैं और **प्रत्येक machine** पर run होने वाले **containers की संख्या** adjust करनी चाहिए (और शायद अपने cluster में और machines add करनी चाहिए)। + +यदि आप **प्रति container multiple processes** run करते हैं, तो आपको सुनिश्चित करना होगा कि start किए गए processes की संख्या available memory से **अधिक memory consume** न करे। + +## Start करने से पहले Previous Steps और Containers { #previous-steps-before-starting-and-containers } + +यदि आप containers (जैसे Docker, Kubernetes) उपयोग कर रहे हैं, तो दो मुख्य approaches हैं जिनका आप उपयोग कर सकते हैं। + +### Multiple Containers { #multiple-containers } + +यदि आपके पास **multiple containers** हैं, शायद प्रत्येक **single process** run कर रहा है (उदाहरण के लिए, **Kubernetes** cluster में), तो आप replicated worker containers run करने से **पहले**, single container में, single process चलाते हुए, **previous steps** का काम करने वाला **separate container** रखना चाहेंगे। + +/// note | नोट + +यदि आप Kubernetes उपयोग कर रहे हैं, तो यह शायद [Init Container](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/) होगा। + +/// + +यदि आपके use case में उन previous steps को **parallel में multiple times** run करने में कोई problem नहीं है (उदाहरण के लिए यदि आप database migrations नहीं चला रहे, बल्कि बस check कर रहे हैं कि database अभी ready है या नहीं), तो आप उन्हें हर container में main process start करने से ठीक पहले भी रख सकते हैं। + +### Single Container { #single-container } + +यदि आपका setup simple है, जिसमें **single container** है जो फिर multiple **worker processes** start करता है (या सिर्फ एक process), तो आप app के साथ process start करने से ठीक पहले, उन previous steps को उसी container में run कर सकते हैं। + +### Base Docker Image { #base-docker-image } + +एक official FastAPI Docker image हुआ करती थी: [tiangolo/uvicorn-gunicorn-fastapi](https://github.com/tiangolo/uvicorn-gunicorn-fastapi-docker)। लेकिन अब यह deprecated है। ⛔️ + +आपको शायद इस base Docker image (या किसी अन्य similar one) का उपयोग **नहीं** करना चाहिए। + +यदि आप **Kubernetes** (या अन्य) उपयोग कर रहे हैं और पहले से ही cluster level पर, multiple **containers** के साथ **replication** set कर रहे हैं। उन मामलों में, ऊपर बताए अनुसार **scratch से image build** करना बेहतर है: [FastAPI के लिए Docker Image बनाएँ](#build-a-docker-image-for-fastapi). + +और यदि आपको multiple workers की आवश्यकता है, तो आप बस `--workers` command line option उपयोग कर सकते हैं। + +/// note | Technical Details + +Docker image तब बनाई गई थी जब Uvicorn dead workers को manage और restart करने का support नहीं करता था, इसलिए Uvicorn के साथ Gunicorn का उपयोग करना required था, जिससे काफी complexity जुड़ती थी, सिर्फ इसलिए कि Gunicorn Uvicorn worker processes को manage और restart कर सके। + +लेकिन अब जब Uvicorn (और `fastapi` command) `--workers` use करने का support करते हैं, तो अपनी खुद की build करने के बजाय base Docker image उपयोग करने का कोई कारण नहीं है (यह लगभग उतनी ही code की मात्रा है 😅). + +/// + +## Container Image Deploy करें { #deploy-the-container-image } + +Container (Docker) Image होने के बाद इसे deploy करने के कई तरीके हैं। + +उदाहरण के लिए: + +* Single server में **Docker Compose** के साथ +* **Kubernetes** cluster के साथ +* Docker Swarm Mode cluster के साथ +* Nomad जैसे किसी अन्य tool के साथ +* किसी cloud service के साथ जो आपकी container image लेता है और उसे deploy करता है + +## `uv` के साथ Docker Image { #docker-image-with-uv } + +यदि आप अपने project को install और manage करने के लिए [uv](https://github.com/astral-sh/uv) उपयोग कर रहे हैं, तो आप उनकी [uv Docker guide](https://docs.astral.sh/uv/guides/integration/docker/) follow कर सकते हैं। + +## Recap { #recap } + +Container systems (जैसे **Docker** और **Kubernetes** के साथ) का उपयोग करने पर सभी **deployment concepts** handle करना काफी straightforward हो जाता है: + +* HTTPS +* startup पर Running +* Restarts +* Replication (running processes की संख्या) +* Memory +* Start करने से पहले previous steps + +अधिकतर मामलों में, आप शायद कोई base image use नहीं करना चाहेंगे, और इसके बजाय official Python Docker image पर आधारित **scratch से container image build** करेंगे। + +`Dockerfile` में instructions के **order** और **Docker cache** का ध्यान रखकर आप **build times minimize** कर सकते हैं, ताकि आपकी productivity maximize हो (और बोरियत से बचें)। 😎 diff --git a/docs/hi/docs/deployment/fastapicloud.md b/docs/hi/docs/deployment/fastapicloud.md new file mode 100644 index 000000000..06a2a2d3c --- /dev/null +++ b/docs/hi/docs/deployment/fastapicloud.md @@ -0,0 +1,47 @@ +# FastAPI Cloud { #fastapi-cloud } + +आप अपनी FastAPI app को सिर्फ **एक command** से [FastAPI Cloud](https://fastapicloud.com) पर deploy कर सकते हैं। 🚀 + +
+ +```console +$ fastapi deploy + +Deploying to FastAPI Cloud... + +✅ Deployment successful! + +🐔 Ready the chicken! Your app is ready at https://myapp.fastapicloud.dev +``` + +
+ +CLI अपने-आप आपकी FastAPI application का पता लगा लेगा और उसे cloud पर deploy कर देगा। अगर आप logged in नहीं हैं, तो authentication प्रक्रिया पूरी करने के लिए आपका browser खुलेगा। + +बस इतना ही! अब आप उस URL पर अपनी app access कर सकते हैं। ✨ + +## FastAPI Cloud के बारे में { #about-fastapi-cloud } + +**[FastAPI Cloud](https://fastapicloud.com)** उसी author और team द्वारा बनाया गया है जो **FastAPI** के पीछे हैं। + +यह कम से कम प्रयास में API को **build** करने, **deploy** करने, और **access** करने की प्रक्रिया को सरल बनाता है। + +यह FastAPI के साथ apps बनाने वाले उसी **developer experience** को उन्हें cloud पर **deploy** करने में भी लाता है। 🎉 + +यह app deploy करते समय ज़रूरी अधिकांश चीज़ों का भी ध्यान रखेगा, जैसे: + +* HTTPS +* Replication, requests के आधार पर autoscaling के साथ +* आदि। + +FastAPI Cloud, *FastAPI and friends* open source projects का मुख्य sponsor और funding provider है। ✨ + +## दूसरे cloud providers पर deploy करें { #deploy-to-other-cloud-providers } + +FastAPI open source है और standards पर आधारित है। आप FastAPI apps को अपने चुने हुए किसी भी cloud provider पर deploy कर सकते हैं। + +उनके साथ FastAPI apps deploy करने के लिए अपने cloud provider की guides follow करें। 🤓 + +## अपने खुद के server पर deploy करें { #deploy-your-own-server } + +मैं आपको इस **Deployment** guide में आगे सभी details भी सिखाऊँगा, ताकि आप समझ सकें कि क्या हो रहा है, क्या होना चाहिए, या FastAPI apps को अपने-आप, अपने खुद के servers के साथ भी कैसे deploy करना है। 🤓 diff --git a/docs/hi/docs/deployment/https.md b/docs/hi/docs/deployment/https.md new file mode 100644 index 000000000..834712835 --- /dev/null +++ b/docs/hi/docs/deployment/https.md @@ -0,0 +1,231 @@ +# HTTPS के बारे में { #about-https } + +यह मान लेना आसान है कि HTTPS कोई ऐसी चीज़ है जिसे बस "enabled" किया जाता है या नहीं। + +लेकिन यह उससे कहीं ज़्यादा जटिल है। + +/// tip | सुझाव + +अगर आप जल्दी में हैं या आपको परवाह नहीं है, तो अलग-अलग तकनीकों के साथ सब कुछ setup करने के लिए step by step निर्देशों हेतु अगले sections पर जाएँ। + +/// + +**HTTPS की मूल बातें सीखने** के लिए, एक उपभोक्ता के दृष्टिकोण से, देखें [https://howhttps.works/](https://howhttps.works/)। + +अब, एक **developer के दृष्टिकोण** से, HTTPS के बारे में सोचते समय ध्यान रखने योग्य कई बातें यहाँ हैं: + +* HTTPS के लिए, **server** के पास **तीसरे पक्ष** द्वारा बनाए गए "certificates" होने चाहिए। + * वे certificates वास्तव में तीसरे पक्ष से **प्राप्त** किए जाते हैं, "generated" नहीं। +* Certificates की एक **lifespan** होती है। + * वे **expire** हो जाते हैं। + * और फिर उन्हें **renew** करना पड़ता है, तीसरे पक्ष से **फिर से प्राप्त** करना पड़ता है। +* connection का encryption **TCP level** पर होता है। + * यह **HTTP से एक layer नीचे** है। + * इसलिए, **certificate और encryption** handling **HTTP से पहले** की जाती है। +* **TCP को "domains" के बारे में पता नहीं होता**। केवल IP addresses के बारे में। + * जिस **विशिष्ट domain** का request किया गया है, उसकी जानकारी **HTTP data** में जाती है। +* **HTTPS certificates** किसी **विशिष्ट domain** को "certify" करते हैं, लेकिन protocol और encryption TCP level पर होते हैं, इस domain को जानने से **पहले** कि किस domain से निपटा जा रहा है। +* **By default**, इसका मतलब होगा कि आपके पास **प्रति IP address केवल एक HTTPS certificate** हो सकता है। + * इससे कोई फर्क नहीं पड़ता कि आपका server कितना बड़ा है या उस पर मौजूद हर application कितनी छोटी हो सकती है। + * हालांकि, इसका एक **समाधान** है। +* **TLS** protocol (जो HTTP से पहले, TCP level पर encryption संभालता है) के लिए एक **extension** है जिसे **[SNI](https://en.wikipedia.org/wiki/Server_Name_Indication)** कहा जाता है। + * यह SNI extension एक ही server (एक **single IP address** के साथ) को **कई HTTPS certificates** रखने और **कई HTTPS domains/applications** serve करने की अनुमति देता है। + * इसे काम करने के लिए, server पर चल रहे, **public IP address** पर listen कर रहे, एक **single** component (program) के पास server में **सभी HTTPS certificates** होने चाहिए। +* सुरक्षित connection प्राप्त करने के **बाद**, communication protocol **अभी भी HTTP** रहता है। + * contents **encrypted** होते हैं, भले ही उन्हें **HTTP protocol** के साथ भेजा जा रहा हो। + +Server (machine, host, आदि) पर **एक program/HTTP server** चलाना और **HTTPS के सभी हिस्सों को manage** करना एक सामान्य practice है: **encrypted HTTPS requests** प्राप्त करना, उसी server में चल रही वास्तविक HTTP application (इस मामले में **FastAPI** application) को **decrypted HTTP requests** भेजना, application से **HTTP response** लेना, उपयुक्त **HTTPS certificate** का उपयोग करके उसे **encrypt** करना और **HTTPS** का उपयोग करके client को वापस भेजना। इस server को अक्सर **[TLS Termination Proxy](https://en.wikipedia.org/wiki/TLS_termination_proxy)** कहा जाता है। + +TLS Termination Proxy के रूप में आप जिन options का उपयोग कर सकते हैं, उनमें से कुछ हैं: + +* Traefik (जो certificate renewals भी handle कर सकता है) +* Caddy (जो certificate renewals भी handle कर सकता है) +* Nginx +* HAProxy + +## Let's Encrypt { #lets-encrypt } + +Let's Encrypt से पहले, ये **HTTPS certificates** trusted तीसरे पक्षों द्वारा बेचे जाते थे। + +इनमें से किसी certificate को प्राप्त करने की प्रक्रिया कठिन होती थी, काफी paperwork की जरूरत होती थी और certificates काफी महंगे होते थे। + +लेकिन फिर **[Let's Encrypt](https://letsencrypt.org/)** बनाया गया। + +यह Linux Foundation का एक project है। यह automated तरीके से **मुफ्त में HTTPS certificates** प्रदान करता है। ये certificates सभी standard cryptographic security का उपयोग करते हैं, और short-lived होते हैं (लगभग 3 महीने), इसलिए उनकी कम lifespan के कारण **security वास्तव में बेहतर** होती है। + +Domains को सुरक्षित रूप से verify किया जाता है और certificates automatically generate किए जाते हैं। इससे इन certificates के renewal को automate करना भी संभव होता है। + +विचार यह है कि इन certificates की acquisition और renewal को automate किया जाए ताकि आपके पास **secure HTTPS, मुफ्त में, हमेशा के लिए** हो सके। + +## Developers के लिए HTTPS { #https-for-developers } + +यहाँ step by step एक उदाहरण है कि HTTPS API कैसी दिख सकती है, मुख्य रूप से developers के लिए महत्वपूर्ण विचारों पर ध्यान देते हुए। + +### Domain Name { #domain-name } + +सब कुछ शायद आपके द्वारा कोई **domain name** **प्राप्त** करने से शुरू होगा। फिर, आप इसे DNS server में configure करेंगे (संभवतः आपके उसी cloud provider में)। + +आप शायद एक cloud server (एक virtual machine) या कुछ समान प्राप्त करेंगे, और उसके पास एक स्थिर **public IP address** होगा। + +DNS server(s) में आप एक record (एक "`A record`") configure करेंगे ताकि **आपका domain** आपके server के public **IP address** की ओर point करे। + +आप शायद यह सिर्फ एक बार करेंगे, पहली बार, जब सब कुछ setup कर रहे होंगे। + +/// tip | सुझाव + +यह Domain Name वाला हिस्सा HTTPS से बहुत पहले का है, लेकिन चूँकि सब कुछ domain और IP address पर निर्भर करता है, इसलिए इसे यहाँ mention करना उचित है। + +/// + +### DNS { #dns } + +अब आइए वास्तविक HTTPS parts पर focus करें। + +सबसे पहले, browser **DNS servers** से check करेगा कि **domain के लिए IP** क्या है, इस मामले में, `someapp.example.com`। + +DNS servers browser को किसी विशिष्ट **IP address** का उपयोग करने के लिए कहेंगे। यह आपके server द्वारा उपयोग किया जाने वाला public IP address होगा, जिसे आपने DNS servers में configure किया है। + + + +### TLS Handshake Start { #tls-handshake-start } + +Browser फिर उस IP address से **port 443** (HTTPS port) पर communicate करेगा। + +Communication का पहला हिस्सा केवल client और server के बीच connection establish करना और वे कौन-सी cryptographic keys उपयोग करेंगे आदि तय करना है। + + + +TLS connection establish करने के लिए client और server के बीच इस interaction को **TLS handshake** कहा जाता है। + +### SNI Extension के साथ TLS { #tls-with-sni-extension } + +Server में **केवल एक process** किसी विशिष्ट **IP address** में किसी विशिष्ट **port** पर listen कर सकता है। उसी IP address में दूसरे ports पर अन्य processes listen कर सकते हैं, लेकिन IP address और port के हर combination के लिए केवल एक। + +TLS (HTTPS) by default विशिष्ट port `443` का उपयोग करता है। इसलिए हमें इसी port की जरूरत होगी। + +क्योंकि इस port पर केवल एक process listen कर सकता है, जो process यह करेगा वह **TLS Termination Proxy** होगा। + +TLS Termination Proxy के पास एक या अधिक **TLS certificates** (HTTPS certificates) तक access होगा। + +ऊपर चर्चा किए गए **SNI extension** का उपयोग करके, TLS Termination Proxy check करेगा कि इस connection के लिए उपलब्ध TLS (HTTPS) certificates में से किसका उपयोग करना चाहिए, client द्वारा expected domain से match करने वाले certificate का उपयोग करते हुए। + +इस मामले में, यह `someapp.example.com` के लिए certificate का उपयोग करेगा। + + + +Client पहले से ही उस entity पर **trust** करता है जिसने वह TLS certificate generate किया है (इस मामले में Let's Encrypt, लेकिन हम इसके बारे में बाद में देखेंगे), इसलिए यह **verify** कर सकता है कि certificate valid है। + +फिर, certificate का उपयोग करके, client और TLS Termination Proxy **तय करते हैं कि बाकी TCP communication को कैसे encrypt करना है**। इससे **TLS Handshake** वाला हिस्सा पूरा होता है। + +इसके बाद, client और server के पास एक **encrypted TCP connection** होता है, यही TLS प्रदान करता है। और फिर वे उस connection का उपयोग वास्तविक **HTTP communication** शुरू करने के लिए कर सकते हैं। + +और **HTTPS** यही है, यह pure (unencrypted) TCP connection के बजाय एक **secure TLS connection** के अंदर साधारण **HTTP** ही है। + +/// tip | सुझाव + +ध्यान दें कि communication का encryption **TCP level** पर होता है, HTTP level पर नहीं। + +/// + +### HTTPS Request { #https-request } + +अब जबकि client और server (विशेष रूप से browser और TLS Termination Proxy) के पास एक **encrypted TCP connection** है, वे **HTTP communication** शुरू कर सकते हैं। + +तो, client एक **HTTPS request** भेजता है। यह encrypted TLS connection के माध्यम से बस एक HTTP request है। + + + +### Request को Decrypt करें { #decrypt-the-request } + +TLS Termination Proxy सहमत किए गए encryption का उपयोग **request को decrypt** करने के लिए करेगा, और **साधारण (decrypted) HTTP request** को application चलाने वाले process तक transmit करेगा (उदाहरण के लिए FastAPI application चलाने वाले Uvicorn के साथ एक process)। + + + +### HTTP Response { #http-response } + +Application request को process करेगी और TLS Termination Proxy को एक **साधारण (unencrypted) HTTP response** भेजेगी। + + + +### HTTPS Response { #https-response } + +TLS Termination Proxy फिर पहले सहमत cryptography (जो `someapp.example.com` के लिए certificate से शुरू हुई थी) का उपयोग करके **response को encrypt** करेगा, और इसे browser को वापस भेजेगा। + +इसके बाद, browser verify करेगा कि response valid है और सही cryptographic key आदि से encrypted है। फिर वह **response को decrypt** करेगा और process करेगा। + + + +Client (browser) को पता होगा कि response सही server से आया है क्योंकि यह उस cryptography का उपयोग कर रहा है जिस पर उन्होंने पहले **HTTPS certificate** का उपयोग करके सहमति की थी। + +### Multiple Applications { #multiple-applications } + +उसी server (या servers) में, **multiple applications** हो सकती हैं, उदाहरण के लिए, अन्य API programs या database। + +केवल एक process विशिष्ट IP और port handle कर सकता है (हमारे उदाहरण में TLS Termination Proxy) लेकिन अन्य applications/processes भी server(s) पर चल सकते हैं, जब तक वे **public IP और port के उसी combination** का उपयोग करने की कोशिश नहीं करते। + + + +इस तरह, TLS Termination Proxy **multiple domains** के लिए, multiple applications के लिए HTTPS और certificates handle कर सकता है, और फिर हर मामले में requests को सही application तक transmit कर सकता है। + +### Certificate Renewal { #certificate-renewal } + +भविष्य में किसी समय, प्रत्येक certificate **expire** हो जाएगा (इसे प्राप्त करने के लगभग 3 महीने बाद)। + +और फिर, कोई दूसरा program होगा (कुछ मामलों में यह दूसरा program होता है, कुछ मामलों में यह वही TLS Termination Proxy हो सकता है) जो Let's Encrypt से बात करेगा, और certificate(s) को renew करेगा। + + + +**TLS certificates** किसी **domain name** से **associated** होते हैं, IP address से नहीं। + +इसलिए, certificates renew करने के लिए, renewal program को authority (Let's Encrypt) को **prove** करना होगा कि वह वास्तव में उस domain को **"own" और control** करता है। + +ऐसा करने के लिए, और अलग-अलग application needs को accommodate करने के लिए, इसे करने के कई तरीके हैं। कुछ लोकप्रिय तरीके हैं: + +* **कुछ DNS records modify करें**। + * इसके लिए, renewal program को DNS provider की APIs support करनी होंगी, इसलिए, आप जिस DNS provider का उपयोग कर रहे हैं, उसके आधार पर यह option हो भी सकता है या नहीं भी। +* Domain से associated public IP address पर (कम से कम certificate acquisition process के दौरान) **server के रूप में चलें**। + * जैसा कि हमने ऊपर कहा, केवल एक process किसी विशिष्ट IP और port पर listen कर सकता है। + * यह उन कारणों में से एक है कि जब वही TLS Termination Proxy certificate renewal process का भी ध्यान रखता है तो यह बहुत उपयोगी होता है। + * अन्यथा, आपको TLS Termination Proxy को momentarily stop करना पड़ सकता है, certificates प्राप्त करने के लिए renewal program start करना पड़ सकता है, फिर उन्हें TLS Termination Proxy के साथ configure करना पड़ सकता है, और फिर TLS Termination Proxy को restart करना पड़ सकता है। यह ideal नहीं है, क्योंकि जिस समय TLS Termination Proxy off होगा, उस दौरान आपकी app(s) available नहीं होंगी। + +App को serve करते हुए भी यह पूरा renewal process, उन मुख्य कारणों में से एक है कि आप application server के साथ सीधे TLS certificates (जैसे Uvicorn) का उपयोग करने के बजाय TLS Termination Proxy के साथ **HTTPS handle करने के लिए एक अलग system** रखना चाहेंगे। + +## Proxy Forwarded Headers { #proxy-forwarded-headers } + +HTTPS handle करने के लिए proxy का उपयोग करते समय, आपका **application server** (उदाहरण के लिए FastAPI CLI के माध्यम से Uvicorn) HTTPS process के बारे में कुछ नहीं जानता, यह **TLS Termination Proxy** के साथ plain HTTP में communicate करता है। + +यह **proxy** सामान्यतः request को **application server** तक transmit करने से पहले कुछ HTTP headers on the fly set करेगा, ताकि application server को पता चल सके कि request proxy द्वारा **forwarded** की जा रही है। + +/// note | तकनीकी विवरण + +Proxy headers हैं: + +* [X-Forwarded-For](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-For) +* [X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Proto) +* [X-Forwarded-Host](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Forwarded-Host) + +/// + +फिर भी, क्योंकि **application server** नहीं जानता कि वह trusted **proxy** के पीछे है, by default, वह उन headers पर trust नहीं करेगा। + +लेकिन आप **application server** को **proxy** द्वारा भेजे गए *forwarded* headers पर trust करने के लिए configure कर सकते हैं। अगर आप FastAPI CLI का उपयोग कर रहे हैं, तो आप *CLI Option* `--forwarded-allow-ips` का उपयोग करके उसे बता सकते हैं कि उसे किन IPs से आने वाले उन *forwarded* headers पर trust करना चाहिए। + +उदाहरण के लिए, अगर **application server** केवल trusted **proxy** से communication receive कर रहा है, तो आप इसे `--forwarded-allow-ips="*"` पर set कर सकते हैं ताकि यह सभी incoming IPs पर trust करे, क्योंकि यह केवल उसी IP से requests receive करेगा जिसका उपयोग **proxy** कर रहा है। + +इस तरह application यह जान पाएगी कि उसका अपना public URL क्या है, क्या वह HTTPS का उपयोग कर रही है, domain, आदि। + +यह उदाहरण के लिए redirects को ठीक से handle करने में उपयोगी होगा। + +/// tip | सुझाव + +आप इसके बारे में documentation में और सीख सकते हैं: [Proxy के पीछे - Proxy Forwarded Headers सक्षम करें](../advanced/behind-a-proxy.md#enable-proxy-forwarded-headers) + +/// + +## Recap { #recap } + +**HTTPS** होना बहुत महत्वपूर्ण है, और अधिकांश मामलों में काफी **critical** है। HTTPS के आसपास एक developer के रूप में आपको जो ज़्यादातर effort लगाना होता है, वह बस **इन concepts को समझने** और वे कैसे काम करते हैं, इसे समझने के बारे में है। + +लेकिन एक बार जब आप **developers के लिए HTTPS** की मूल जानकारी जान लेते हैं, तो आप सब कुछ सरल तरीके से manage करने में मदद के लिए अलग-अलग tools को आसानी से combine और configure कर सकते हैं। + +अगले कुछ chapters में, मैं आपको **FastAPI** applications के लिए **HTTPS** setup करने के कई ठोस उदाहरण दिखाऊँगा। 🔒 diff --git a/docs/hi/docs/deployment/index.md b/docs/hi/docs/deployment/index.md new file mode 100644 index 000000000..7b0c5b2d5 --- /dev/null +++ b/docs/hi/docs/deployment/index.md @@ -0,0 +1,23 @@ +# Deployment { #deployment } + +**FastAPI** application को deploy करना अपेक्षाकृत आसान है। + +## Deployment का क्या अर्थ है { #what-does-deployment-mean } + +किसी application को **deploy** करने का अर्थ है उसे **users के लिए उपलब्ध** कराने के लिए आवश्यक चरण पूरे करना। + +किसी **web API** के लिए, इसमें सामान्यतः उसे एक **remote machine** में रखना शामिल होता है, एक **server program** के साथ जो अच्छा performance, stability आदि प्रदान करता है, ताकि आपके **users** application को कुशलता से और बिना रुकावटों या समस्याओं के **access** कर सकें। + +यह **development** चरणों के विपरीत है, जहाँ आप लगातार code बदल रहे होते हैं, उसे तोड़ते और ठीक करते हैं, development server को रोकते और फिर से शुरू करते हैं, आदि। + +## Deployment Strategies { #deployment-strategies } + +इसे करने के कई तरीके हैं, जो आपके विशिष्ट use case और आपके द्वारा उपयोग किए जाने वाले tools पर निर्भर करते हैं। + +आप tools के संयोजन का उपयोग करके स्वयं **server deploy** कर सकते हैं, आप कोई **cloud service** उपयोग कर सकते हैं जो आपके लिए काम का कुछ हिस्सा करती है, या अन्य संभावित विकल्प चुन सकते हैं। + +उदाहरण के लिए, हमने, FastAPI के पीछे की team ने, [**FastAPI Cloud**](https://fastapicloud.com) बनाया, ताकि FastAPI apps को cloud पर deploy करना जितना संभव हो उतना streamlined हो, FastAPI के साथ काम करने के समान developer experience के साथ। + +मैं आपको कुछ मुख्य concepts दिखाऊँगा जिन्हें **FastAPI** application deploy करते समय शायद ध्यान में रखना चाहिए (हालाँकि इनमें से अधिकतर किसी भी अन्य प्रकार की web application पर लागू होता है)। + +अगले sections में आपको ध्यान में रखने के लिए अधिक details और इसे करने की कुछ techniques दिखेंगी। ✨ diff --git a/docs/hi/docs/deployment/manually.md b/docs/hi/docs/deployment/manually.md new file mode 100644 index 000000000..840421513 --- /dev/null +++ b/docs/hi/docs/deployment/manually.md @@ -0,0 +1,156 @@ +# Server को मैन्युअली चलाएँ { #run-a-server-manually } + +## `fastapi run` Command का उपयोग करें { #use-the-fastapi-run-command } + +संक्षेप में, अपनी FastAPI application serve करने के लिए `fastapi run` का उपयोग करें: + +
+ +```console +$ fastapi run main.py + + FastAPI Starting production server 🚀 + + Searching for package file structure from directories + with __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with + the following code: + + from main import app + + app Using import string: main:app + + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs + + Logs: + + INFO Started server process [2306215] + INFO Waiting for application startup. + INFO Application startup complete. + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C + to quit) +``` + +
+ +यह ज़्यादातर मामलों में काम करेगा। 😎 + +आप उस command का उपयोग, उदाहरण के लिए, अपनी **FastAPI** app को किसी container में, किसी server में, आदि शुरू करने के लिए कर सकते हैं। + +## ASGI Servers { #asgi-servers } + +आइए details में थोड़ा और गहराई से देखें। + +FastAPI Python web frameworks और servers बनाने के लिए एक standard का उपयोग करता है जिसे ASGI कहा जाता है। FastAPI एक ASGI web framework है। + +किसी remote server machine में **FastAPI** application (या कोई भी दूसरी ASGI application) चलाने के लिए आपको मुख्य रूप से एक ASGI server program चाहिए, जैसे **Uvicorn**; यही `fastapi` command में default रूप से आता है। + +कई विकल्प हैं, जिनमें शामिल हैं: + +* [Uvicorn](https://www.uvicorn.dev/): एक high performance ASGI server। +* [Hypercorn](https://hypercorn.readthedocs.io/): एक ASGI server जो अन्य features के साथ HTTP/2 और Trio के साथ compatible है। +* [Daphne](https://github.com/django/daphne): Django Channels के लिए बनाया गया ASGI server। +* [Granian](https://github.com/emmett-framework/granian): Python applications के लिए एक Rust HTTP server। + +## Server Machine और Server Program { #server-machine-and-server-program } + +नामों के बारे में ध्यान रखने योग्य एक छोटा-सा detail है। 💡 + +शब्द "**server**" आमतौर पर remote/cloud computer (physical या virtual machine) और उस machine पर चल रहे program (जैसे Uvicorn), दोनों के लिए उपयोग किया जाता है। + +बस ध्यान रखें कि जब आप सामान्य रूप से "server" पढ़ते हैं, तो यह उन दो चीज़ों में से किसी एक को संदर्भित कर सकता है। + +Remote machine का संदर्भ देते समय, इसे **server** कहना आम है, लेकिन **machine**, **VM** (virtual machine), **node** भी कहा जाता है। ये सभी किसी प्रकार की remote machine को संदर्भित करते हैं, जो सामान्यतः Linux चला रही होती है, जहाँ आप programs चलाते हैं। + +## Server Program Install करें { #install-the-server-program } + +जब आप FastAPI install करते हैं, तो यह एक production server, Uvicorn, के साथ आता है, और आप इसे `fastapi run` command से शुरू कर सकते हैं। + +लेकिन आप एक ASGI server को मैन्युअली भी install कर सकते हैं। + +सुनिश्चित करें कि आप एक [virtual environment](../virtual-environments.md) बनाएँ, उसे activate करें, और फिर आप server application install कर सकते हैं। + +उदाहरण के लिए, Uvicorn install करने के लिए: + +
+ +```console +$ pip install "uvicorn[standard]" + +---> 100% +``` + +
+ +किसी भी अन्य ASGI server program के लिए भी इसी तरह की प्रक्रिया लागू होगी। + +/// tip | टिप + +`standard` जोड़ने पर, Uvicorn कुछ recommended extra dependencies install और use करेगा। + +इसमें `uvloop` शामिल है, जो `asyncio` के लिए high-performance drop-in replacement है, और बड़ा concurrency performance boost देता है। + +जब आप `pip install "fastapi[standard]"` जैसी किसी command से FastAPI install करते हैं, तो आपको `uvicorn[standard]` भी मिल जाता है। + +/// + +## Server Program चलाएँ { #run-the-server-program } + +यदि आपने ASGI server मैन्युअली install किया है, तो आमतौर पर आपको अपनी FastAPI application import कराने के लिए एक खास format में import string पास करनी होगी: + +
+ +```console +$ uvicorn main:app --host 0.0.0.0 --port 80 + +INFO: Uvicorn running on http://0.0.0.0:80 (Press CTRL+C to quit) +``` + +
+ +/// note | नोट + +Command `uvicorn main:app` इनका संदर्भ देती है: + +* `main`: file `main.py` (Python "module")। +* `app`: `main.py` के अंदर `app = FastAPI()` line से बनाया गया object। + +यह इसके equivalent है: + +```Python +from main import app +``` + +/// + +हर alternative ASGI server program की command मिलती-जुलती होगी, आप उनके संबंधित documentation में और पढ़ सकते हैं। + +/// warning | चेतावनी + +Uvicorn और अन्य servers एक `--reload` option support करते हैं जो development के दौरान उपयोगी होता है। + +`--reload` option बहुत अधिक resources consume करता है, अधिक unstable होता है, आदि। + +यह **development** के दौरान बहुत मदद करता है, लेकिन आपको इसे **production** में use **नहीं** करना चाहिए। + +/// + +## Deployment Concepts { #deployment-concepts } + +ये examples server program (जैसे Uvicorn) चलाते हैं, **एक single process** शुरू करते हैं, जो predefined port (जैसे `80`) पर सभी IPs (`0.0.0.0`) को listen करता है। + +यह basic idea है। लेकिन आप शायद कुछ अतिरिक्त चीज़ों का ध्यान रखना चाहेंगे, जैसे: + +* Security - HTTPS +* startup पर चलना +* Restarts +* Replication (चल रहे processes की संख्या) +* Memory +* शुरू करने से पहले के previous steps + +अगले chapters में मैं आपको इन concepts में से हर एक के बारे में, उनके बारे में कैसे सोचें, और उन्हें handle करने की strategies के साथ कुछ concrete examples के बारे में और बताऊँगा। 🚀 diff --git a/docs/hi/docs/deployment/server-workers.md b/docs/hi/docs/deployment/server-workers.md new file mode 100644 index 000000000..540c2da5e --- /dev/null +++ b/docs/hi/docs/deployment/server-workers.md @@ -0,0 +1,139 @@ +# Server Workers - Workers के साथ Uvicorn { #server-workers-uvicorn-with-workers } + +आइए पहले वाले deployment concepts को फिर से देखें: + +* Security - HTTPS +* startup पर चलना +* Restarts +* **Replication (चल रहे processes की संख्या)** +* Memory +* शुरू करने से पहले के पिछले steps + +इस बिंदु तक, docs के सभी tutorials में, आपने शायद एक **server program** चलाया होगा, उदाहरण के लिए, `fastapi` command का उपयोग करके, जो Uvicorn चलाता है, और एक **single process** चलाता है। + +Applications deploy करते समय आप शायद **processes की कुछ replication** रखना चाहेंगे ताकि **multiple cores** का लाभ लिया जा सके और अधिक requests handle की जा सकें। + +जैसा कि आपने पिछले chapter में [Deployment Concepts](concepts.md) के बारे में देखा, कई strategies हैं जिनका आप उपयोग कर सकते हैं। + +यहाँ मैं आपको दिखाऊँगा कि `fastapi` command या सीधे `uvicorn` command का उपयोग करके **worker processes** के साथ **Uvicorn** कैसे उपयोग करें। + +/// note | नोट + +यदि आप containers का उपयोग कर रहे हैं, उदाहरण के लिए Docker या Kubernetes के साथ, तो मैं आपको इसके बारे में अगले chapter में और बताऊँगा: [Containers में FastAPI - Docker](docker.md)। + +विशेष रूप से, **Kubernetes** पर चलते समय आप शायद workers का उपयोग **नहीं** करना चाहेंगे और इसके बजाय **प्रति container एक single Uvicorn process** चलाना चाहेंगे, लेकिन मैं आपको इसके बारे में उस chapter में बाद में बताऊँगा। + +/// + +## Multiple Workers { #multiple-workers } + +आप `--workers` command line option के साथ multiple workers शुरू कर सकते हैं: + +//// tab | `fastapi` + +यदि आप `fastapi` command का उपयोग करते हैं: + +
+ +```console +$ fastapi run --workers 4 main.py + + FastAPI Starting production server 🚀 + + Searching for package file structure from directories with + __init__.py files + Importing from /home/user/code/awesomeapp + + module 🐍 main.py + + code Importing the FastAPI app object from the module with the + following code: + + from main import app + + app Using import string: main:app + + server Server started at http://0.0.0.0:8000 + server Documentation at http://0.0.0.0:8000/docs + + Logs: + + INFO Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to + quit) + INFO Started parent process [27365] + INFO Started server process [27368] + INFO Started server process [27369] + INFO Started server process [27370] + INFO Started server process [27367] + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Waiting for application startup. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. + INFO Application startup complete. +``` + +
+ +//// + +//// tab | `uvicorn` + +यदि आप सीधे `uvicorn` command का उपयोग करना पसंद करते हैं: + +
+ +```console +$ uvicorn main:app --host 0.0.0.0 --port 8080 --workers 4 +INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit) +INFO: Started parent process [27365] +INFO: Started server process [27368] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27369] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27370] +INFO: Waiting for application startup. +INFO: Application startup complete. +INFO: Started server process [27367] +INFO: Waiting for application startup. +INFO: Application startup complete. +``` + +
+ +//// + +यहाँ एकमात्र नया option `--workers` है, जो Uvicorn को 4 worker processes शुरू करने के लिए कहता है। + +आप यह भी देख सकते हैं कि यह प्रत्येक process का **PID** दिखाता है, parent process के लिए `27365` (यह **process manager** है) और प्रत्येक worker process के लिए एक: `27368`, `27369`, `27370`, और `27367`। + +## Deployment Concepts { #deployment-concepts } + +यहाँ आपने देखा कि application के execution को **parallelize** करने, CPU में **multiple cores** का लाभ लेने, और **अधिक requests** serve करने में सक्षम होने के लिए multiple **workers** का उपयोग कैसे किया जाता है। + +ऊपर दी गई deployment concepts की सूची से, workers का उपयोग मुख्य रूप से **replication** वाले हिस्से में मदद करेगा, और थोड़ा बहुत **restarts** में भी, लेकिन आपको अभी भी बाकी चीज़ों का ध्यान रखना होगा: + +* **Security - HTTPS** +* **startup पर चलना** +* ***Restarts*** +* Replication (चल रहे processes की संख्या) +* **Memory** +* **शुरू करने से पहले के पिछले steps** + +## Containers और Docker { #containers-and-docker } + +अगले chapter में [Containers में FastAPI - Docker](docker.md) के बारे में मैं कुछ strategies समझाऊँगा जिनका उपयोग आप बाकी **deployment concepts** को handle करने के लिए कर सकते हैं। + +मैं आपको दिखाऊँगा कि single Uvicorn process चलाने के लिए **शुरू से अपनी खुद की image कैसे build करें**। यह एक सरल process है और शायद यही आप तब करना चाहेंगे जब आप **Kubernetes** जैसे distributed container management system का उपयोग कर रहे हों। + +## Recap { #recap } + +आप `fastapi` या `uvicorn` commands के साथ `--workers` CLI option का उपयोग करके multiple worker processes का उपयोग कर सकते हैं, ताकि **multi-core CPUs** का लाभ लिया जा सके और **multiple processes parallel में** चलाए जा सकें। + +यदि आप बाकी deployment concepts का खुद ध्यान रखते हुए **अपना खुद का deployment system** setup कर रहे हैं, तो आप इन tools और ideas का उपयोग कर सकते हैं। + +Containers (जैसे Docker और Kubernetes) के साथ **FastAPI** के बारे में जानने के लिए अगला chapter देखें। आप देखेंगे कि उन tools में बाकी **deployment concepts** को भी हल करने के सरल तरीके हैं। ✨ diff --git a/docs/hi/docs/deployment/versions.md b/docs/hi/docs/deployment/versions.md new file mode 100644 index 000000000..cabf4bc31 --- /dev/null +++ b/docs/hi/docs/deployment/versions.md @@ -0,0 +1,93 @@ +# FastAPI संस्करणों के बारे में { #about-fastapi-versions } + +**FastAPI** पहले से ही कई applications और प्रणालियों में production में उपयोग किया जा रहा है। और test coverage 100% पर रखा जाता है। लेकिन इसका development अभी भी तेजी से आगे बढ़ रहा है। + +नई features अक्सर जोड़ी जाती हैं, bugs नियमित रूप से ठीक किए जाते हैं, और code अभी भी लगातार बेहतर हो रहा है। + +इसीलिए वर्तमान संस्करण अभी भी `0.x.x` हैं, यह दर्शाता है कि हर संस्करण में संभावित रूप से breaking changes हो सकते हैं। यह [Semantic Versioning](https://semver.org/) conventions का पालन करता है। + +आप अभी **FastAPI** के साथ production applications बना सकते हैं (और संभव है कि आप कुछ समय से ऐसा कर भी रहे हों), आपको बस यह सुनिश्चित करना होगा कि आप ऐसा संस्करण उपयोग करें जो आपके बाकी code के साथ सही ढंग से काम करता हो। + +## अपने `fastapi` संस्करण को pin करें { #pin-your-fastapi-version } + +सबसे पहले आपको **FastAPI** के जिस संस्करण का उपयोग आप कर रहे हैं उसे उस विशिष्ट नवीनतम संस्करण पर "pin" करना चाहिए जिसके बारे में आपको पता है कि वह आपके application के लिए सही ढंग से काम करता है। + +उदाहरण के लिए, मान लें कि आप अपने app में संस्करण `0.112.0` उपयोग कर रहे हैं। + +यदि आप `requirements.txt` file उपयोग करते हैं, तो आप संस्करण को इस तरह निर्दिष्ट कर सकते हैं: + +```txt +fastapi[standard]==0.112.0 +``` + +इसका मतलब होगा कि आप ठीक संस्करण `0.112.0` का उपयोग करेंगे। + +या आप इसे इस तरह भी pin कर सकते हैं: + +```txt +fastapi[standard]>=0.112.0,<0.113.0 +``` + +इसका मतलब होगा कि आप संस्करण `0.112.0` या उससे ऊपर, लेकिन `0.113.0` से कम उपयोग करेंगे, उदाहरण के लिए, संस्करण `0.112.2` अभी भी स्वीकार किया जाएगा। + +यदि आप अपनी installations प्रबंधित करने के लिए कोई अन्य tool उपयोग करते हैं, जैसे `uv`, Poetry, Pipenv, या अन्य, तो उन सभी में ऐसा तरीका होता है जिसका उपयोग करके आप अपने packages के लिए विशिष्ट संस्करण परिभाषित कर सकते हैं। + +## उपलब्ध संस्करण { #available-versions } + +आप उपलब्ध संस्करणों को (जैसे वर्तमान नवीनतम क्या है यह जांचने के लिए) [Release Notes](../release-notes.md) में देख सकते हैं। + +## संस्करणों के बारे में { #about-versions } + +Semantic Versioning conventions के अनुसार, `1.0.0` से नीचे का कोई भी संस्करण संभावित रूप से breaking changes जोड़ सकता है। + +FastAPI इस convention का भी पालन करता है कि कोई भी "PATCH" संस्करण परिवर्तन bug fixes और non-breaking changes के लिए होता है। + +/// tip | सुझाव + +"PATCH" आखिरी संख्या होती है, उदाहरण के लिए, `0.2.3` में, PATCH संस्करण `3` है। + +/// + +तो, आपको इस तरह के संस्करण पर pin करने में सक्षम होना चाहिए: + +```txt +fastapi>=0.45.0,<0.46.0 +``` + +Breaking changes और नई features "MINOR" संस्करणों में जोड़ी जाती हैं। + +/// tip | सुझाव + +"MINOR" बीच की संख्या होती है, उदाहरण के लिए, `0.2.3` में, MINOR संस्करण `2` है। + +/// + +## FastAPI संस्करणों को upgrade करना { #upgrading-the-fastapi-versions } + +आपको अपने app के लिए tests जोड़ने चाहिए। + +**FastAPI** के साथ यह बहुत आसान है (Starlette के लिए धन्यवाद), docs देखें: [Testing](../tutorial/testing.md) + +Tests होने के बाद, आप **FastAPI** संस्करण को अधिक हाल के संस्करण में upgrade कर सकते हैं, और अपने tests चलाकर सुनिश्चित कर सकते हैं कि आपका पूरा code सही ढंग से काम कर रहा है। + +यदि सब कुछ काम कर रहा है, या आवश्यक बदलाव करने के बाद, और आपके सभी tests pass हो रहे हैं, तो आप अपने `fastapi` को उस नए हालिया संस्करण पर pin कर सकते हैं। + +## Starlette के बारे में { #about-starlette } + +आपको `starlette` के संस्करण को pin नहीं करना चाहिए। + +**FastAPI** के अलग-अलग संस्करण Starlette के किसी विशिष्ट नए संस्करण का उपयोग करेंगे। + +इसलिए, आप बस **FastAPI** को सही Starlette संस्करण उपयोग करने दे सकते हैं। + +## Pydantic के बारे में { #about-pydantic } + +Pydantic अपने tests में **FastAPI** के tests शामिल करता है, इसलिए Pydantic के नए संस्करण (`1.0.0` से ऊपर) हमेशा FastAPI के साथ compatible होते हैं। + +आप Pydantic को `1.0.0` से ऊपर किसी भी ऐसे संस्करण पर pin कर सकते हैं जो आपके लिए काम करता हो। + +उदाहरण के लिए: + +```txt +pydantic>=2.7.0,<3.0.0 +``` diff --git a/docs/hi/docs/how-to/authentication-error-status-code.md b/docs/hi/docs/how-to/authentication-error-status-code.md new file mode 100644 index 000000000..267743d44 --- /dev/null +++ b/docs/hi/docs/how-to/authentication-error-status-code.md @@ -0,0 +1,17 @@ +# पुराने 403 Authentication Error Status Codes का उपयोग करें { #use-old-403-authentication-error-status-codes } + +FastAPI version `0.122.0` से पहले, जब integrated security utilities failed authentication के बाद client को error लौटाती थीं, तो वे HTTP status code `403 Forbidden` का उपयोग करती थीं। + +FastAPI version `0.122.0` से शुरू होकर, वे अधिक उपयुक्त HTTP status code `401 Unauthorized` का उपयोग करती हैं, और HTTP specifications, [RFC 7235](https://datatracker.ietf.org/doc/html/rfc7235#section-3.1), [RFC 9110](https://datatracker.ietf.org/doc/html/rfc9110#name-401-unauthorized) का पालन करते हुए response में एक उचित `WWW-Authenticate` header लौटाती हैं। + +लेकिन अगर किसी कारण से आपके clients पुराने behavior पर निर्भर हैं, तो आप अपनी security classes में method `make_not_authenticated_error` को override करके उस पर वापस जा सकते हैं। + +उदाहरण के लिए, आप `HTTPBearer` का एक subclass बना सकते हैं जो default `401 Unauthorized` error के बजाय `403 Forbidden` error लौटाता है: + +{* ../../docs_src/authentication_error_status_code/tutorial001_an_py310.py hl[9:13] *} + +/// tip | टिप + +ध्यान दें कि function exception instance लौटाता है, उसे raise नहीं करता। raising बाकी internal code में किया जाता है। + +/// diff --git a/docs/hi/docs/how-to/conditional-openapi.md b/docs/hi/docs/how-to/conditional-openapi.md new file mode 100644 index 000000000..3a39cd326 --- /dev/null +++ b/docs/hi/docs/how-to/conditional-openapi.md @@ -0,0 +1,56 @@ +# सशर्त OpenAPI { #conditional-openapi } + +अगर आपको ज़रूरत हो, तो आप environment के आधार पर OpenAPI को सशर्त रूप से configure करने के लिए settings और environment variables का उपयोग कर सकते हैं, और इसे पूरी तरह disable भी कर सकते हैं। + +## security, APIs, और docs के बारे में { #about-security-apis-and-docs } + +production में अपनी documentation user interfaces को छिपाना आपकी API को सुरक्षित करने का तरीका *नहीं होना चाहिए*। + +इससे आपकी API में कोई अतिरिक्त security नहीं जुड़ती, *path operations* अभी भी वहीं उपलब्ध रहेंगी जहाँ वे हैं। + +अगर आपके code में कोई security flaw है, तो वह अभी भी मौजूद रहेगा। + +documentation को छिपाना बस यह समझना अधिक कठिन बना देता है कि आपकी API के साथ कैसे interact किया जाए, और production में इसे debug करना आपके लिए अधिक कठिन बना सकता है। इसे बस [Security through obscurity](https://en.wikipedia.org/wiki/Security_through_obscurity) का एक रूप माना जा सकता है। + +अगर आप अपनी API को secure करना चाहते हैं, तो कई बेहतर चीज़ें हैं जो आप कर सकते हैं, उदाहरण के लिए: + +* सुनिश्चित करें कि आपके request bodies और responses के लिए अच्छी तरह defined Pydantic models हैं। +* dependencies का उपयोग करके कोई भी required permissions और roles configure करें। +* plaintext passwords कभी store न करें, केवल password hashes store करें। +* pwdlib और JWT tokens आदि जैसे जाने-माने cryptographic tools implement और use करें। +* जहाँ ज़रूरत हो, OAuth2 scopes के साथ अधिक granular permission controls जोड़ें। +* ...आदि। + +फिर भी, आपके पास कोई बहुत विशिष्ट use case हो सकता है जहाँ आपको सच में किसी environment (जैसे production) के लिए या environment variables से मिली configurations के आधार पर API docs को disable करने की ज़रूरत हो। + +## settings और env vars से सशर्त OpenAPI { #conditional-openapi-from-settings-and-env-vars } + +आप अपनी generated OpenAPI और docs UIs को configure करने के लिए आसानी से वही Pydantic settings use कर सकते हैं। + +उदाहरण के लिए: + +{* ../../docs_src/conditional_openapi/tutorial001_py310.py hl[6,11] *} + +यहाँ हम setting `openapi_url` को उसी default `"/openapi.json"` के साथ declare करते हैं। + +और फिर `FastAPI` app बनाते समय हम इसका उपयोग करते हैं। + +फिर आप environment variable `OPENAPI_URL` को empty string पर set करके OpenAPI (UI docs सहित) को disable कर सकते हैं, जैसे: + +
+ +```console +$ OPENAPI_URL= uvicorn main:app + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +फिर अगर आप `/openapi.json`, `/docs`, या `/redoc` URLs पर जाते हैं, तो आपको बस इस तरह का `404 Not Found` error मिलेगा: + +```JSON +{ + "detail": "Not Found" +} +``` diff --git a/docs/hi/docs/how-to/configure-swagger-ui.md b/docs/hi/docs/how-to/configure-swagger-ui.md new file mode 100644 index 000000000..9df59d68f --- /dev/null +++ b/docs/hi/docs/how-to/configure-swagger-ui.md @@ -0,0 +1,70 @@ +# Swagger UI configure करें { #configure-swagger-ui } + +आप कुछ अतिरिक्त [Swagger UI parameters](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/) configure कर सकते हैं। + +इन्हें configure करने के लिए, `FastAPI()` app object बनाते समय या `get_swagger_ui_html()` function में `swagger_ui_parameters` argument pass करें। + +`swagger_ui_parameters` एक dictionary प्राप्त करता है जिसमें configurations सीधे Swagger UI को pass की जाती हैं। + +FastAPI configurations को **JSON** में बदलता है ताकि वे JavaScript के साथ compatible हों, क्योंकि Swagger UI को यही चाहिए। + +## Syntax Highlighting disable करें { #disable-syntax-highlighting } + +उदाहरण के लिए, आप Swagger UI में syntax highlighting disable कर सकते हैं। + +Settings बदले बिना, syntax highlighting default रूप से enabled रहती है: + + + +लेकिन आप `syntaxHighlight` को `False` पर set करके इसे disable कर सकते हैं: + +{* ../../docs_src/configure_swagger_ui/tutorial001_py310.py hl[3] *} + +...और फिर Swagger UI अब syntax highlighting नहीं दिखाएगा: + + + +## Theme बदलें { #change-the-theme } + +इसी तरह आप key `"syntaxHighlight.theme"` के साथ syntax highlighting theme set कर सकते हैं (ध्यान दें कि इसके बीच में एक dot है): + +{* ../../docs_src/configure_swagger_ui/tutorial002_py310.py hl[3] *} + +वह configuration syntax highlighting color theme बदल देगी: + + + +## Default Swagger UI Parameters बदलें { #change-default-swagger-ui-parameters } + +FastAPI में ज़्यादातर use cases के लिए उपयुक्त कुछ default configuration parameters शामिल हैं। + +इसमें ये default configurations शामिल हैं: + +{* ../../fastapi/openapi/docs.py ln[9:24] hl[18:24] *} + +आप `swagger_ui_parameters` argument में अलग value set करके इनमें से किसी को भी override कर सकते हैं। + +उदाहरण के लिए, `deepLinking` disable करने के लिए आप ये settings `swagger_ui_parameters` में pass कर सकते हैं: + +{* ../../docs_src/configure_swagger_ui/tutorial003_py310.py hl[3] *} + +## अन्य Swagger UI Parameters { #other-swagger-ui-parameters } + +आप जिन अन्य सभी संभावित configurations का उपयोग कर सकते हैं, उन्हें देखने के लिए आधिकारिक [Swagger UI parameters के docs](https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/) पढ़ें। + +## केवल JavaScript settings { #javascript-only-settings } + +Swagger UI अन्य configurations को **केवल JavaScript** objects (उदाहरण के लिए, JavaScript functions) होने की भी अनुमति देता है। + +FastAPI में ये केवल JavaScript `presets` settings भी शामिल हैं: + +```JavaScript +presets: [ + SwaggerUIBundle.presets.apis, + SwaggerUIBundle.SwaggerUIStandalonePreset +] +``` + +ये **JavaScript** objects हैं, strings नहीं, इसलिए आप इन्हें सीधे Python code से pass नहीं कर सकते। + +अगर आपको ऐसी केवल JavaScript configurations का उपयोग करना है, तो आप ऊपर दिए गए methods में से किसी एक का उपयोग कर सकते हैं। पूरी Swagger UI *path operation* को override करें और आपको जो भी JavaScript चाहिए उसे manually लिखें। diff --git a/docs/hi/docs/how-to/custom-docs-ui-assets.md b/docs/hi/docs/how-to/custom-docs-ui-assets.md new file mode 100644 index 000000000..5f22186df --- /dev/null +++ b/docs/hi/docs/how-to/custom-docs-ui-assets.md @@ -0,0 +1,185 @@ +# कस्टम Docs UI Static Assets (Self-Hosting) { #custom-docs-ui-static-assets-self-hosting } + +API docs **Swagger UI** और **ReDoc** का उपयोग करते हैं, और उनमें से प्रत्येक को कुछ JavaScript और CSS files की जरूरत होती है। + +Default रूप से, वे files एक CDN से serve की जाती हैं। + +लेकिन इसे customize करना संभव है, आप कोई विशिष्ट CDN set कर सकते हैं, या files को स्वयं serve कर सकते हैं। + +## JavaScript और CSS के लिए कस्टम CDN { #custom-cdn-for-javascript-and-css } + +मान लें कि आप कोई अलग CDN उपयोग करना चाहते हैं, उदाहरण के लिए आप `https://unpkg.com/` उपयोग करना चाहते हैं। + +यह उपयोगी हो सकता है अगर, उदाहरण के लिए, आप ऐसे देश में रहते हैं जो कुछ URLs को restrict करता है। + +### Automatic docs को disable करें { #disable-the-automatic-docs } + +पहला step automatic docs को disable करना है, क्योंकि default रूप से, वे default CDN का उपयोग करते हैं। + +उन्हें disable करने के लिए, अपना `FastAPI` app बनाते समय उनके URLs को `None` पर set करें: + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[8] *} + +### कस्टम docs शामिल करें { #include-the-custom-docs } + +अब आप कस्टम docs के लिए *path operations* बना सकते हैं। + +आप docs के लिए HTML pages बनाने हेतु FastAPI के internal functions को reuse कर सकते हैं, और उन्हें जरूरी arguments pass कर सकते हैं: + +* `openapi_url`: वह URL जहां docs के लिए HTML page आपके API के लिए OpenAPI schema प्राप्त कर सकता है। आप यहां attribute `app.openapi_url` का उपयोग कर सकते हैं। +* `title`: आपके API का title। +* `oauth2_redirect_url`: default उपयोग करने के लिए आप यहां `app.swagger_ui_oauth2_redirect_url` का उपयोग कर सकते हैं। +* `swagger_js_url`: वह URL जहां आपके Swagger UI docs के लिए HTML **JavaScript** file प्राप्त कर सकता है। यह कस्टम CDN URL है। +* `swagger_css_url`: वह URL जहां आपके Swagger UI docs के लिए HTML **CSS** file प्राप्त कर सकता है। यह कस्टम CDN URL है। + +और ReDoc के लिए भी इसी तरह... + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[2:6,11:19,22:24,27:33] *} + +/// tip | सुझाव + +`swagger_ui_redirect` के लिए *path operation* तब एक helper है जब आप OAuth2 का उपयोग करते हैं। + +यदि आप अपने API को किसी OAuth2 provider के साथ integrate करते हैं, तो आप authenticate कर पाएंगे और प्राप्त credentials के साथ API docs पर वापस आ पाएंगे। और वास्तविक OAuth2 authentication का उपयोग करके उससे interact कर पाएंगे। + +Swagger UI आपके लिए इसे behind the scenes handle करेगा, लेकिन इसके लिए इस "redirect" helper की जरूरत होती है। + +/// + +### इसे test करने के लिए एक *path operation* बनाएं { #create-a-path-operation-to-test-it } + +अब, यह test करने के लिए कि सब कुछ काम करता है, एक *path operation* बनाएं: + +{* ../../docs_src/custom_docs_ui/tutorial001_py310.py hl[36:38] *} + +### इसे test करें { #test-it } + +अब, आप अपने docs पर [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) जा सकेंगे, और page reload करने पर, यह उन assets को नए CDN से load करेगा। + +## Docs के लिए JavaScript और CSS की Self-hosting { #self-hosting-javascript-and-css-for-docs } + +JavaScript और CSS की self-hosting उपयोगी हो सकती है अगर, उदाहरण के लिए, आपको चाहिए कि आपका app offline रहने पर भी, खुले Internet access के बिना, या local network में काम करता रहे। + +यहां आप देखेंगे कि उन files को स्वयं, उसी FastAPI app में कैसे serve किया जाए, और docs को उनका उपयोग करने के लिए कैसे configure किया जाए। + +### Project file structure { #project-file-structure } + +मान लें आपके project की file structure ऐसी दिखती है: + +``` +. +├── app +│ ├── __init__.py +│ ├── main.py +``` + +अब उन static files को store करने के लिए एक directory बनाएं। + +आपकी नई file structure ऐसी दिख सकती है: + +``` +. +├── app +│   ├── __init__.py +│   ├── main.py +└── static/ +``` + +### Files download करें { #download-the-files } + +Docs के लिए जरूरी static files download करें और उन्हें उस `static/` directory में रखें। + +आप शायद प्रत्येक link पर right-click करके "Save link as..." जैसा कोई option select कर सकते हैं। + +**Swagger UI** files का उपयोग करता है: + +* [`swagger-ui-bundle.js`](https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui-bundle.js) +* [`swagger-ui.css`](https://cdn.jsdelivr.net/npm/swagger-ui-dist@5/swagger-ui.css) + +और **ReDoc** file का उपयोग करता है: + +* [`redoc.standalone.js`](https://cdn.jsdelivr.net/npm/redoc@2/bundles/redoc.standalone.js) + +उसके बाद, आपकी file structure ऐसी दिख सकती है: + +``` +. +├── app +│   ├── __init__.py +│   ├── main.py +└── static + ├── redoc.standalone.js + ├── swagger-ui-bundle.js + └── swagger-ui.css +``` + +### Static files serve करें { #serve-the-static-files } + +* `StaticFiles` import करें। +* किसी विशिष्ट path में `StaticFiles()` instance को "Mount" करें। + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[7,11] *} + +### Static files को test करें { #test-the-static-files } + +अपना application start करें और [http://127.0.0.1:8000/static/redoc.standalone.js](http://127.0.0.1:8000/static/redoc.standalone.js) पर जाएं। + +आपको **ReDoc** के लिए एक बहुत लंबी JavaScript file दिखनी चाहिए। + +यह कुछ इस तरह से शुरू हो सकती है: + +```JavaScript +/*! For license information please see redoc.standalone.js.LICENSE.txt */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("null")): +... +``` + +यह confirm करता है कि आप अपने app से static files serve कर पा रहे हैं, और आपने docs के लिए static files को सही जगह पर रखा है। + +अब हम app को docs के लिए उन static files का उपयोग करने के लिए configure कर सकते हैं। + +### Static files के लिए automatic docs को disable करें { #disable-the-automatic-docs-for-static-files } + +कस्टम CDN का उपयोग करने जैसा ही, पहला step automatic docs को disable करना है, क्योंकि वे default रूप से CDN का उपयोग करते हैं। + +उन्हें disable करने के लिए, अपना `FastAPI` app बनाते समय उनके URLs को `None` पर set करें: + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[9] *} + +### Static files के लिए कस्टम docs शामिल करें { #include-the-custom-docs-for-static-files } + +और कस्टम CDN की तरह ही, अब आप कस्टम docs के लिए *path operations* बना सकते हैं। + +फिर से, आप docs के लिए HTML pages बनाने हेतु FastAPI के internal functions को reuse कर सकते हैं, और उन्हें जरूरी arguments pass कर सकते हैं: + +* `openapi_url`: वह URL जहां docs के लिए HTML page आपके API के लिए OpenAPI schema प्राप्त कर सकता है। आप यहां attribute `app.openapi_url` का उपयोग कर सकते हैं। +* `title`: आपके API का title। +* `oauth2_redirect_url`: default उपयोग करने के लिए आप यहां `app.swagger_ui_oauth2_redirect_url` का उपयोग कर सकते हैं। +* `swagger_js_url`: वह URL जहां आपके Swagger UI docs के लिए HTML **JavaScript** file प्राप्त कर सकता है। **यह वही है जिसे अब आपका अपना app serve कर रहा है**। +* `swagger_css_url`: वह URL जहां आपके Swagger UI docs के लिए HTML **CSS** file प्राप्त कर सकता है। **यह वही है जिसे अब आपका अपना app serve कर रहा है**। + +और ReDoc के लिए भी इसी तरह... + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[2:6,14:22,25:27,30:36] *} + +/// tip | सुझाव + +`swagger_ui_redirect` के लिए *path operation* तब एक helper है जब आप OAuth2 का उपयोग करते हैं। + +यदि आप अपने API को किसी OAuth2 provider के साथ integrate करते हैं, तो आप authenticate कर पाएंगे और प्राप्त credentials के साथ API docs पर वापस आ पाएंगे। और वास्तविक OAuth2 authentication का उपयोग करके उससे interact कर पाएंगे। + +Swagger UI आपके लिए इसे behind the scenes handle करेगा, लेकिन इसके लिए इस "redirect" helper की जरूरत होती है। + +/// + +### Static files को test करने के लिए एक *path operation* बनाएं { #create-a-path-operation-to-test-static-files } + +अब, यह test करने के लिए कि सब कुछ काम करता है, एक *path operation* बनाएं: + +{* ../../docs_src/custom_docs_ui/tutorial002_py310.py hl[39:41] *} + +### Static Files UI को test करें { #test-static-files-ui } + +अब, आप अपना WiFi disconnect कर सकेंगे, अपने docs पर [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs) जा सकेंगे, और page reload कर सकेंगे। + +और Internet के बिना भी, आप अपने API के docs देख पाएंगे और उससे interact कर पाएंगे। diff --git a/docs/hi/docs/how-to/custom-request-and-route.md b/docs/hi/docs/how-to/custom-request-and-route.md new file mode 100644 index 000000000..97743d169 --- /dev/null +++ b/docs/hi/docs/how-to/custom-request-and-route.md @@ -0,0 +1,109 @@ +# Custom Request और APIRoute class { #custom-request-and-apiroute-class } + +कुछ मामलों में, आप `Request` और `APIRoute` classes द्वारा उपयोग किए जाने वाले logic को override करना चाह सकते हैं। + +विशेष रूप से, यह middleware में logic का एक अच्छा विकल्प हो सकता है। + +उदाहरण के लिए, अगर आप request body को आपके application द्वारा process किए जाने से पहले पढ़ना या manipulate करना चाहते हैं। + +/// danger | खतरा + +यह एक "advanced" feature है। + +अगर आप अभी-अभी **FastAPI** के साथ शुरुआत कर रहे हैं, तो शायद आप इस section को छोड़ना चाहेंगे। + +/// + +## Use cases { #use-cases } + +कुछ use cases में शामिल हैं: + +* non-JSON request bodies को JSON में convert करना (जैसे [`msgpack`](https://msgpack.org/index.html)). +* gzip-compressed request bodies को decompress करना। +* सभी request bodies को automatically log करना। + +## Custom request body encodings को संभालना { #handling-custom-request-body-encodings } + +आइए देखें कि gzip requests को decompress करने के लिए custom `Request` subclass का उपयोग कैसे करें। + +और उस custom request class का उपयोग करने के लिए एक `APIRoute` subclass। + +### Custom `GzipRequest` class बनाएँ { #create-a-custom-gziprequest-class } + +/// tip | सुझाव + +यह दिखाने के लिए एक सरल उदाहरण है कि यह कैसे काम करता है, अगर आपको Gzip support चाहिए, तो आप दिए गए [`GzipMiddleware`](../advanced/middleware.md#gzipmiddleware) का उपयोग कर सकते हैं। + +/// + +सबसे पहले, हम एक `GzipRequest` class बनाते हैं, जो उपयुक्त header की मौजूदगी में body को decompress करने के लिए `Request.body()` method को overwrite करेगी। + +अगर header में `gzip` नहीं है, तो यह body को decompress करने की कोशिश नहीं करेगी। + +इस तरह, वही route class gzip compressed या uncompressed requests को संभाल सकती है। + +{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[9:16] *} + +### Custom `GzipRoute` class बनाएँ { #create-a-custom-gziproute-class } + +इसके बाद, हम `fastapi.routing.APIRoute` की एक custom subclass बनाते हैं जो `GzipRequest` का उपयोग करेगी। + +इस बार, यह `APIRoute.get_route_handler()` method को overwrite करेगी। + +यह method एक function return करता है। और वही function एक request प्राप्त करेगा और response return करेगा। + +यहाँ हम इसका उपयोग original request से `GzipRequest` बनाने के लिए करते हैं। + +{* ../../docs_src/custom_request_and_route/tutorial001_an_py310.py hl[19:27] *} + +/// note | तकनीकी विवरण + +एक `Request` में `request.scope` attribute होता है, जो बस एक Python `dict` है जिसमें request से संबंधित metadata होता है। + +एक `Request` में `request.receive` भी होता है, जो request की body को "receive" करने के लिए एक function है। + +`scope` `dict` और `receive` function दोनों ASGI specification का हिस्सा हैं। + +और ये दो चीजें, `scope` और `receive`, नई `Request` instance बनाने के लिए आवश्यक हैं। + +`Request` के बारे में अधिक जानने के लिए [Requests के बारे में Starlette के docs](https://www.starlette.dev/requests/) देखें। + +/// + +`GzipRequest.get_route_handler` द्वारा return किए गए function का केवल एक अलग काम है: `Request` को `GzipRequest` में convert करना। + +ऐसा करने से, हमारा `GzipRequest` data को हमारे *path operations* तक पास करने से पहले decompress करने का ध्यान रखेगा (अगर आवश्यक हो)। + +उसके बाद, processing logic सब वही रहता है। + +लेकिन `GzipRequest.body` में हमारे बदलावों की वजह से, request body जरूरत पड़ने पर **FastAPI** द्वारा load किए जाने पर automatically decompress हो जाएगी। + +## Exception handler में request body तक पहुँचना { #accessing-the-request-body-in-an-exception-handler } + +/// tip | सुझाव + +इसी समस्या को हल करने के लिए, `RequestValidationError` के custom handler में `body` का उपयोग करना शायद बहुत आसान है ([Errors संभालना](../tutorial/handling-errors.md#use-the-requestvalidationerror-body))। + +लेकिन यह उदाहरण अभी भी valid है और यह दिखाता है कि internal components के साथ कैसे interact करें। + +/// + +हम इसी approach का उपयोग exception handler में request body तक पहुँचने के लिए भी कर सकते हैं। + +हमें बस request को `try`/`except` block के अंदर संभालना है: + +{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[14,16] *} + +अगर कोई exception होता है, तो `Request` instance अभी भी scope में होगी, इसलिए error संभालते समय हम request body को पढ़ सकते हैं और उसका उपयोग कर सकते हैं: + +{* ../../docs_src/custom_request_and_route/tutorial002_an_py310.py hl[17:19] *} + +## Router में custom `APIRoute` class { #custom-apiroute-class-in-a-router } + +आप `APIRouter` का `route_class` parameter भी set कर सकते हैं: + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[26] *} + +इस उदाहरण में, `router` के अंतर्गत *path operations* custom `TimedRoute` class का उपयोग करेंगे, और response में एक अतिरिक्त `X-Response-Time` header होगा जिसमें response generate करने में लगा समय होगा: + +{* ../../docs_src/custom_request_and_route/tutorial003_py310.py hl[13:20] *} diff --git a/docs/hi/docs/how-to/extending-openapi.md b/docs/hi/docs/how-to/extending-openapi.md new file mode 100644 index 000000000..f3bebfa66 --- /dev/null +++ b/docs/hi/docs/how-to/extending-openapi.md @@ -0,0 +1,88 @@ +# OpenAPI को विस्तारित करना { #extending-openapi } + +कुछ मामलों में आपको generated OpenAPI schema को संशोधित करने की ज़रूरत हो सकती है। + +इस section में आप देखेंगे कि कैसे। + +## सामान्य process { #the-normal-process } + +सामान्य (default) process इस प्रकार है। + +एक `FastAPI` application (instance) में एक `.openapi()` method होता है, जिससे OpenAPI schema return करने की अपेक्षा की जाती है। + +application object बनाने के हिस्से के रूप में, `/openapi.json` के लिए (या आपने अपने `openapi_url` में जो भी set किया है उसके लिए) एक *path operation* registered होता है। + +यह बस application के `.openapi()` method के result के साथ एक JSON response return करता है। + +Default रूप से, method `.openapi()` जो करता है वह यह है कि property `.openapi_schema` को check करता है कि उसमें contents हैं या नहीं, और उन्हें return करता है। + +अगर नहीं हैं, तो यह उन्हें `fastapi.openapi.utils.get_openapi` में utility function का उपयोग करके generate करता है। + +और वह function `get_openapi()` parameters के रूप में ये प्राप्त करता है: + +* `title`: OpenAPI title, जो docs में दिखाया जाता है। +* `version`: आपके API का version, जैसे `2.5.0`। +* `openapi_version`: उपयोग की गई OpenAPI specification का version। Default रूप से, latest: `3.1.0`। +* `summary`: API का एक छोटा summary। +* `description`: आपके API का description, इसमें markdown शामिल हो सकता है और यह docs में दिखाया जाएगा। +* `routes`: application से routes, जो `app.routes` से लिए जाते हैं। FastAPI इन्हें registered *path operations* collect करने के लिए उपयोग करता है, जिनमें included routers से आने वाले भी शामिल हैं। + +/// tip | तकनीकी विवरण + +`app.routes` एक lower-level route tree है। इसमें route candidates शामिल हो सकते हैं जिन्हें FastAPI internally included routers के लिए उपयोग करता है, केवल final `APIRoute` objects ही नहीं। + +आप फिर भी `app.routes` को `get_openapi()` में pass कर सकते हैं। FastAPI effective path operations collect करने के लिए उस route tree को traverse करेगा। + +/// + +/// note | नोट + +parameter `summary` OpenAPI 3.1.0 और उससे ऊपर में उपलब्ध है, जिसे FastAPI 0.99.0 और उससे ऊपर support करता है। + +/// + +## Defaults को override करना { #overriding-the-defaults } + +ऊपर दी गई जानकारी का उपयोग करके, आप OpenAPI schema generate करने और अपनी ज़रूरत के अनुसार प्रत्येक हिस्से को override करने के लिए उसी utility function का उपयोग कर सकते हैं। + +उदाहरण के लिए, आइए [custom logo शामिल करने के लिए ReDoc का OpenAPI extension](https://github.com/Rebilly/ReDoc/blob/master/docs/redoc-vendor-extensions.md#x-logo) जोड़ें। + +### सामान्य **FastAPI** { #normal-fastapi } + +सबसे पहले, अपनी पूरी **FastAPI** application सामान्य रूप से लिखें: + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[1,4,7:9] *} + +### OpenAPI schema generate करें { #generate-the-openapi-schema } + +फिर, `custom_openapi()` function के अंदर, OpenAPI schema generate करने के लिए उसी utility function का उपयोग करें: + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[2,15:21] *} + +### OpenAPI schema को संशोधित करें { #modify-the-openapi-schema } + +अब आप OpenAPI schema में `info` "object" में custom `x-logo` जोड़कर ReDoc extension जोड़ सकते हैं: + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[22:24] *} + +### OpenAPI schema को cache करें { #cache-the-openapi-schema } + +आप अपनी generated schema store करने के लिए property `.openapi_schema` को "cache" के रूप में उपयोग कर सकते हैं। + +इस तरह, जब भी कोई user आपके API docs खोलेगा, आपकी application को हर बार schema generate नहीं करना पड़ेगा। + +यह केवल एक बार generate होगा, और फिर अगली requests के लिए वही cached schema उपयोग किया जाएगा। + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[13:14,25:26] *} + +### Method को override करें { #override-the-method } + +अब आप `.openapi()` method को अपने नए function से replace कर सकते हैं। + +{* ../../docs_src/extending_openapi/tutorial001_py310.py hl[29] *} + +### इसे check करें { #check-it } + +जब आप [http://127.0.0.1:8000/redoc](http://127.0.0.1:8000/redoc) पर जाएंगे, तो आप देखेंगे कि आप अपना custom logo उपयोग कर रहे हैं (इस उदाहरण में, **FastAPI** का logo): + + diff --git a/docs/hi/docs/how-to/general.md b/docs/hi/docs/how-to/general.md new file mode 100644 index 000000000..95c8bb653 --- /dev/null +++ b/docs/hi/docs/how-to/general.md @@ -0,0 +1,43 @@ +# सामान्य - How To - Recipes { #general-how-to-recipes } + +सामान्य या अक्सर पूछे जाने वाले प्रश्नों के लिए, docs में अन्य जगहों के कई pointers यहाँ दिए गए हैं। + +## Data फ़िल्टर करें - सुरक्षा { #filter-data-security } + +यह सुनिश्चित करने के लिए कि आप जितना data लौटाना चाहिए उससे अधिक न लौटाएँ, [Tutorial - Response Model - Return Type](../tutorial/response-model.md) के docs पढ़ें। + +## Response Performance को optimize करें - Response Model - Return Type { #optimize-response-performance-response-model-return-type } + +JSON data लौटाते समय performance को optimize करने के लिए, return type या response model का उपयोग करें, इस तरह Pydantic JSON में serialization को Rust side पर संभालेगा, Python से गुज़रे बिना। अधिक पढ़ें [Tutorial - Response Model - Return Type](../tutorial/response-model.md) के docs में। + +## Documentation Tags - OpenAPI { #documentation-tags-openapi } + +अपने *path operations* में tags जोड़ने और उन्हें docs UI में group करने के लिए, [Tutorial - Path Operation Configurations - Tags](../tutorial/path-operation-configuration.md#tags) के docs पढ़ें। + +## Documentation Summary और Description - OpenAPI { #documentation-summary-and-description-openapi } + +अपने *path operations* में summary और description जोड़ने, और उन्हें docs UI में दिखाने के लिए, [Tutorial - Path Operation Configurations - Summary and Description](../tutorial/path-operation-configuration.md#summary-and-description) के docs पढ़ें। + +## Documentation Response description - OpenAPI { #documentation-response-description-openapi } + +response का description define करने के लिए, जो docs UI में दिखाया जाता है, [Tutorial - Path Operation Configurations - Response description](../tutorial/path-operation-configuration.md#response-description) के docs पढ़ें। + +## Documentation में *Path Operation* को Deprecate करें - OpenAPI { #documentation-deprecate-a-path-operation-openapi } + +किसी *path operation* को deprecate करने और उसे docs UI में दिखाने के लिए, [Tutorial - Path Operation Configurations - Deprecation](../tutorial/path-operation-configuration.md#deprecate-a-path-operation) के docs पढ़ें। + +## किसी भी Data को JSON-compatible में convert करें { #convert-any-data-to-json-compatible } + +किसी भी data को JSON-compatible में convert करने के लिए, [Tutorial - JSON Compatible Encoder](../tutorial/encoder.md) के docs पढ़ें। + +## OpenAPI Metadata - Docs { #openapi-metadata-docs } + +अपने OpenAPI schema में metadata जोड़ने के लिए, जिसमें license, version, contact, आदि शामिल हैं, [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md) के docs पढ़ें। + +## OpenAPI Custom URL { #openapi-custom-url } + +OpenAPI URL को customize करने (या हटाने) के लिए, [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md#openapi-url) के docs पढ़ें। + +## OpenAPI Docs URLs { #openapi-docs-urls } + +अपने-आप generate किए गए docs user interfaces के लिए उपयोग किए जाने वाले URLs को update करने के लिए, [Tutorial - Metadata and Docs URLs](../tutorial/metadata.md#docs-urls) के docs पढ़ें। diff --git a/docs/hi/docs/how-to/graphql.md b/docs/hi/docs/how-to/graphql.md new file mode 100644 index 000000000..7a8fbdb3d --- /dev/null +++ b/docs/hi/docs/how-to/graphql.md @@ -0,0 +1,60 @@ +# GraphQL { #graphql } + +क्योंकि **FastAPI** **ASGI** standard पर आधारित है, इसलिए ASGI के साथ compatible किसी भी **GraphQL** library को integrate करना बहुत आसान है। + +आप उसी application में सामान्य FastAPI *path operations* को GraphQL के साथ combine कर सकते हैं। + +/// tip | सुझाव + +**GraphQL** कुछ बहुत specific use cases को solve करता है। + +Common **web APIs** की तुलना में इसके **advantages** और **disadvantages** हैं। + +सुनिश्चित करें कि आप evaluate करें कि आपके use case के लिए **benefits**, **drawbacks** की भरपाई करते हैं या नहीं। 🤓 + +/// + +## GraphQL Libraries { #graphql-libraries } + +यहाँ कुछ **GraphQL** libraries हैं जिनमें **ASGI** support है। आप उन्हें **FastAPI** के साथ उपयोग कर सकते हैं: + +* [Strawberry](https://strawberry.rocks/) 🍓 + * [FastAPI के लिए docs](https://strawberry.rocks/docs/integrations/fastapi) के साथ +* [Ariadne](https://ariadnegraphql.org/) + * [FastAPI के लिए docs](https://ariadnegraphql.org/docs/fastapi-integration) के साथ +* [Tartiflette](https://tartiflette.io/) + * ASGI integration प्रदान करने के लिए [Tartiflette ASGI](https://tartiflette.github.io/tartiflette-asgi/) के साथ +* [Graphene](https://graphene-python.org/) + * [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3) के साथ + +## Strawberry के साथ GraphQL { #graphql-with-strawberry } + +यदि आपको **GraphQL** के साथ काम करने की ज़रूरत है या आप करना चाहते हैं, तो [**Strawberry**](https://strawberry.rocks/) **recommended** library है क्योंकि इसका design **FastAPI** के design के सबसे करीब है, यह पूरी तरह **type annotations** पर आधारित है। + +आपके use case के आधार पर, आप कोई अलग library उपयोग करना पसंद कर सकते हैं, लेकिन अगर आप मुझसे पूछें, तो मैं शायद सुझाव दूँगा कि आप **Strawberry** आज़माएँ। + +यहाँ एक छोटा preview है कि आप Strawberry को FastAPI के साथ कैसे integrate कर सकते हैं: + +{* ../../docs_src/graphql_/tutorial001_py310.py hl[3,22,25] *} + +आप [Strawberry documentation](https://strawberry.rocks/) में Strawberry के बारे में और जान सकते हैं। + +और [FastAPI के साथ Strawberry](https://strawberry.rocks/docs/integrations/fastapi) के बारे में docs भी। + +## Starlette से पुराना `GraphQLApp` { #older-graphqlapp-from-starlette } + +Starlette के पिछले versions में [Graphene](https://graphene-python.org/) के साथ integrate करने के लिए एक `GraphQLApp` class शामिल थी। + +इसे Starlette से deprecated कर दिया गया था, लेकिन यदि आपके पास ऐसा code है जो इसका उपयोग करता था, तो आप आसानी से [starlette-graphene3](https://github.com/ciscorn/starlette-graphene3) पर **migrate** कर सकते हैं, जो वही use case cover करता है और जिसका **लगभग identical interface** है। + +/// tip | सुझाव + +यदि आपको GraphQL की ज़रूरत है, तो मैं फिर भी recommend करूँगा कि आप [Strawberry](https://strawberry.rocks/) देखें, क्योंकि यह custom classes और types की बजाय type annotations पर आधारित है। + +/// + +## और जानें { #learn-more } + +आप [official GraphQL documentation](https://graphql.org/) में **GraphQL** के बारे में और जान सकते हैं। + +आप ऊपर वर्णित उन libraries में से प्रत्येक के बारे में उनके links में और भी पढ़ सकते हैं। diff --git a/docs/hi/docs/how-to/index.md b/docs/hi/docs/how-to/index.md new file mode 100644 index 000000000..c42c2dd0c --- /dev/null +++ b/docs/hi/docs/how-to/index.md @@ -0,0 +1,13 @@ +# कैसे करें - रेसिपी { #how-to-recipes } + +यहाँ आप **कई topics** के लिए अलग-अलग recipes या "how to" guides देखेंगे। + +इनमें से ज़्यादातर ideas कमोबेश **स्वतंत्र** होंगे, और ज़्यादातर मामलों में आपको इन्हें केवल तभी पढ़ने की ज़रूरत होगी जब वे सीधे **आपके project** पर लागू होते हों। + +अगर कुछ आपके project के लिए रोचक और उपयोगी लगता है, तो आगे बढ़कर उसे देखें, लेकिन नहीं तो आप शायद उन्हें छोड़ सकते हैं। + +/// tip | सुझाव + +अगर आप **FastAPI सीखना** structured तरीके से चाहते हैं (recommended), तो इसके बजाय [ट्यूटोरियल - यूज़र गाइड](../tutorial/index.md) को अध्याय-दर-अध्याय पढ़ें। + +/// diff --git a/docs/hi/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md b/docs/hi/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md new file mode 100644 index 000000000..68bc07e30 --- /dev/null +++ b/docs/hi/docs/how-to/migrate-from-pydantic-v1-to-pydantic-v2.md @@ -0,0 +1,153 @@ +# Pydantic v1 से Pydantic v2 में माइग्रेट करें { #migrate-from-pydantic-v1-to-pydantic-v2 } + +अगर आपके पास कोई पुराना FastAPI app है, तो हो सकता है कि आप Pydantic version 1 का उपयोग कर रहे हों। + +FastAPI version 0.100.0 में Pydantic v1 या v2, दोनों में से किसी के लिए support था। यह वही उपयोग करता था जो आपने install किया हुआ था। + +FastAPI version 0.119.0 ने Pydantic v2 के अंदर से Pydantic v1 के लिए आंशिक support पेश किया (`pydantic.v1` के रूप में), ताकि v2 में migration आसान हो सके। + +FastAPI 0.126.0 ने Pydantic v1 के लिए support हटा दिया, लेकिन थोड़े समय के लिए `pydantic.v1` को support करना जारी रखा। + +FastAPI 0.128.0 ने `pydantic.v1` के लिए support भी हटा दिया, इसलिए FastAPI के नवीनतम versions के लिए Pydantic v2 required है। + +/// warning | चेतावनी + +Pydantic team ने **Python 3.14** से शुरू करते हुए, Python के नवीनतम versions के लिए Pydantic v1 का support बंद कर दिया। + +इसमें `pydantic.v1` भी शामिल है, जो अब Python 3.14 और उससे ऊपर में supported नहीं है। + +अगर आप Python की नवीनतम features का उपयोग करना चाहते हैं, तो आपको यह सुनिश्चित करना होगा कि आप Pydantic v2 का उपयोग करें। + +/// + +अगर आपके पास Pydantic v1 वाला कोई पुराना FastAPI app है, तो यहाँ मैं आपको दिखाऊँगा कि उसे Pydantic v2 में कैसे migrate करें, और gradual migration में मदद के लिए **FastAPI 0.119.0 की features** भी दिखाऊँगा। + +## आधिकारिक गाइड { #official-guide } + +Pydantic के पास v1 से v2 के लिए एक आधिकारिक [Migration Guide](https://docs.pydantic.dev/latest/migration/) है। + +इसमें यह भी शामिल है कि क्या बदला है, validations अब कैसे अधिक सही और strict हैं, संभावित caveats आदि। + +क्या बदला है इसे बेहतर समझने के लिए आप इसे पढ़ सकते हैं। + +## Tests { #tests } + +सुनिश्चित करें कि आपके app के लिए [tests](../tutorial/testing.md) हैं और आप उन्हें continuous integration (CI) पर चलाते हैं। + +इस तरह, आप upgrade कर सकते हैं और सुनिश्चित कर सकते हैं कि सब कुछ अभी भी अपेक्षा के अनुसार काम कर रहा है। + +## `bump-pydantic` { #bump-pydantic } + +कई मामलों में, जब आप customizations के बिना regular Pydantic models का उपयोग करते हैं, तो आप Pydantic v1 से Pydantic v2 में migration की अधिकांश प्रक्रिया automate कर पाएँगे। + +आप उसी Pydantic team का [`bump-pydantic`](https://github.com/pydantic/bump-pydantic) उपयोग कर सकते हैं। + +यह tool आपको उस अधिकांश code को अपने आप बदलने में मदद करेगा जिसे बदलने की ज़रूरत है। + +इसके बाद, आप tests चला सकते हैं और जाँच सकते हैं कि सब कुछ काम करता है या नहीं। अगर करता है, तो आपका काम हो गया। 😎 + +## v2 में Pydantic v1 { #pydantic-v1-in-v2 } + +Pydantic v2 में Pydantic v1 की सभी चीज़ें `pydantic.v1` submodule के रूप में शामिल हैं। लेकिन यह Python 3.13 से ऊपर के versions में अब supported नहीं है। + +इसका मतलब है कि आप Pydantic v2 का नवीनतम version install कर सकते हैं और इस submodule से पुराने Pydantic v1 components को import और उपयोग कर सकते हैं, जैसे कि आपके पास पुराना Pydantic v1 install हो। + +{* ../../docs_src/pydantic_v1_in_v2/tutorial001_an_py310.py hl[1,4] *} + +### v2 में Pydantic v1 के लिए FastAPI support { #fastapi-support-for-pydantic-v1-in-v2 } + +/// warning | चेतावनी + +`pydantic.v1` models के लिए यह FastAPI support **FastAPI 0.119.0** में जोड़ा गया था और **FastAPI 0.128.0** में हटा दिया गया। इसका उद्देश्य Pydantic v2 में migration के लिए अस्थायी सहायता होना था। + +FastAPI के वर्तमान versions में, अपने app में `pydantic.v1` model का उपयोग करने पर error आएगा। + +इस section का बाकी हिस्सा केवल उन पुराने versions में उपलब्ध अस्थायी support का वर्णन करता है। + +/// + +FastAPI 0.119.0 से, Pydantic v2 के अंदर से Pydantic v1 के लिए आंशिक support भी है, ताकि v2 में migration आसान हो सके। + +इसलिए, आप Pydantic को नवीनतम version 2 में upgrade कर सकते थे, और imports को `pydantic.v1` submodule का उपयोग करने के लिए बदल सकते थे, और कई मामलों में यह बस काम कर जाता। + +{* ../../docs_src/pydantic_v1_in_v2/tutorial002_an_py310.py hl[2,5,15] *} + +/// warning | चेतावनी + +ध्यान रखें कि Pydantic team अब Python के हाल के versions में Pydantic v1 को support नहीं करती, Python 3.14 से शुरू करते हुए, इसलिए `pydantic.v1` का उपयोग भी Python 3.14 और उससे ऊपर में supported नहीं है। + +/// + +### एक ही app में Pydantic v1 और v2 { #pydantic-v1-and-v2-on-the-same-app } + +Pydantic द्वारा यह **supported नहीं है** कि Pydantic v2 का कोई model हो जिसके अपने fields Pydantic v1 models के रूप में defined हों, या इसका उल्टा। + +```mermaid +graph TB + subgraph "❌ Not Supported" + direction TB + subgraph V2["Pydantic v2 Model"] + V1Field["Pydantic v1 Model"] + end + subgraph V1["Pydantic v1 Model"] + V2Field["Pydantic v2 Model"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +...लेकिन आपके पास एक ही app में अलग-अलग models हो सकते हैं, कुछ Pydantic v1 का उपयोग करते हुए और कुछ Pydantic v2 का उपयोग करते हुए। + +```mermaid +graph TB + subgraph "✅ Supported" + direction TB + subgraph V2["Pydantic v2 Model"] + V2Field["Pydantic v2 Model"] + end + subgraph V1["Pydantic v1 Model"] + V1Field["Pydantic v1 Model"] + end + end + + style V2 fill:#f9fff3 + style V1 fill:#fff6f0 + style V1Field fill:#fff6f0 + style V2Field fill:#f9fff3 +``` + +कुछ मामलों में, आपके FastAPI app में एक ही **path operation** में Pydantic v1 और v2 दोनों models होना भी संभव है: + +{* ../../docs_src/pydantic_v1_in_v2/tutorial003_an_py310.py hl[2:3,6,12,21:22] *} + +ऊपर दिए गए इस उदाहरण में, input model एक Pydantic v1 model है, और output model (`response_model=ItemV2` में defined) एक Pydantic v2 model है। + +### Pydantic v1 parameters { #pydantic-v1-parameters } + +अगर आपको Pydantic v1 models के साथ parameters के लिए FastAPI-specific tools जैसे `Body`, `Query`, `Form` आदि का उपयोग करना है, तो Pydantic v2 में migration पूरा करते समय आप उन्हें `fastapi.temp_pydantic_v1_params` से import कर सकते हैं: + +{* ../../docs_src/pydantic_v1_in_v2/tutorial004_an_py310.py hl[4,18] *} + +### चरणों में माइग्रेट करें { #migrate-in-steps } + +/// warning | चेतावनी + +नीचे वर्णित, एक ही app में Pydantic v1 और v2 दोनों models का उपयोग करके gradual migration केवल **FastAPI 0.119.0 से 0.127.x** में काम करता है। इसे **FastAPI 0.128.0** में हटा दिया गया, नवीनतम versions के लिए **Pydantic v2** models required हैं। + +/// + +/// tip | सुझाव + +पहले `bump-pydantic` के साथ कोशिश करें, अगर आपके tests pass हो जाते हैं और वह काम करता है, तो आपका काम एक command में हो गया। ✨ + +/// + +अगर `bump-pydantic` आपके use case के लिए काम नहीं करता, तो आप Pydantic v2 में gradual migration करने के लिए एक ही app में Pydantic v1 और v2 दोनों models के support का उपयोग कर सकते हैं। + +आप पहले Pydantic को नवीनतम version 2 का उपयोग करने के लिए upgrade कर सकते हैं, और अपने सभी models के लिए `pydantic.v1` का उपयोग करने के लिए imports बदल सकते हैं। + +फिर, आप gradual steps में, groups के रूप में अपने models को Pydantic v1 से v2 में migrate करना शुरू कर सकते हैं। 🚶 diff --git a/docs/hi/docs/how-to/separate-openapi-schemas.md b/docs/hi/docs/how-to/separate-openapi-schemas.md new file mode 100644 index 000000000..c5d2b17a0 --- /dev/null +++ b/docs/hi/docs/how-to/separate-openapi-schemas.md @@ -0,0 +1,102 @@ +# Input और Output के लिए अलग OpenAPI Schemas या नहीं { #separate-openapi-schemas-for-input-and-output-or-not } + +जबसे **Pydantic v2** रिलीज़ हुआ है, generated OpenAPI पहले की तुलना में थोड़ा अधिक सटीक और **सही** है। 😎 + +वास्तव में, कुछ मामलों में, एक ही Pydantic model के लिए OpenAPI में **दो JSON Schemas** भी होंगे, input और output के लिए, इस पर निर्भर करते हुए कि उनमें **default values** हैं या नहीं। + +आइए देखते हैं कि यह कैसे काम करता है और अगर आपको ज़रूरत हो तो इसे कैसे बदलना है। + +## Input और Output के लिए Pydantic Models { #pydantic-models-for-input-and-output } + +मान लीजिए आपके पास default values वाला एक Pydantic model है, जैसे यह: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:7] hl[7] *} + +### Input के लिए Model { #model-for-input } + +अगर आप इस model को यहाँ की तरह input के रूप में उपयोग करते हैं: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py ln[1:15] hl[14] *} + +...तो `description` field **required नहीं होगा**। क्योंकि इसका default value `None` है। + +### Docs में Input Model { #input-model-in-docs } + +आप docs में इसकी पुष्टि कर सकते हैं, `description` field के पास **लाल asterisk** नहीं है, इसे required के रूप में mark नहीं किया गया है: + +
+ +
+ +### Output के लिए Model { #model-for-output } + +लेकिन अगर आप उसी model को output के रूप में उपयोग करते हैं, जैसे यहाँ: + +{* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *} + +...तो क्योंकि `description` का default value है, अगर आप उस field के लिए **कुछ भी return नहीं करते**, तब भी इसका वही **default value** रहेगा। + +### Output Response Data के लिए Model { #model-for-output-response-data } + +अगर आप docs के साथ interact करते हैं और response जाँचते हैं, तो भले ही code ने `description` fields में से किसी एक में कुछ भी add नहीं किया, JSON response में default value (`null`) शामिल होता है: + +
+ +
+ +इसका मतलब है कि इसमें **हमेशा एक value होगा**, बस कभी-कभी value `None` हो सकता है (या JSON में `null`)। + +इसका मतलब है कि आपकी API का उपयोग करने वाले clients को यह जाँचने की ज़रूरत नहीं है कि value मौजूद है या नहीं, वे **मान सकते हैं कि field हमेशा मौजूद रहेगा**, बस कुछ मामलों में इसका default value `None` होगा। + +OpenAPI में इसे describe करने का तरीका है कि उस field को **required** के रूप में mark किया जाए, क्योंकि वह हमेशा मौजूद रहेगा। + +इस वजह से, किसी model के लिए JSON Schema अलग हो सकता है, यह इस पर निर्भर करता है कि उसे **input या output** के लिए उपयोग किया गया है: + +* **input** के लिए `description` **required नहीं होगा** +* **output** के लिए यह **required** होगा (और संभवतः `None`, या JSON terms में, `null`) + +### Docs में Output के लिए Model { #model-for-output-in-docs } + +आप docs में output model भी देख सकते हैं, **दोनों** `name` और `description` को **लाल asterisk** के साथ **required** के रूप में mark किया गया है: + +
+ +
+ +### Docs में Input और Output के लिए Model { #model-for-input-and-output-in-docs } + +और अगर आप OpenAPI में उपलब्ध सभी Schemas (JSON Schemas) जाँचते हैं, तो आप देखेंगे कि दो हैं, एक `Item-Input` और एक `Item-Output`। + +`Item-Input` के लिए, `description` **required नहीं है**, इसमें लाल asterisk नहीं है। + +लेकिन `Item-Output` के लिए, `description` **required** है, इसमें लाल asterisk है। + +
+ +
+ +**Pydantic v2** की इस feature के साथ, आपकी API documentation अधिक **precise** होती है, और अगर आपके पास autogenerated clients और SDKs हैं, तो वे भी अधिक precise होंगे, बेहतर **developer experience** और consistency के साथ। 🎉 + +## Schemas को अलग न करें { #do-not-separate-schemas } + +अब, कुछ मामले ऐसे हैं जहाँ आप **input और output के लिए same schema** रखना चाह सकते हैं। + +शायद इसका मुख्य use case यह है कि अगर आपके पास पहले से कुछ autogenerated client code/SDKs हैं और आप अभी सभी autogenerated client code/SDKs को update नहीं करना चाहते, तो शायद आप इसे किसी समय करना चाहेंगे, लेकिन शायद अभी नहीं। + +उस स्थिति में, आप **FastAPI** में इस feature को parameter `separate_input_output_schemas=False` के साथ disable कर सकते हैं। + +/// note | नोट + +`separate_input_output_schemas` के लिए support FastAPI `0.102.0` में add किया गया था। 🤓 + +/// + +{* ../../docs_src/separate_openapi_schemas/tutorial002_py310.py hl[10] *} + +### Docs में Input और Output Models के लिए Same Schema { #same-schema-for-input-and-output-models-in-docs } + +और अब model के लिए input और output के लिए केवल एक single schema होगा, सिर्फ `Item`, और इसमें `description` **required नहीं** होगा: + +
+ +
diff --git a/docs/hi/docs/how-to/testing-database.md b/docs/hi/docs/how-to/testing-database.md new file mode 100644 index 000000000..c5189ca21 --- /dev/null +++ b/docs/hi/docs/how-to/testing-database.md @@ -0,0 +1,7 @@ +# Database की Testing { #testing-a-database } + +आप databases, SQL, और SQLModel के बारे में [SQLModel docs](https://sqlmodel.tiangolo.com/) में पढ़ सकते हैं। 🤓 + +[FastAPI के साथ SQLModel इस्तेमाल करने पर एक छोटा tutorial](https://sqlmodel.tiangolo.com/tutorial/fastapi/) है। ✨ + +उस tutorial में [SQL databases की testing](https://sqlmodel.tiangolo.com/tutorial/fastapi/tests/) के बारे में एक section शामिल है। 😎 diff --git a/docs/hi/docs/resources/index.md b/docs/hi/docs/resources/index.md new file mode 100644 index 000000000..d60effdc7 --- /dev/null +++ b/docs/hi/docs/resources/index.md @@ -0,0 +1,3 @@ +# संसाधन { #resources } + +अतिरिक्त संसाधन, external links, और भी बहुत कुछ। ✈️ diff --git a/docs/hi/docs/tutorial/security/first-steps.md b/docs/hi/docs/tutorial/security/first-steps.md new file mode 100644 index 000000000..a7bf2e700 --- /dev/null +++ b/docs/hi/docs/tutorial/security/first-steps.md @@ -0,0 +1,203 @@ +# सुरक्षा - पहले कदम { #security-first-steps } + +मान लें कि आपका **backend** API किसी domain में है। + +और आपका **frontend** किसी दूसरे domain में है या उसी domain के किसी अलग path में है (या किसी mobile application में)। + +और आप चाहते हैं कि frontend, **username** और **password** का उपयोग करके backend के साथ authenticate कर सके। + +हम इसे **FastAPI** के साथ बनाने के लिए **OAuth2** का उपयोग कर सकते हैं। + +लेकिन आपको केवल वे छोटी-छोटी जानकारियाँ खोजने के लिए पूरी लंबी specification पढ़ने में समय न लगाना पड़े। + +आइए सुरक्षा संभालने के लिए **FastAPI** द्वारा दिए गए tools का उपयोग करें। + +## यह कैसा दिखता है { #how-it-looks } + +आइए पहले बस code का उपयोग करें और देखें कि यह कैसे काम करता है, और फिर हम वापस आकर समझेंगे कि क्या हो रहा है। + +## `main.py` बनाएँ { #create-main-py } + +उदाहरण को एक file `main.py` में copy करें: + +{* ../../docs_src/security/tutorial001_an_py310.py *} + +## इसे चलाएँ { #run-it } + +/// note | नोट + +[`python-multipart`](https://github.com/Kludex/python-multipart) package **FastAPI** के साथ अपने-आप install हो जाता है जब आप `pip install "fastapi[standard]"` command चलाते हैं। + +हालाँकि, अगर आप `pip install fastapi` command का उपयोग करते हैं, तो `python-multipart` package default रूप से शामिल नहीं होता। + +इसे manually install करने के लिए, सुनिश्चित करें कि आप एक [virtual environment](../../virtual-environments.md) बनाएँ, उसे activate करें, और फिर इसे इस तरह install करें: + +```console +$ pip install python-multipart +``` + +ऐसा इसलिए है क्योंकि **OAuth2**, `username` और `password` भेजने के लिए "form data" का उपयोग करता है। + +/// + +उदाहरण को इस तरह चलाएँ: + +
+ +```console +$ fastapi dev + +INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) +``` + +
+ +## इसे जाँचें { #check-it } + +Interactive docs पर जाएँ: [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs). + +आपको कुछ ऐसा दिखाई देगा: + + + +/// tip | Authorize बटन! + +आपके पास पहले से ही एक चमकदार नया "Authorize" बटन है। + +और आपकी *path operation* के ऊपर-दाएँ कोने में एक छोटा-सा lock है जिस पर आप click कर सकते हैं। + +/// + +और अगर आप उस पर click करते हैं, तो आपके पास `username` और `password` (और अन्य optional fields) type करने के लिए एक छोटा authorization form होगा: + + + +/// note | नोट + +आप form में क्या type करते हैं, इससे कोई फर्क नहीं पड़ता, यह अभी काम नहीं करेगा। लेकिन हम वहाँ तक पहुँचेंगे। + +/// + +यह निश्चित रूप से final users के लिए frontend नहीं है, लेकिन यह आपके पूरे API को interactively document करने के लिए एक शानदार automatic tool है। + +इसे frontend team द्वारा उपयोग किया जा सकता है (जो आप खुद भी हो सकते हैं)। + +इसे third party applications और systems द्वारा उपयोग किया जा सकता है। + +और इसे आप खुद भी उसी application को debug, check और test करने के लिए उपयोग कर सकते हैं। + +## `password` flow { #the-password-flow } + +अब थोड़ा पीछे चलते हैं और समझते हैं कि यह सब क्या है। + +`password` "flow", OAuth2 में परिभाषित उन तरीकों ("flows") में से एक है, जिनका उपयोग security और authentication संभालने के लिए किया जाता है। + +OAuth2 को इस तरह design किया गया था कि backend या API उस server से independent हो सके जो user को authenticate करता है। + +लेकिन इस case में, वही **FastAPI** application API और authentication दोनों संभालेगा। + +तो, आइए इसे उस simplified दृष्टिकोण से review करें: + +* User frontend में `username` और `password` type करता है, और `Enter` दबाता है। +* Frontend (जो user के browser में चल रहा है) उस `username` और `password` को हमारे API के एक specific URL पर भेजता है (`tokenUrl="token"` के साथ declare किया गया)। +* API उस `username` और `password` को check करता है, और एक "token" के साथ respond करता है (हमने अभी तक इनमें से कुछ भी implement नहीं किया है)। + * एक "token" बस कुछ content वाली string है जिसका उपयोग हम बाद में इस user को verify करने के लिए कर सकते हैं। + * सामान्यतः, token को कुछ समय बाद expire होने के लिए set किया जाता है। + * इसलिए, user को बाद में किसी समय फिर से log in करना होगा। + * और अगर token चोरी हो जाता है, तो risk कम होता है। यह किसी permanent key जैसा नहीं है जो हमेशा काम करेगी (अधिकांश cases में)। +* Frontend उस token को अस्थायी रूप से कहीं store करता है। +* User frontend web app के किसी दूसरे section में जाने के लिए frontend में click करता है। +* Frontend को API से कुछ और data fetch करने की आवश्यकता होती है। + * लेकिन उस specific endpoint के लिए इसे authentication चाहिए। + * इसलिए, हमारे API के साथ authenticate करने के लिए, यह `Authorization` header भेजता है जिसकी value `Bearer ` plus token होती है। + * अगर token में `foobar` है, तो `Authorization` header का content होगा: `Bearer foobar`. + +## **FastAPI** का `OAuth2PasswordBearer` { #fastapis-oauth2passwordbearer } + +**FastAPI** इन security features को implement करने के लिए abstraction के अलग-अलग levels पर कई tools देता है। + +इस उदाहरण में हम **OAuth2** का उपयोग करने जा रहे हैं, **Password** flow के साथ, **Bearer** token का उपयोग करते हुए। हम यह `OAuth2PasswordBearer` class का उपयोग करके करते हैं। + +/// note | नोट + +"bearer" token एकमात्र विकल्प नहीं है। + +लेकिन हमारे use case के लिए यह सबसे अच्छा है। + +और यह अधिकांश use cases के लिए सबसे अच्छा हो सकता है, जब तक कि आप OAuth2 expert न हों और ठीक-ठीक न जानते हों कि कोई दूसरा विकल्प आपकी आवश्यकताओं के लिए बेहतर क्यों है। + +उस case में, **FastAPI** आपको इसे बनाने के लिए tools भी देता है। + +/// + +जब हम `OAuth2PasswordBearer` class का instance बनाते हैं तो हम `tokenUrl` parameter pass करते हैं। इस parameter में वह URL होता है जिसका उपयोग client (user के browser में चल रहा frontend) token पाने के लिए `username` और `password` भेजने में करेगा। + +{* ../../docs_src/security/tutorial001_an_py310.py hl[8] *} + +/// tip | सुझाव + +यहाँ `tokenUrl="token"` एक relative URL `token` को refer करता है जिसे हमने अभी तक बनाया नहीं है। क्योंकि यह relative URL है, यह `./token` के equivalent है। + +क्योंकि हम relative URL का उपयोग कर रहे हैं, अगर आपका API `https://example.com/` पर स्थित था, तो यह `https://example.com/token` को refer करेगा। लेकिन अगर आपका API `https://example.com/api/v1/` पर स्थित था, तो यह `https://example.com/api/v1/token` को refer करेगा। + +Relative URL का उपयोग करना महत्वपूर्ण है ताकि यह सुनिश्चित हो सके कि आपका application [Proxy के पीछे](../../advanced/behind-a-proxy.md) जैसे advanced use case में भी काम करता रहे। + +/// + +यह parameter उस endpoint / *path operation* को create नहीं करता, बल्कि declare करता है कि URL `/token` वही होगा जिसका उपयोग client को token पाने के लिए करना चाहिए। उस जानकारी का उपयोग OpenAPI में किया जाता है, और फिर interactive API documentation systems में। + +हम जल्द ही वास्तविक path operation भी बनाएँगे। + +/// note | नोट + +अगर आप बहुत strict "Pythonista" हैं, तो आपको parameter name `tokenUrl` की style `token_url` के बजाय पसंद न आए। + +ऐसा इसलिए है क्योंकि यह OpenAPI spec जैसा ही name उपयोग कर रहा है। ताकि अगर आपको इनमें से किसी भी security scheme के बारे में और अधिक जाँच करनी हो, तो आप बस इसे copy और paste करके इसके बारे में और जानकारी खोज सकें। + +/// + +`oauth2_scheme` variable `OAuth2PasswordBearer` का instance है, लेकिन यह एक "callable" भी है। + +इसे इस तरह call किया जा सकता है: + +```Python +oauth2_scheme(some, parameters) +``` + +तो, इसे `Depends` के साथ उपयोग किया जा सकता है। + +### इसका उपयोग करें { #use-it } + +अब आप उस `oauth2_scheme` को `Depends` के साथ dependency में pass कर सकते हैं। + +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} + +यह dependency एक `str` प्रदान करेगी जिसे *path operation function* के parameter `token` को assign किया जाता है। + +**FastAPI** जान जाएगा कि यह OpenAPI schema (और automatic API docs) में "security scheme" define करने के लिए इस dependency का उपयोग कर सकता है। + +/// note | तकनीकी विवरण + +**FastAPI** जान जाएगा कि यह OpenAPI में security scheme define करने के लिए `OAuth2PasswordBearer` class (जो dependency में declare की गई है) का उपयोग कर सकता है क्योंकि यह `fastapi.security.oauth2.OAuth2` से inherit करती है, जो बदले में `fastapi.security.base.SecurityBase` से inherit करती है। + +OpenAPI (और automatic API docs) के साथ integrate होने वाली सभी security utilities `SecurityBase` से inherit करती हैं, इसी तरह **FastAPI** जान सकता है कि उन्हें OpenAPI में कैसे integrate करना है। + +/// + +## यह क्या करता है { #what-it-does } + +यह request में उस `Authorization` header को खोजेगा, check करेगा कि value `Bearer ` plus कोई token है या नहीं, और token को `str` के रूप में return करेगा। + +अगर इसे `Authorization` header नहीं दिखता, या value में `Bearer ` token नहीं है, तो यह सीधे 401 status code error (`UNAUTHORIZED`) के साथ respond करेगा। + +Error return करने के लिए आपको यह भी check करने की आवश्यकता नहीं है कि token मौजूद है या नहीं। आप निश्चिंत हो सकते हैं कि अगर आपकी function execute होती है, तो उस token में एक `str` होगा। + +आप इसे अभी interactive docs में आज़मा सकते हैं: + + + +हम अभी token की validity verify नहीं कर रहे हैं, लेकिन यह पहले से ही एक शुरुआत है। + +## Recap { #recap } + +तो, केवल 3 या 4 अतिरिक्त lines में, आपके पास पहले से ही security का कुछ primitive form है। diff --git a/docs/hi/docs/tutorial/security/get-current-user.md b/docs/hi/docs/tutorial/security/get-current-user.md new file mode 100644 index 000000000..403d6e7d5 --- /dev/null +++ b/docs/hi/docs/tutorial/security/get-current-user.md @@ -0,0 +1,105 @@ +# Current User प्राप्त करें { #get-current-user } + +पिछले अध्याय में security system (जो dependency injection system पर आधारित है) *path operation function* को `str` के रूप में एक `token` दे रहा था: + +{* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} + +लेकिन वह अभी भी इतना उपयोगी नहीं है। + +आइए इसे हमें current user देने वाला बनाते हैं। + +## एक user model बनाएँ { #create-a-user-model } + +पहले, एक Pydantic user model बनाते हैं। + +जिस तरह हम bodies declare करने के लिए Pydantic का उपयोग करते हैं, उसी तरह हम इसे कहीं और भी उपयोग कर सकते हैं: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} + +## एक `get_current_user` dependency बनाएँ { #create-a-get-current-user-dependency } + +आइए एक dependency `get_current_user` बनाएँ। + +याद है कि dependencies की sub-dependencies हो सकती हैं? + +`get_current_user` के पास उसी `oauth2_scheme` के साथ एक dependency होगी जिसे हमने पहले बनाया था। + +ठीक वैसे ही जैसे हम पहले सीधे *path operation* में कर रहे थे, हमारी नई dependency `get_current_user` sub-dependency `oauth2_scheme` से `str` के रूप में एक `token` प्राप्त करेगी: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[25] *} + +## user प्राप्त करें { #get-the-user } + +`get_current_user` हमारे द्वारा बनाई गई एक (fake) utility function का उपयोग करेगी, जो token को `str` के रूप में लेती है और हमारा Pydantic `User` model लौटाती है: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[19:22,26:27] *} + +## current user inject करें { #inject-the-current-user } + +तो अब हम *path operation* में अपने `get_current_user` के साथ वही `Depends` उपयोग कर सकते हैं: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[31] *} + +ध्यान दें कि हम `current_user` का type Pydantic model `User` के रूप में declare करते हैं। + +यह function के अंदर completion और type checks में हमारी मदद करेगा। + +/// tip | टिप + +आपको याद होगा कि request bodies भी Pydantic models के साथ declare की जाती हैं। + +यहाँ **FastAPI** confuse नहीं होगा क्योंकि आप `Depends` का उपयोग कर रहे हैं। + +/// + +/// tip | टिप + +जिस तरह यह dependency system design किया गया है, वह हमें अलग-अलग dependencies (अलग-अलग "dependables") रखने देता है जो सभी एक `User` model लौटाती हैं। + +हम केवल एक dependency तक सीमित नहीं हैं जो उस type का data लौटा सकती है। + +/// + +## अन्य models { #other-models } + +अब आप *path operation functions* में सीधे current user प्राप्त कर सकते हैं और `Depends` का उपयोग करके **Dependency Injection** स्तर पर security mechanisms संभाल सकते हैं। + +और आप security requirements के लिए कोई भी model या data उपयोग कर सकते हैं (इस मामले में, Pydantic model `User`)। + +लेकिन आप किसी विशेष data model, class या type का उपयोग करने तक सीमित नहीं हैं। + +क्या आप अपने model में `id` और `email` रखना चाहते हैं और कोई `username` नहीं रखना चाहते? बिल्कुल। आप इन्हीं tools का उपयोग कर सकते हैं। + +क्या आप केवल एक `str` रखना चाहते हैं? या केवल एक `dict`? या सीधे database class model instance? सब कुछ उसी तरह काम करता है। + +असल में आपके application में login करने वाले users नहीं हैं, बल्कि robots, bots, या अन्य systems हैं, जिनके पास बस एक access token है? फिर भी, सब कुछ उसी तरह काम करता है। + +बस अपने application के लिए जिस भी प्रकार का model, जिस भी प्रकार की class, जिस भी प्रकार का database चाहिए, उसका उपयोग करें। **FastAPI** dependency injection system के साथ आपकी ज़रूरतें पूरी करता है। + +## Code size { #code-size } + +यह example verbose लग सकता है। ध्यान रखें कि हम security, data models, utility functions और *path operations* को उसी file में मिला रहे हैं। + +लेकिन यहाँ मुख्य बात है। + +security और dependency injection से जुड़ी चीज़ें एक बार लिखी जाती हैं। + +और आप इसे जितना चाहें उतना complex बना सकते हैं। फिर भी, यह केवल एक बार, एक ही जगह पर, पूरी flexibility के साथ लिखा जाता है। + +लेकिन आपके पास उसी security system का उपयोग करने वाले हजारों endpoints (*path operations*) हो सकते हैं। + +और वे सभी (या उनका कोई भी हिस्सा जिसे आप चाहें) इन dependencies या आपके द्वारा बनाई गई किसी भी अन्य dependencies को फिर से उपयोग करने का लाभ उठा सकते हैं। + +और ये सभी हजारों *path operations* सिर्फ 3 lines जितने छोटे हो सकते हैं: + +{* ../../docs_src/security/tutorial002_an_py310.py hl[30:32] *} + +## Recap { #recap } + +अब आप अपने *path operation function* में सीधे current user प्राप्त कर सकते हैं। + +हम पहले ही आधे रास्ते तक पहुँच चुके हैं। + +हमें बस user/client के लिए एक *path operation* जोड़ना है ताकि वह वास्तव में `username` और `password` भेज सके। + +वह आगे आता है। diff --git a/docs/hi/docs/tutorial/security/index.md b/docs/hi/docs/tutorial/security/index.md new file mode 100644 index 000000000..43fbd0a9b --- /dev/null +++ b/docs/hi/docs/tutorial/security/index.md @@ -0,0 +1,105 @@ +# Security { #security } + +security, authentication और authorization को handle करने के कई तरीके हैं। + +और यह सामान्यतः एक जटिल और "कठिन" विषय होता है। + +कई frameworks और systems में केवल security और authentication को handle करने में ही बहुत अधिक effort और code लग जाता है (कई मामलों में यह लिखे गए पूरे code का 50% या उससे अधिक हो सकता है)। + +**FastAPI** आपको **Security** से आसानी से, तेज़ी से, standard तरीके से निपटने में मदद करने के लिए कई tools प्रदान करता है, बिना सभी security specifications को पढ़ने और सीखने की ज़रूरत के। + +लेकिन पहले, आइए कुछ छोटे concepts देखते हैं। + +## जल्दी में हैं? { #in-a-hurry } + +अगर आपको इन terms की परवाह नहीं है और आपको बस username और password पर आधारित authentication के साथ security *अभी* जोड़नी है, तो अगले chapters पर जाएँ। + +## OAuth2 { #oauth2 } + +OAuth2 एक specification है जो authentication और authorization को handle करने के कई तरीके define करती है। + +यह काफ़ी विस्तृत specification है और कई जटिल use cases को cover करती है। + +इसमें "third party" का उपयोग करके authenticate करने के तरीके शामिल हैं। + +यही चीज़ अंदर से उन सभी systems में इस्तेमाल होती है जिनमें "login with Facebook, Google, X (Twitter), GitHub" होता है। + +### OAuth 1 { #oauth-1 } + +OAuth 1 भी था, जो OAuth2 से बहुत अलग और अधिक जटिल था, क्योंकि इसमें communication को encrypt करने के तरीके पर direct specifications शामिल थीं। + +आजकल यह बहुत लोकप्रिय या इस्तेमाल में नहीं है। + +OAuth2 यह specify नहीं करता कि communication को कैसे encrypt करना है, यह अपेक्षा करता है कि आपकी application HTTPS के साथ serve की जा रही हो। + +/// tip | सुझाव + +**deployment** वाले section में आप देखेंगे कि Traefik और Let's Encrypt का उपयोग करके HTTPS को मुफ्त में कैसे setup किया जाता है। + +/// + +## OpenID Connect { #openid-connect } + +OpenID Connect एक और specification है, जो **OAuth2** पर आधारित है। + +यह OAuth2 को बस extend करता है और कुछ ऐसी चीज़ें specify करता है जो OAuth2 में तुलनात्मक रूप से ambiguous हैं, ताकि इसे अधिक interoperable बनाया जा सके। + +उदाहरण के लिए, Google login OpenID Connect का उपयोग करता है (जो अंदर से OAuth2 का उपयोग करता है)। + +लेकिन Facebook login OpenID Connect को support नहीं करता। उसका अपना OAuth2 flavor है। + +### OpenID ("OpenID Connect" नहीं) { #openid-not-openid-connect } + +एक "OpenID" specification भी थी। उसने वही समस्या हल करने की कोशिश की जो **OpenID Connect** करता है, लेकिन वह OAuth2 पर आधारित नहीं थी। + +इसलिए, वह एक पूरा अतिरिक्त system था। + +आजकल यह बहुत लोकप्रिय या इस्तेमाल में नहीं है। + +## OpenAPI { #openapi } + +OpenAPI (पहले Swagger के नाम से जाना जाता था) APIs बनाने के लिए open specification है (अब Linux Foundation का हिस्सा)। + +**FastAPI** **OpenAPI** पर आधारित है। + +इसी वजह से कई automatic interactive documentation interfaces, code generation, आदि होना संभव होता है। + +OpenAPI कई security "schemes" define करने का तरीका देता है। + +इनका उपयोग करके, आप इन सभी standard-based tools का लाभ उठा सकते हैं, जिनमें ये interactive documentation systems भी शामिल हैं। + +OpenAPI निम्नलिखित security schemes define करता है: + +* `apiKey`: एक application-specific key जो यहाँ से आ सकती है: + * एक query parameter. + * एक header. + * एक cookie. +* `http`: standard HTTP authentication systems, जिनमें शामिल हैं: + * `bearer`: एक header `Authorization` जिसमें `Bearer ` plus एक token का value होता है। यह OAuth2 से inherited है। + * HTTP Basic authentication. + * HTTP Digest, आदि। +* `oauth2`: security handle करने के सभी OAuth2 तरीके (जिन्हें "flows" कहा जाता है)। + * इनमें से कई flows OAuth 2.0 authentication provider बनाने के लिए उपयुक्त हैं (जैसे Google, Facebook, X (Twitter), GitHub, आदि): + * `implicit` + * `clientCredentials` + * `authorizationCode` + * लेकिन एक specific "flow" है जिसे उसी application में सीधे authentication handle करने के लिए पूरी तरह इस्तेमाल किया जा सकता है: + * `password`: कुछ अगले chapters इसके examples cover करेंगे। +* `openIdConnect`: इसमें OAuth2 authentication data को automatically discover करने का तरीका होता है। + * यह automatic discovery वही है जो OpenID Connect specification में define की गई है। + +/// tip | सुझाव + +Google, Facebook, X (Twitter), GitHub, आदि जैसे अन्य authentication/authorization providers को integrate करना भी संभव और तुलनात्मक रूप से आसान है। + +सबसे जटिल समस्या उन जैसे authentication/authorization provider बनाना है, लेकिन **FastAPI** आपको इसे आसानी से करने के लिए tools देता है, और आपके लिए heavy lifting करता है। + +/// + +## **FastAPI** utilities { #fastapi-utilities } + +FastAPI इन security schemes में से प्रत्येक के लिए `fastapi.security` module में कई tools प्रदान करता है, जो इन security mechanisms का उपयोग आसान बनाते हैं। + +अगले chapters में आप देखेंगे कि **FastAPI** द्वारा प्रदान किए गए उन tools का उपयोग करके अपनी API में security कैसे जोड़ें। + +और आप यह भी देखेंगे कि यह interactive documentation system में automatically कैसे integrate हो जाता है। diff --git a/docs/hi/docs/tutorial/security/oauth2-jwt.md b/docs/hi/docs/tutorial/security/oauth2-jwt.md new file mode 100644 index 000000000..2066d8f5a --- /dev/null +++ b/docs/hi/docs/tutorial/security/oauth2-jwt.md @@ -0,0 +1,277 @@ +# Password के साथ OAuth2 (और hashing), JWT tokens के साथ Bearer { #oauth2-with-password-and-hashing-bearer-with-jwt-tokens } + +अब जब हमारे पास पूरा security flow है, तो आइए JWT tokens और secure password hashing का उपयोग करके application को वास्तव में secure बनाते हैं। + +यह code ऐसा है जिसे आप अपनी application में सच में उपयोग कर सकते हैं, password hashes को अपने database में save कर सकते हैं, आदि। + +हम पिछले chapter में जहाँ छोड़ा था, वहीं से शुरू करेंगे और उसे आगे बढ़ाएँगे। + +## JWT के बारे में { #about-jwt } + +JWT का मतलब है "JSON Web Tokens"। + +यह एक JSON object को बिना spaces वाली लंबी dense string में codify करने का standard है। यह ऐसा दिखता है: + +``` +eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c +``` + +यह encrypted नहीं है, इसलिए कोई भी contents से जानकारी वापस प्राप्त कर सकता है। + +लेकिन यह signed है। इसलिए, जब आपको कोई token मिलता है जिसे आपने issue किया था, तो आप verify कर सकते हैं कि उसे आपने ही issue किया था। + +इस तरह, आप एक token बना सकते हैं जिसकी expiration, मान लीजिए, 1 week हो। और फिर जब user अगले दिन token के साथ वापस आता है, तो आपको पता होता है कि वह user अभी भी आपके system में logged in है। + +एक week के बाद, token expired हो जाएगा और user authorized नहीं होगा और नया token पाने के लिए उसे फिर से sign in करना होगा। और अगर user (या कोई third party) expiration बदलने के लिए token को modify करने की कोशिश करे, तो आप इसे पता लगा पाएँगे, क्योंकि signatures match नहीं होंगे। + +अगर आप JWT tokens के साथ प्रयोग करना चाहते हैं और देखना चाहते हैं कि वे कैसे काम करते हैं, तो [https://jwt.io](https://jwt.io/) देखें। + +## `PyJWT` install करें { #install-pyjwt } + +Python में JWT tokens generate और verify करने के लिए हमें `PyJWT` install करना होगा। + +सुनिश्चित करें कि आप एक [virtual environment](../../virtual-environments.md) बनाएँ, उसे activate करें, और फिर `pyjwt` install करें: + +
+ +```console +$ pip install pyjwt + +---> 100% +``` + +
+ +/// note | नोट + +अगर आप RSA या ECDSA जैसे digital signature algorithms का उपयोग करने की योजना बना रहे हैं, तो आपको cryptography library dependency `pyjwt[crypto]` install करनी चाहिए। + +आप इसके बारे में [PyJWT Installation docs](https://pyjwt.readthedocs.io/en/latest/installation.html) में और पढ़ सकते हैं। + +/// + +## Password hashing { #password-hashing } + +"Hashing" का मतलब है किसी content (इस मामले में password) को bytes के sequence (बस एक string) में बदलना, जो बेकार/असमझ text जैसा दिखता है। + +जब भी आप बिल्कुल वही content (बिल्कुल वही password) pass करते हैं, आपको बिल्कुल वही gibberish मिलता है। + +लेकिन आप उस gibberish से वापस password में convert नहीं कर सकते। + +### Password hashing क्यों उपयोग करें { #why-use-password-hashing } + +अगर आपका database चोरी हो जाता है, तो चोर के पास आपके users के plaintext passwords नहीं होंगे, केवल hashes होंगे। + +इसलिए, चोर उस password को किसी दूसरे system में उपयोग करने की कोशिश नहीं कर पाएगा (क्योंकि कई users हर जगह वही password उपयोग करते हैं, यह खतरनाक होगा)। + +## `pwdlib` install करें { #install-pwdlib } + +pwdlib password hashes संभालने के लिए एक शानदार Python package है। + +यह कई secure hashing algorithms और उनके साथ काम करने के लिए utilities support करता है। + +Recommended algorithm "Argon2" है। + +सुनिश्चित करें कि आप एक [virtual environment](../../virtual-environments.md) बनाएँ, उसे activate करें, और फिर Argon2 के साथ pwdlib install करें: + +
+ +```console +$ pip install "pwdlib[argon2]" + +---> 100% +``` + +
+ +/// tip | सुझाव + +`pwdlib` के साथ, आप इसे इस तरह configure भी कर सकते हैं कि यह **Django**, **Flask** security plug-in या कई अन्य द्वारा बनाए गए passwords read कर सके। + +तो, उदाहरण के लिए, आप एक database में Django application का वही data FastAPI application के साथ share कर पाएँगे। या उसी database का उपयोग करते हुए धीरे-धीरे Django application को migrate कर पाएँगे। + +और आपके users एक ही समय में आपकी Django app या आपकी **FastAPI** app से login कर पाएँगे। + +/// + +## Passwords को hash और verify करें { #hash-and-verify-the-passwords } + +`pwdlib` से वे tools import करें जिनकी हमें ज़रूरत है। + +Recommended settings के साथ एक PasswordHash instance बनाएँ - इसका उपयोग passwords को hash और verify करने के लिए किया जाएगा। + +/// tip | सुझाव + +pwdlib bcrypt hashing algorithm को भी support करता है लेकिन legacy algorithms शामिल नहीं करता - outdated hashes के साथ काम करने के लिए passlib library का उपयोग करना recommended है। + +उदाहरण के लिए, आप इसका उपयोग किसी दूसरे system (जैसे Django) द्वारा generate किए गए passwords read और verify करने के लिए कर सकते हैं, लेकिन किसी भी नए passwords को Argon2 या Bcrypt जैसे अलग algorithm से hash कर सकते हैं। + +और एक ही समय में उन सभी के साथ compatible रह सकते हैं। + +/// + +User से आने वाले password को hash करने के लिए एक utility function बनाएँ। + +और एक और utility बनाएँ जो verify करे कि received password stored hash से match करता है या नहीं। + +और एक और utility बनाएँ जो authenticate करे और user return करे। + +{* ../../docs_src/security/tutorial004_an_py310.py hl[8,49,51,58:59,62:63,72:79] *} + +जब `authenticate_user` को ऐसे username के साथ call किया जाता है जो database में मौजूद नहीं है, तब भी हम dummy hash के against `verify_password` चलाते हैं। + +यह सुनिश्चित करता है कि username valid हो या न हो, endpoint response देने में लगभग समान समय ले, जिससे **timing attacks** रोके जा सकें जिनका उपयोग मौजूदा usernames enumerate करने के लिए किया जा सकता है। + +/// note | नोट + +अगर आप नए (fake) database `fake_users_db` को check करेंगे, तो आप देखेंगे कि hashed password अब कैसा दिखता है: `"$argon2id$v=19$m=65536,t=3,p=4$wagCPXjifgvUFBzq4hqe3w$CYaIb8sB+wtD+Vu/P4uod1+Qof8h+1g7bbDlBID48Rc"`। + +/// + +## JWT tokens संभालें { #handle-jwt-tokens } + +Installed modules import करें। + +एक random secret key बनाएँ जिसका उपयोग JWT tokens sign करने के लिए किया जाएगा। + +Secure random secret key generate करने के लिए command उपयोग करें: + +
+ +```console +$ openssl rand -hex 32 + +09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7 +``` + +
+ +और output को variable `SECRET_KEY` में copy करें (example वाला उपयोग न करें)। + +JWT token sign करने के लिए उपयोग किए गए algorithm के साथ एक variable `ALGORITHM` बनाएँ और इसे `"HS256"` पर set करें। + +Token की expiration के लिए एक variable बनाएँ। + +एक Pydantic Model define करें जिसका उपयोग response के लिए token endpoint में किया जाएगा। + +नया access token generate करने के लिए एक utility function बनाएँ। + +{* ../../docs_src/security/tutorial004_an_py310.py hl[4,7,13:15,29:31,82:90] *} + +## Dependencies update करें { #update-the-dependencies } + +`get_current_user` को update करें ताकि वह पहले जैसा ही token receive करे, लेकिन इस बार JWT tokens का उपयोग करते हुए। + +Received token को decode करें, verify करें, और current user return करें। + +अगर token invalid है, तो तुरंत HTTP error return करें। + +{* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} + +## `/token` *path operation* update करें { #update-the-token-path-operation } + +Token की expiration time के साथ एक `timedelta` बनाएँ। + +एक वास्तविक JWT access token बनाएँ और उसे return करें। + +{* ../../docs_src/security/tutorial004_an_py310.py hl[121:136] *} + +### JWT "subject" `sub` के बारे में technical details { #technical-details-about-the-jwt-subject-sub } + +JWT specification कहता है कि token के subject के साथ एक key `sub` होती है। + +इसका उपयोग करना optional है, लेकिन यही वह जगह है जहाँ आप user की identification रखेंगे, इसलिए हम इसे यहाँ उपयोग कर रहे हैं। + +JWT का उपयोग user की पहचान करने और उन्हें आपकी API पर सीधे operations perform करने की अनुमति देने के अलावा अन्य चीज़ों के लिए भी किया जा सकता है। + +उदाहरण के लिए, आप एक "car" या एक "blog post" की पहचान कर सकते हैं। + +फिर आप उस entity के बारे में permissions जोड़ सकते हैं, जैसे "drive" (car के लिए) या "edit" (blog के लिए)। + +और फिर, आप वह JWT token किसी user (या bot) को दे सकते हैं, और वे उन actions को perform करने के लिए इसका उपयोग कर सकते हैं (car drive करना, या blog post edit करना), बिना account की ज़रूरत के, केवल उस JWT token के साथ जिसे आपकी API ने इसके लिए generate किया है। + +इन ideas का उपयोग करके, JWT का उपयोग कहीं अधिक sophisticated scenarios के लिए किया जा सकता है। + +इन cases में, उन entities में से कई की same ID हो सकती है, मान लीजिए `foo` (एक user `foo`, एक car `foo`, और एक blog post `foo`)। + +इसलिए, ID collisions से बचने के लिए, user के लिए JWT token बनाते समय, आप `sub` key के value के आगे prefix जोड़ सकते हैं, जैसे `username:`। इसलिए, इस example में, `sub` का value हो सकता था: `username:johndoe`। + +ध्यान रखने वाली महत्वपूर्ण बात यह है कि `sub` key के पास पूरी application में unique identifier होना चाहिए, और यह एक string होना चाहिए। + +## इसे check करें { #check-it } + +Server run करें और docs पर जाएँ: [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs)। + +आप user interface ऐसा देखेंगे: + + + +Application को पहले की तरह ही authorize करें। + +Credentials का उपयोग करते हुए: + +Username: `johndoe` +Password: `secret` + +/// tip | सुझाव + +ध्यान दें कि code में कहीं भी plaintext password "`secret`" नहीं है, हमारे पास केवल hashed version है। + +/// + + + +Endpoint `/users/me/` call करें, आपको response इस तरह मिलेगा: + +```JSON +{ + "username": "johndoe", + "email": "johndoe@example.com", + "full_name": "John Doe", + "disabled": false +} +``` + + + +अगर आप developer tools खोलते हैं, तो आप देख सकते हैं कि भेजे गए data में केवल token शामिल है, password केवल पहले request में user को authenticate करने और वह access token पाने के लिए भेजा जाता है, लेकिन उसके बाद नहीं: + + + +/// note | नोट + +`Authorization` header पर ध्यान दें, जिसका value `Bearer ` से शुरू होता है। + +/// + +## `scopes` के साथ advanced उपयोग { #advanced-usage-with-scopes } + +OAuth2 में "scopes" की धारणा है। + +आप उनका उपयोग JWT token में permissions का specific set जोड़ने के लिए कर सकते हैं। + +फिर आप यह token सीधे किसी user या third party को दे सकते हैं, ताकि वे restrictions के set के साथ आपकी API से interact कर सकें। + +आप बाद में **Advanced User Guide** में सीख सकते हैं कि उनका उपयोग कैसे करें और वे **FastAPI** में कैसे integrated हैं। + +## Recap { #recap } + +अब तक आपने जो देखा है, उससे आप OAuth2 और JWT जैसे standards का उपयोग करके एक secure **FastAPI** application setup कर सकते हैं। + +लगभग किसी भी framework में security संभालना काफ़ी जल्दी एक जटिल विषय बन जाता है। + +कई packages जो इसे बहुत सरल बनाते हैं, उन्हें data model, database, और available features के साथ कई compromises करने पड़ते हैं। और इनमें से कुछ packages जो चीज़ों को बहुत अधिक सरल बना देते हैं, उनके अंदर वास्तव में security flaws होते हैं। + +--- + +**FastAPI** किसी भी database, data model या tool के साथ कोई compromise नहीं करता। + +यह आपको उन चीज़ों को चुनने की पूरी flexibility देता है जो आपके project के लिए सबसे अच्छी हों। + +और आप सीधे कई well maintained और widely used packages जैसे `pwdlib` और `PyJWT` का उपयोग कर सकते हैं, क्योंकि **FastAPI** external packages integrate करने के लिए किसी complex mechanism की मांग नहीं करता। + +लेकिन यह आपको process को जितना संभव हो उतना सरल बनाने के लिए tools देता है, बिना flexibility, robustness, या security से compromise किए। + +और आप OAuth2 जैसे secure, standard protocols को अपेक्षाकृत simple तरीके से उपयोग और implement कर सकते हैं। + +आप **Advanced User Guide** में और सीख सकते हैं कि अधिक fine-grained permission system के लिए OAuth2 "scopes" का उपयोग कैसे करें, इन्हीं standards का पालन करते हुए। Scopes के साथ OAuth2 वह mechanism है जिसका उपयोग कई बड़े authentication providers, जैसे Facebook, Google, GitHub, Microsoft, X (Twitter), आदि करते हैं, ताकि third party applications को अपने users की ओर से उनकी APIs के साथ interact करने के लिए authorize किया जा सके।