Compare commits

...

6 Commits

Author SHA1 Message Date
RadinPirouz
4f081c9d3a fastapi: updated file doc 2026-05-13 17:15:18 +03:30
RadinPirouz
5b2723718f update fastapi life span doc 2026-05-13 17:06:09 +03:30
RadinPirouz
97814b3b57 update fastapi get doc 2026-05-13 17:04:08 +03:30
RadinPirouz
2222dc63a1 updated simple route doc 2026-05-13 17:03:08 +03:30
RadinPirouz
7c08e19545 Updated Some Doc 2026-05-13 17:00:43 +03:30
RadinPirouz
4cc57be794 request lib 2026-02-08 22:08:05 +03:30
8 changed files with 2484 additions and 354 deletions

View File

@@ -1,12 +1,22 @@
# FastAPI Simple Route Example
This document demonstrates how to create a basic FastAPI application with a single HTTP route and how to run it using `uvicorn`, which is the default and recommended ASGI server for FastAPI.
## Overview
This document explains how to create a basic FastAPI application with a single HTTP route and how to run it using `uvicorn`.
FastAPI is an ASGI web framework, and `uvicorn` is commonly used as the ASGI server to run FastAPI applications.
---
## Create a Simple FastAPI Application
# 1. Create a Simple FastAPI Application
Create a Python file named `main.py` and add the following content:
Create a Python file named:
```text
main.py
```
Add the following code:
```python
from fastapi import FastAPI
@@ -19,72 +29,243 @@ def home_dir():
return {"message": "Home Page"}
```
### Explanation
---
* `FastAPI()` initializes the application instance.
* `@app.get("/")` registers an HTTP GET endpoint at the root path (`/`).
* The `home_dir` function is the request handler and returns a JSON response.
* FastAPI automatically handles JSON serialization and response headers.
# 2. Code Explanation
## Import FastAPI
```python
from fastapi import FastAPI
```
This imports the `FastAPI` class from the FastAPI package.
---
## Running the Application
## Create the Application Instance
FastAPI applications are typically run using **uvicorn**, an ASGI server designed for high performance.
```python
app = FastAPI()
```
### Option 1: Run Using FastAPI CLI (Development Mode)
This creates the main FastAPI application instance.
FastAPI provides a development-friendly CLI wrapper that uses `uvicorn` internally:
The variable name `app` is important because it is later used by `uvicorn` when starting the server.
---
## Define a GET Route
```python
@app.get("/")
def home_dir():
return {"message": "Home Page"}
```
This creates an HTTP `GET` endpoint at the root path:
```http
GET /
```
When a user sends a request to `/`, the `home_dir` function is executed.
The function returns a Python dictionary:
```python
{"message": "Home Page"}
```
FastAPI automatically converts this dictionary into a JSON response.
---
# 3. Running the Application
FastAPI applications are usually run using `uvicorn`.
---
## Option 1: Run Using FastAPI CLI
You can run the application in development mode using:
```bash
fastapi dev main.py
```
This command:
This command starts the FastAPI application in development mode.
* Starts the application in development mode
* Enables auto-reload on code changes
* Automatically binds to a local development interface
It is useful during local development because it supports automatic reload when the source code changes.
---
### Option 2: Run Directly with Uvicorn (Recommended)
## Option 2: Run Directly with Uvicorn
For explicit control over runtime configuration, run the application directly with `uvicorn`:
You can also run the application directly using `uvicorn`:
```bash
uvicorn main:app --reload --host 0.0.0.0 --port 1234
```
#### Command Breakdown
* `main` → Python file name (without `.py`)
* `app` → FastAPI application instance
* `--reload` → Automatically reloads the server on code changes (development only)
* `--host 0.0.0.0` → Exposes the service on all network interfaces
* `--port 1234` → Custom application port
This is the more explicit and commonly used method.
---
## Accessing the Application
# 4. Uvicorn Command Breakdown
Once running, the application will be available at:
```bash
uvicorn main:app --reload --host 0.0.0.0 --port 1234
```
* API Endpoint:
`http://localhost:1234/`
## `uvicorn`
* Interactive API Docs (Swagger UI):
`http://localhost:1234/docs`
Starts the ASGI server.
* Alternative API Docs (ReDoc):
`http://localhost:1234/redoc`
## `main`
Refers to the Python file name:
```text
main.py
```
You write `main`, not `main.py`.
## `app`
Refers to the FastAPI application instance:
```python
app = FastAPI()
```
## `--reload`
Automatically restarts the server when code changes.
This should only be used in development.
## `--host 0.0.0.0`
Makes the application listen on all available network interfaces.
This is useful when running inside Docker, virtual machines, or remote servers.
## `--port 1234`
Runs the application on port `1234`.
---
## Best Practices
# 5. Accessing the Application
* Use `--reload` only in development environments
* In production, run `uvicorn` behind a process manager (e.g., systemd, Docker, Kubernetes)
* Explicitly define host and port for containerized and cloud deployments
* Keep the application entry point (`main:app`) consistent across environments
After starting the server, the application will be available at:
```text
http://localhost:1234/
```
The response will be:
```json
{
"message": "Home Page"
}
```
---
# 6. Interactive API Documentation
FastAPI automatically generates API documentation.
## Swagger UI
```text
http://localhost:1234/docs
```
Swagger UI allows you to test API endpoints directly from the browser.
## ReDoc
```text
http://localhost:1234/redoc
```
ReDoc provides a clean documentation view for the API.
---
# 7. Complete Example
```python
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def home_dir():
return {"message": "Home Page"}
```
Run it with:
```bash
uvicorn main:app --reload --host 0.0.0.0 --port 1234
```
---
# 8. Best Practices
Use `--reload` only during development.
Use a consistent application entry point such as:
```text
main:app
```
Explicitly define the host and port in Docker, cloud, or server environments.
Use `0.0.0.0` when the application needs to be reachable from outside the local machine.
Use `127.0.0.1` or `localhost` when the application should only be accessible locally.
Do not expose development servers directly to the internet.
In production, run FastAPI behind a proper process manager, reverse proxy, or container orchestration platform.
---
# 9. DevOps Production Note
The following command is suitable for local development:
```bash
uvicorn main:app --reload --host 0.0.0.0 --port 1234
```
For production, avoid using `--reload`.
A typical production setup may include:
```text
FastAPI
Uvicorn or Gunicorn with Uvicorn workers
Nginx or Traefik
Docker or Kubernetes
Logging and monitoring
Health checks
Environment-based configuration
```
Example production-style command:
```bash
uvicorn main:app --host 0.0.0.0 --port 1234
```

View File

@@ -1,10 +1,14 @@
# FastAPI GET Endpoints and JSON Responses
This document demonstrates how to define multiple **GET endpoints** in FastAPI, return JSON responses, and use **path parameters** to retrieve specific data from an in-memory dataset.
## Overview
This document explains how to create multiple `GET` endpoints in FastAPI, return JSON responses, and use path parameters to retrieve specific data from an in-memory dataset.
The example uses a simple list of users to simulate a database.
---
## Example Application
# 1. Example Application
Create or update `main.py` with the following content:
@@ -35,24 +39,38 @@ def get_user_by_name(name_input: str):
for item in users:
if item["name"] == name_input:
return {"information": item}
return {"message": "User not found"}
```
---
## Code Overview
### Application Initialization
# 2. Application Initialization
```python
app = FastAPI()
```
Initializes the FastAPI application instance.
This creates the main FastAPI application instance.
The variable `app` is used by `uvicorn` when starting the service.
Example:
```bash
uvicorn main:app --reload
```
In `main:app`:
```text
main = Python file name
app = FastAPI application instance
```
---
### In-Memory Data Store
# 3. In-Memory Data Store
```python
users = [
@@ -62,21 +80,64 @@ users = [
]
```
* Simulates a database using a Python list
* Each user is represented as a JSON-compatible dictionary
* Suitable for development and testing purposes
This list is used as temporary storage.
Each user is represented as a Python dictionary.
FastAPI can automatically convert these dictionaries into JSON responses.
Example Python object:
```python
{"name": "abbas", "age": 20}
```
Example JSON response:
```json
{
"name": "abbas",
"age": 20
}
```
## Important Note
This in-memory list is only suitable for learning, development, and testing.
If the application restarts, the data will be reset.
For production, use a persistent database such as PostgreSQL, MySQL, MongoDB, or another database system.
---
## Defined Endpoints
# 4. Defined Endpoints
### Root Endpoint
The application defines three `GET` endpoints:
```http
GET /
GET /users
GET /user/{name_input}
```
---
# 5. Root Endpoint
```python
@app.get("/")
def root_dir():
return {"message": "API is working"}
```
This endpoint is available at:
```http
GET /
```
**Response:**
It returns a simple JSON response:
```json
{
@@ -84,43 +145,96 @@ GET /
}
```
Used as a health check or readiness probe.
This type of endpoint is commonly used as a simple health check.
For example, load balancers, monitoring systems, or Kubernetes probes can use it to check whether the API is reachable.
---
### Get All Users
# 6. Get All Users Endpoint
```python
@app.get("/users")
def get_users():
return users
```
This endpoint is available at:
```http
GET /users
```
**Response:**
It returns the full list of users.
Example response:
```json
[
{"name": "abbas", "age": 20},
{"name": "mmd", "age": 37},
{"name": "asghar", "age": 19}
{
"name": "abbas",
"age": 20
},
{
"name": "mmd",
"age": 37
},
{
"name": "asghar",
"age": 19
}
]
```
Returns the full list of users as JSON.
FastAPI automatically serializes the Python list into a JSON array.
---
### Get User by Name (Path Parameter)
# 7. Get User by Name Endpoint
```python
@app.get("/user/{name_input}")
def get_user_by_name(name_input: str):
for item in users:
if item["name"] == name_input:
return {"information": item}
return {"message": "User not found"}
```
This endpoint is available at:
```http
GET /user/{name_input}
```
**Example Request:**
The `{name_input}` part is a path parameter.
Example request:
```http
GET /user/abbas
```
**Successful Response:**
In this request, FastAPI assigns:
```python
name_input = "abbas"
```
The function then searches the `users` list for a user whose name matches the input.
---
# 8. Successful Response Example
Request:
```http
GET /user/abbas
```
Response:
```json
{
@@ -131,7 +245,17 @@ GET /user/abbas
}
```
**Failure Response:**
---
# 9. Failure Response Example
Request:
```http
GET /user/ali
```
Response:
```json
{
@@ -139,31 +263,304 @@ GET /user/abbas
}
```
---
In the current simple version, the API returns a normal JSON message even when the user does not exist.
## Path Parameters
* `name_input` is a dynamic path parameter
* Automatically validated and converted to `str` by FastAPI
* Used to filter data at runtime
However, in a real API, it is better to return a proper `404 Not Found` response.
---
## Running the Application
# 10. Path Parameters
Use `uvicorn` to start the service:
A path parameter is a dynamic part of the URL.
In this route:
```python
@app.get("/user/{name_input}")
```
`name_input` is a path parameter.
Example:
```http
GET /user/mmd
```
FastAPI extracts the value from the URL and passes it to the function:
```python
def get_user_by_name(name_input: str):
```
Because `name_input` is defined as a string:
```python
name_input: str
```
FastAPI validates it as a string.
---
# 11. Better Version with HTTPException
The previous version works, but it does not return the correct HTTP status code when a user is not found.
A better version uses `HTTPException`.
```python
from fastapi import FastAPI, HTTPException, status
app = FastAPI()
users = [
{"name": "abbas", "age": 20},
{"name": "mmd", "age": 37},
{"name": "asghar", "age": 19},
]
@app.get("/")
def root_dir():
return {"message": "API is working"}
@app.get("/users")
def get_users():
return users
@app.get("/user/{name_input}")
def get_user_by_name(name_input: str):
for item in users:
if item["name"] == name_input:
return {"information": item}
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found"
)
```
---
# 12. Improved Failure Response
Request:
```http
GET /user/ali
```
Response:
```json
{
"detail": "User not found"
}
```
HTTP status code:
```http
404 Not Found
```
This is better because the API response now correctly tells the client that the requested resource does not exist.
---
# 13. Running the Application
Start the FastAPI application using `uvicorn`:
```bash
uvicorn main:app --reload
```
The application will be available at:
```text
http://localhost:8000
```
---
## Best Practices
# 14. Accessing the Endpoints
* Use structured JSON responses (`key: value`) instead of tuples
* Validate user input when moving beyond in-memory data
* Replace in-memory storage with a database for production
* Use proper HTTP status codes (`404`, `200`) in real-world APIs
* Separate routing, models, and business logic as the project grows
Root endpoint:
```text
http://localhost:8000/
```
Get all users:
```text
http://localhost:8000/users
```
Get user by name:
```text
http://localhost:8000/user/abbas
```
Interactive API documentation:
```text
http://localhost:8000/docs
```
Alternative API documentation:
```text
http://localhost:8000/redoc
```
---
# 15. Testing with curl
## Test Root Endpoint
```bash
curl http://localhost:8000/
```
Response:
```json
{
"message": "API is working"
}
```
## Test Get All Users
```bash
curl http://localhost:8000/users
```
Response:
```json
[
{
"name": "abbas",
"age": 20
},
{
"name": "mmd",
"age": 37
},
{
"name": "asghar",
"age": 19
}
]
```
## Test Get User by Name
```bash
curl http://localhost:8000/user/abbas
```
Response:
```json
{
"information": {
"name": "abbas",
"age": 20
}
}
```
## Test User Not Found
```bash
curl http://localhost:8000/user/ali
```
Response:
```json
{
"detail": "User not found"
}
```
---
# 16. Complete Recommended Version
```python
from fastapi import FastAPI, HTTPException, status
app = FastAPI()
users = [
{"name": "abbas", "age": 20},
{"name": "mmd", "age": 37},
{"name": "asghar", "age": 19},
]
@app.get("/")
def root_dir():
return {"message": "API is working"}
@app.get("/users")
def get_users():
return users
@app.get("/user/{name_input}")
def get_user_by_name(name_input: str):
for item in users:
if item["name"] == name_input:
return {"information": item}
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found"
)
```
---
# 17. Best Practices
Use `GET` endpoints only for retrieving data.
Do not use `GET` requests to create, update, or delete resources.
Return structured JSON responses.
Use proper HTTP status codes.
Use `404 Not Found` when a requested resource does not exist.
Use `200 OK` when the request is successful.
Replace in-memory lists with a real database in production.
Keep route names clear and consistent.
Use plural naming for collection endpoints, such as:
```http
GET /users
```
Use specific resource endpoints for single items, such as:
```http
GET /users/{username}
```
As the project grows, separate code into different files for routes, models, services, and database logic.

View File

@@ -1,12 +1,19 @@
# FastAPI POST Endpoint and JSON Input
This section demonstrates how to handle **POST requests** in FastAPI to create new resources using request data and return JSON responses.
## Overview
This document explains how to create a `POST` endpoint in FastAPI for adding new users. It covers two approaches:
1. Sending input as query parameters
2. Sending input as a JSON request body using a Pydantic model
For real API development, the Pydantic model approach is recommended because it provides a cleaner structure, better validation, and more realistic request handling.
---
## Example Application (POST Request)
# 1. Example Application Using Query Parameters
Extend `main.py` with the following code:
Create or update `main.py` with the following code:
```python
from fastapi import FastAPI
@@ -32,59 +39,154 @@ def create_user(name: str, age: int):
return {"msg": "User created successfully"}
```
---
## Code Overview
### POST Endpoint Definition
## Explanation
```python
@app.post("/new_user")
def create_user(name: str, age: int):
```
* Registers an HTTP **POST** endpoint at `/new_user`
* Accepts input parameters:
This registers a `POST` endpoint at:
* `name` → string
* `age` → integer
* FastAPI automatically validates input types
---
### Creating a New Resource
```python
new_user = {"name": name, "age": age}
users.append(new_user)
```http
POST /new_user
```
* Constructs a new user object
* Appends it to the in-memory `users` list
* Simulates creating a record in a database
---
### JSON Response
The endpoint receives two parameters:
```python
return {"msg": "User created successfully"}
name: str
age: int
```
* Returns a structured JSON response
* Automatically serialized by FastAPI
---
FastAPI automatically validates the input types. If `age` is not an integer, FastAPI returns a validation error.
## Example Request
### Using `curl`
```bash
curl -X POST "http://localhost:8000/new_user?name=ali&age=25"
```
### Response
## Example Response
```json
{
"msg": "User created successfully"
}
```
## Important Note
In this version, the data is sent through query parameters, not as a JSON body.
This is acceptable for simple testing, but it is not the best practice for real APIs that create resources.
---
# 2. Recommended Application Using JSON Body
A better approach is to define a Pydantic model and receive the user data as JSON.
```python
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class User(BaseModel):
name: str
age: int
users = [
{"name": "abbas", "age": 20},
{"name": "mmd", "age": 37},
{"name": "asghar", "age": 19},
]
@app.get("/")
def home_page():
return {"msg": "API is working"}
@app.post("/new_user")
def create_user(user: User):
new_user = {"name": user.name, "age": user.age}
users.append(new_user)
return {"msg": "User created successfully"}
```
## Explanation
```python
class User(BaseModel):
name: str
age: int
```
This creates a request model named `User`.
The model defines the expected structure of the JSON input:
```json
{
"name": "ali",
"age": 25
}
```
FastAPI uses this model to:
Validate incoming data
Convert JSON into a Python object
Generate automatic API documentation
Return useful validation errors when input is invalid
---
# 3. POST Endpoint Definition
```python
@app.post("/new_user")
def create_user(user: User):
```
This creates a `POST` endpoint at:
```http
POST /new_user
```
The endpoint expects a JSON request body matching the `User` model.
---
# 4. Creating a New Resource
```python
new_user = {"name": user.name, "age": user.age}
users.append(new_user)
```
This code creates a new dictionary using the received request data and appends it to the `users` list.
The `users` list acts as temporary in-memory storage.
This simulates inserting a new record into a database.
---
# 5. Returning a JSON Response
```python
return {"msg": "User created successfully"}
```
FastAPI automatically converts the returned dictionary into a JSON response.
Example response:
```json
{
@@ -94,34 +196,174 @@ curl -X POST "http://localhost:8000/new_user?name=ali&age=25"
---
## Verifying the Result
# 6. Example Request Using curl
After creating a user, retrieve the updated list:
```bash
curl -X POST "http://localhost:8000/new_user" \
-H "Content-Type: application/json" \
-d '{"name": "ali", "age": 25}'
```
## Response
```json
{
"msg": "User created successfully"
}
```
---
# 7. Verifying the Result
To verify that the user was added, you should also define a `GET /users` endpoint.
```python
@app.get("/users")
def get_users():
return users
```
Then send this request:
```http
GET /users
```
Response will now include the newly added user.
Example response:
```json
[
{
"name": "abbas",
"age": 20
},
{
"name": "mmd",
"age": 37
},
{
"name": "asghar",
"age": 19
},
{
"name": "ali",
"age": 25
}
]
```
---
## Running the Application
# 8. Complete Recommended Version
Start the FastAPI service using `uvicorn`:
```python
from fastapi import FastAPI, status
from pydantic import BaseModel
app = FastAPI()
class User(BaseModel):
name: str
age: int
users = [
{"name": "abbas", "age": 20},
{"name": "mmd", "age": 37},
{"name": "asghar", "age": 19},
]
@app.get("/")
def home_page():
return {"msg": "API is working"}
@app.get("/users")
def get_users():
return users
@app.post("/new_user", status_code=status.HTTP_201_CREATED)
def create_user(user: User):
new_user = {"name": user.name, "age": user.age}
users.append(new_user)
return {
"msg": "User created successfully",
"user": new_user
}
```
---
# 9. Running the Application
Start the FastAPI application using `uvicorn`:
```bash
uvicorn main:app --reload
```
The API will run at:
```text
http://localhost:8000
```
Interactive API documentation will be available at:
```text
http://localhost:8000/docs
```
---
## Best Practices
# 10. Best Practices
* POST requests should be used to create resources
* Avoid modifying in-memory data in production environments
* Use request bodies with Pydantic models instead of query parameters for real APIs
* Return appropriate HTTP status codes (`201 Created`)
* Validate and sanitize all client-provided input
* Replace in-memory storage with persistent databases
Use `POST` requests when creating new resources.
Use Pydantic models for request bodies instead of query parameters.
Return proper HTTP status codes, such as:
```http
201 Created
```
Do not use in-memory lists for production data storage.
Use a real database such as PostgreSQL, MySQL, or MongoDB in production.
Validate and sanitize all client-provided input.
Keep model names clear and professional. For example, use `User` instead of `user_class`.
Return meaningful responses that include the created resource when useful.
Use `/docs` to test and verify API behavior during development.
---
# 11. Production Note for DevOps
The in-memory `users` list is reset every time the application restarts. In production environments, application data must be stored in a persistent database.
For production deployment, the FastAPI application should usually run behind a process manager and reverse proxy, such as:
```text
Gunicorn / Uvicorn workers
Nginx or Traefik
Docker or Kubernetes
PostgreSQL or another persistent database
```
The development command:
```bash
uvicorn main:app --reload
```
should not be used in production because `--reload` is intended only for local development.

View File

@@ -1,122 +0,0 @@
# FastAPI JSONResponse (Explicit JSON Responses)
This document demonstrates how to return **explicit JSON responses** in FastAPI using `JSONResponse`.
While FastAPI automatically serializes dictionaries to JSON, `JSONResponse` is useful when you need **full control** over the response.
---
## Example Application
Create or update `main.py` with the following content:
```python
from fastapi import FastAPI, status
from fastapi.responses import JSONResponse
app = FastAPI()
@app.get("/")
def home():
return JSONResponse(
content={"msg": "API is working"},
status_code=status.HTTP_200_OK
)
```
---
## Why Use `JSONResponse`
FastAPI automatically converts Python dictionaries into JSON responses.
However, `JSONResponse` is useful when you need to:
* Explicitly control the response type
* Set custom status codes dynamically
* Customize headers
* Return non-standard JSON structures
* Override default response behavior
---
## Response Behavior
### Endpoint
```http
GET /
```
### Response Body
```json
{
"msg": "API is working"
}
```
### HTTP Status Code
```
200 OK
```
---
## Comparison: Default Response vs JSONResponse
### Default FastAPI Response
```python
@app.get("/")
def home():
return {"msg": "API is working"}
```
* Automatically serialized to JSON
* Simpler and recommended for most cases
---
### Explicit JSONResponse
```python
return JSONResponse(
content={"msg": "API is working"},
status_code=status.HTTP_200_OK
)
```
* Explicit control over response
* Useful for advanced use cases
---
## When to Use `JSONResponse`
* Returning conditional status codes
* Adding custom headers
* Returning responses outside standard request flow
* Building middleware or exception handlers
* Integrating with legacy systems
---
## Running the Application
Start the application using `uvicorn`:
```bash
uvicorn main:app --reload
```
---
## Best Practices
* Prefer returning dictionaries for simple APIs
* Use `JSONResponse` only when additional control is required
* Keep response formats consistent across endpoints
* Avoid mixing response styles unnecessarily
* Use response models for structured APIs

View File

@@ -0,0 +1,514 @@
# FastAPI Response Model and JSONResponse
## Overview
This document explains two important FastAPI response concepts:
1. Using `response_model` to control what data is returned to the client
2. Using `JSONResponse` when you need explicit control over the response body, status code, or headers
Response models are especially useful when you want to hide sensitive fields such as passwords from API responses.
---
# 1. Response Model
## Incorrect Example
The following code has several issues:
```python
from fastapi import FastAPI, status , HTTPExption
from pydantic import BaseModel
app = FastAPI()
class usersin(BaseModel):
username: str
pass: str
class usersout(BaseModel):
username: str
@app.post("/user")
def home(user: usersin, responce_model=usersout):
return user
```
## Problems in the Code
### 1. `HTTPExption` is misspelled
Correct import:
```python
HTTPException
```
### 2. `pass` cannot be used as a field name
`pass` is a reserved keyword in Python.
Instead of:
```python
pass: str
```
Use:
```python
password: str
```
### 3. `response_model` is written in the wrong place
This is incorrect:
```python
def home(user: usersin, responce_model=usersout):
```
`response_model` must be passed inside the route decorator.
Correct:
```python
@app.post("/user", response_model=UserOut)
```
### 4. `responce_model` is misspelled
Correct spelling:
```python
response_model
```
---
# 2. Correct Response Model Example
Create or update `main.py` with the following content:
```python
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class UserIn(BaseModel):
username: str
password: str
class UserOut(BaseModel):
username: str
@app.post("/user", response_model=UserOut)
def create_user(user: UserIn):
return user
```
---
# 3. How Response Model Works
## Input Model
```python
class UserIn(BaseModel):
username: str
password: str
```
This model defines the data that the API receives from the client.
Example request body:
```json
{
"username": "abbas",
"password": "123456"
}
```
The API accepts both fields:
```text
username
password
```
---
## Output Model
```python
class UserOut(BaseModel):
username: str
```
This model defines the data that the API returns to the client.
Even though the endpoint receives the password, the response only returns the username.
Example response:
```json
{
"username": "abbas"
}
```
The password is removed from the response automatically.
---
# 4. Endpoint Definition
```python
@app.post("/user", response_model=UserOut)
def create_user(user: UserIn):
return user
```
This creates a `POST` endpoint at:
```http
POST /user
```
The endpoint receives data based on `UserIn` and returns data based on `UserOut`.
FastAPI uses `response_model` to filter the response before sending it to the client.
---
# 5. Example Request
## Using curl
```bash
curl -X POST "http://localhost:8000/user" \
-H "Content-Type: application/json" \
-d '{"username": "abbas", "password": "123456"}'
```
## Response
```json
{
"username": "abbas"
}
```
The password is not included in the response.
---
# 6. Why Use Response Models
Response models are useful because they help you:
Protect sensitive data
Keep API responses consistent
Control exactly what the client receives
Improve automatic documentation
Validate response data before sending it
Separate input schemas from output schemas
---
# 7. Better Version with Status Code
For user creation endpoints, it is better to return `201 Created`.
```python
from fastapi import FastAPI, status
from pydantic import BaseModel
app = FastAPI()
class UserIn(BaseModel):
username: str
password: str
class UserOut(BaseModel):
username: str
@app.post(
"/user",
response_model=UserOut,
status_code=status.HTTP_201_CREATED
)
def create_user(user: UserIn):
return user
```
---
# 8. JSONResponse
FastAPI automatically converts Python dictionaries into JSON responses.
For most endpoints, this is enough:
```python
@app.get("/")
def home():
return {"msg": "API is working"}
```
However, FastAPI also allows you to use `JSONResponse` when you need more control.
---
# 9. Example Application Using JSONResponse
Create or update `main.py` with the following content:
```python
from fastapi import FastAPI, status
from fastapi.responses import JSONResponse
app = FastAPI()
@app.get("/")
def home():
return JSONResponse(
content={"msg": "API is working"},
status_code=status.HTTP_200_OK
)
```
---
# 10. Response Behavior
## Endpoint
```http
GET /
```
## Response Body
```json
{
"msg": "API is working"
}
```
## HTTP Status Code
```http
200 OK
```
---
# 11. Default Response vs JSONResponse
## Default FastAPI Response
```python
@app.get("/")
def home():
return {"msg": "API is working"}
```
This is the recommended style for most simple APIs.
FastAPI automatically serializes the dictionary into JSON.
---
## Explicit JSONResponse
```python
return JSONResponse(
content={"msg": "API is working"},
status_code=status.HTTP_200_OK
)
```
This gives more direct control over the response.
---
# 12. When to Use JSONResponse
Use `JSONResponse` when you need to:
Return dynamic status codes
Add custom headers
Customize the response structure manually
Return responses from exception handlers
Return responses from middleware
Override FastAPIs default response behavior
---
# 13. Example: JSONResponse with Custom Status Code
```python
from fastapi import FastAPI, status
from fastapi.responses import JSONResponse
app = FastAPI()
@app.post("/login")
def login():
return JSONResponse(
content={"msg": "Login successful"},
status_code=status.HTTP_200_OK
)
```
---
# 14. Example: JSONResponse with Headers
```python
from fastapi import FastAPI
from fastapi.responses import JSONResponse
app = FastAPI()
@app.get("/custom")
def custom_response():
return JSONResponse(
content={"msg": "Custom response"},
headers={"X-App-Version": "1.0.0"}
)
```
---
# 15. Complete Example with Response Model and JSONResponse
```python
from fastapi import FastAPI, status
from fastapi.responses import JSONResponse
from pydantic import BaseModel
app = FastAPI()
class UserIn(BaseModel):
username: str
password: str
class UserOut(BaseModel):
username: str
@app.get("/")
def home():
return JSONResponse(
content={"msg": "API is working"},
status_code=status.HTTP_200_OK
)
@app.post(
"/user",
response_model=UserOut,
status_code=status.HTTP_201_CREATED
)
def create_user(user: UserIn):
return user
```
---
# 16. Running the Application
Start the FastAPI application using `uvicorn`:
```bash
uvicorn main:app --reload
```
The API will run at:
```text
http://localhost:8000
```
Interactive API documentation will be available at:
```text
http://localhost:8000/docs
```
---
# 17. Best Practices
Use `response_model` to control API output.
Never return sensitive data such as passwords, tokens, or secrets.
Use separate models for input and output.
Use clear class names such as `UserIn` and `UserOut`.
Use `password` instead of `pass` because `pass` is a reserved Python keyword.
Place `response_model` inside the route decorator, not inside the function parameters.
Prefer returning normal dictionaries for simple responses.
Use `JSONResponse` only when extra control is required.
Use proper HTTP status codes, such as:
```http
200 OK
201 Created
400 Bad Request
401 Unauthorized
404 Not Found
500 Internal Server Error
```
Do not use `uvicorn --reload` in production.
---
# 18. DevOps Production Note
In production, the FastAPI application should usually run behind a production-grade ASGI server setup and a reverse proxy.
A common production stack is:
```text
FastAPI
Gunicorn with Uvicorn workers
Nginx or Traefik
Docker or Kubernetes
PostgreSQL or another persistent database
```
The development command:
```bash
uvicorn main:app --reload
```
is only for local development.
For production, use a more stable process configuration, such as Gunicorn with Uvicorn workers, container health checks, logging, monitoring, and proper secret management.

View File

@@ -1,42 +1,79 @@
# FastAPI POST Requests with File Uploads
This document demonstrates how to handle **file uploads** in FastAPI.
File uploads are essential for APIs that need to receive **images, documents, or binary data** from clients.
## Overview
This document explains how to handle file uploads in FastAPI using `POST` requests.
File upload endpoints are commonly used when an API needs to receive:
```text
Images
Documents
PDF files
Text files
Binary files
Multiple files in one request
```
FastAPI supports file uploads using:
```python
File
UploadFile
```
For real applications, `UploadFile` is usually preferred because it provides file metadata and handles large files more efficiently.
---
## Example Application
# 1. Required Package
FastAPI file uploads require `python-multipart`.
Install it with:
```bash
pip install python-multipart
```
If you are using the standard FastAPI installation, it may already be included:
```bash
pip install "fastapi[standard]"
```
---
# 2. Example Application
Create or update `main.py` with the following content:
```python
from fastapi import FastAPI, File, UploadFile, status
from fastapi.responses import JSONResponse
from fastapi import FastAPI, File, UploadFile
from typing import List
app = FastAPI()
users_db = [
{"id": "1", "name": "radin", "password": "123"}
]
@app.post("/file")
def upload_file_bytes(file: bytes = File(...)):
"""
Receive file as raw bytes.
Receive a file as raw bytes.
Returns the size of the uploaded file.
"""
return {"file_size": len(file)}
return {
"file_size": len(file)
}
@app.post("/uploadfile")
def upload_file_uploadfile(file: UploadFile):
async def upload_file_uploadfile(file: UploadFile):
"""
Receive file as UploadFile.
Returns filename, content type, and size.
Receive a file as an UploadFile object.
Returns filename, content type, and file size.
"""
content = file.read()
content = await file.read()
return {
"filename": file.filename,
"content_type": file.content_type,
@@ -45,35 +82,52 @@ def upload_file_uploadfile(file: UploadFile):
@app.post("/uploadmultifile")
def upload_multiple_files(files: List[UploadFile]):
async def upload_multiple_files(files: List[UploadFile]):
"""
Receive multiple files as UploadFile list.
Receive multiple files as UploadFile objects.
Returns filenames and content types.
"""
return [
{"filename": file.filename, "content_type": file.content_type}
for file in files
]
result = []
for file in files:
result.append({
"filename": file.filename,
"content_type": file.content_type
})
return result
```
---
## File Upload Methods
# 3. File Upload as Bytes
### 1. `File` as Bytes
## Endpoint
* Accepts the uploaded file as raw bytes
* Suitable for small files or direct in-memory processing
* Fast but lacks metadata (filename, content type)
```python
@app.post("/file")
def upload_file_bytes(file: bytes = File(...)):
return {
"file_size": len(file)
}
```
**Example Request (curl):**
This endpoint receives the uploaded file as raw bytes.
## Endpoint URL
```http
POST /file
```
## Example Request
```bash
curl -X POST "http://localhost:8000/file" \
-F "file=@example.txt"
```
**Response:**
## Example Response
```json
{
@@ -81,23 +135,71 @@ curl -X POST "http://localhost:8000/file" \
}
```
## Explanation
```python
file: bytes = File(...)
```
This tells FastAPI to expect a file field named `file`.
The uploaded file is loaded directly into memory as bytes.
## When to Use This Method
This method is suitable for:
```text
Small files
Simple testing
Direct in-memory processing
Quick file size checks
```
## Limitation
This method does not provide file metadata such as:
```text
Original filename
Content type
File headers
```
It also loads the whole file into memory, so it is not ideal for large files.
---
### 2. `UploadFile`
# 4. File Upload with `UploadFile`
* Accepts file as `UploadFile` object
* Provides metadata: `filename` and `content_type`
* Supports `.read()`, `.write()`, and `.seek()` operations
* More efficient for large files (uses spooled temporary files)
## Endpoint
**Example Request (curl):**
```python
@app.post("/uploadfile")
async def upload_file_uploadfile(file: UploadFile):
content = await file.read()
return {
"filename": file.filename,
"content_type": file.content_type,
"file_size": len(content)
}
```
## Endpoint URL
```http
POST /uploadfile
```
## Example Request
```bash
curl -X POST "http://localhost:8000/uploadfile" \
-F "file=@example.txt"
```
**Response:**
## Example Response
```json
{
@@ -109,13 +211,72 @@ curl -X POST "http://localhost:8000/uploadfile" \
---
### 3. Multiple File Uploads
# 5. Why Use `UploadFile`
* Accepts a list of `UploadFile`
* Allows uploading multiple files in one request
* Useful for batch uploads or form submissions
`UploadFile` is better than raw bytes for most real APIs.
**Example Request (curl):**
It provides useful metadata:
```python
file.filename
file.content_type
file.file
```
It also supports file operations such as:
```python
await file.read()
await file.write()
await file.seek()
await file.close()
```
## Important Note
When using `UploadFile.read()`, the endpoint should usually be asynchronous:
```python
async def upload_file_uploadfile(file: UploadFile):
content = await file.read()
```
This is better than writing:
```python
def upload_file_uploadfile(file: UploadFile):
content = file.read()
```
because `file.read()` is asynchronous and should be awaited.
---
# 6. Multiple File Uploads
## Endpoint
```python
@app.post("/uploadmultifile")
async def upload_multiple_files(files: List[UploadFile]):
result = []
for file in files:
result.append({
"filename": file.filename,
"content_type": file.content_type
})
return result
```
## Endpoint URL
```http
POST /uploadmultifile
```
## Example Request
```bash
curl -X POST "http://localhost:8000/uploadmultifile" \
@@ -123,45 +284,229 @@ curl -X POST "http://localhost:8000/uploadmultifile" \
-F "files=@file2.txt"
```
**Response:**
## Example Response
```json
[
{"filename": "file1.txt", "content_type": "text/plain"},
{"filename": "file2.txt", "content_type": "text/plain"}
{
"filename": "file1.txt",
"content_type": "text/plain"
},
{
"filename": "file2.txt",
"content_type": "text/plain"
}
]
```
## Explanation
```python
files: List[UploadFile]
```
This tells FastAPI to receive multiple uploaded files using the same form field name:
```text
files
```
Each uploaded file is handled as an `UploadFile` object.
---
## Content-Type
# 7. Content-Type for File Uploads
For file uploads, the request must include:
File uploads use:
```
```http
Content-Type: multipart/form-data
```
* Each file is sent as a separate part in the multipart request
When using `curl` with `-F`, this header is generated automatically.
Example:
```bash
curl -X POST "http://localhost:8000/uploadfile" \
-F "file=@example.txt"
```
The request sends the file as a multipart form field.
---
## Running the Application
# 8. Complete Recommended Version
Start the service using `uvicorn`:
```python
from fastapi import FastAPI, File, UploadFile, HTTPException, status
from typing import List
app = FastAPI()
MAX_FILE_SIZE = 5 * 1024 * 1024
@app.get("/")
def root():
return {
"message": "API is working"
}
@app.post("/file")
def upload_file_bytes(file: bytes = File(...)):
if len(file) > MAX_FILE_SIZE:
raise HTTPException(
status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
detail="File is too large"
)
return {
"file_size": len(file)
}
@app.post("/uploadfile")
async def upload_file_uploadfile(file: UploadFile):
content = await file.read()
if len(content) > MAX_FILE_SIZE:
raise HTTPException(
status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
detail="File is too large"
)
return {
"filename": file.filename,
"content_type": file.content_type,
"file_size": len(content)
}
@app.post("/uploadmultifile")
async def upload_multiple_files(files: List[UploadFile]):
result = []
for file in files:
content = await file.read()
if len(content) > MAX_FILE_SIZE:
raise HTTPException(
status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
detail=f"File is too large: {file.filename}"
)
result.append({
"filename": file.filename,
"content_type": file.content_type,
"file_size": len(content)
})
return result
```
---
# 9. Running the Application
Start the FastAPI service using `uvicorn`:
```bash
uvicorn main:app --reload
```
The application will be available at:
```text
http://localhost:8000
```
Interactive API documentation:
```text
http://localhost:8000/docs
```
Alternative API documentation:
```text
http://localhost:8000/redoc
```
---
## Best Practices
# 10. Testing with curl
* Use `UploadFile` for large or multiple files
* Validate file type and size on the server
* Avoid loading very large files fully into memory
* Use HTTPS for secure file transfer
* Store files in dedicated storage (S3, local disk, or DB)
* Return clear metadata (filename, size, content type) to clients
* Support multiple files when needed for batch operations
## Upload File as Bytes
```bash
curl -X POST "http://localhost:8000/file" \
-F "file=@example.txt"
```
## Upload Single File with `UploadFile`
```bash
curl -X POST "http://localhost:8000/uploadfile" \
-F "file=@example.txt"
```
## Upload Multiple Files
```bash
curl -X POST "http://localhost:8000/uploadmultifile" \
-F "files=@file1.txt" \
-F "files=@file2.txt"
```
---
# 11. `bytes` vs `UploadFile`
| Feature | `bytes` | `UploadFile` |
| -------------------------- | --------------------------- | ------------------------- |
| File content | Loaded directly into memory | Uses file-like object |
| Filename | Not available | Available |
| Content type | Not available | Available |
| Best for | Small files | Large files and real APIs |
| Metadata | No | Yes |
| Recommended for production | Usually no | Yes |
---
# 12. Best Practices
Use `UploadFile` for real-world APIs.
Use `bytes` only for small files or simple testing.
Validate file size on the server.
Validate file type before processing or storing the file.
Do not trust the uploaded filename.
Do not store uploaded files directly using user-provided names.
Avoid loading very large files fully into memory.
Use HTTPS for secure file transfer.
Store files in dedicated storage such as:
```text
Local disk
Object storage such as S3 or MinIO
Database storage when appropriate
Network file storage
```
Return clear metadata to the client, such as:
```text
Filename
Content type
File size
Upload status
```

View File

@@ -1,13 +1,16 @@
# FastAPI Application Lifespan (Startup & Shutdown Events)
# FastAPI Application Lifespan, Startup, and Shutdown Events
FastAPI allows you to run code when your application **starts up** or **shuts down**.
This is useful for initializing resources, database connections, caches, or background tasks.
## Overview
FastAPI allows you to execute code when the application starts and when it shuts down. This is useful for initializing and cleaning up shared resources such as database connections, cache clients, machine learning models, message queues, or background services.
The modern recommended approach is to use the `lifespan` parameter with an async context manager. The older `@app.on_event()` method is still available, but FastAPI marks it as deprecated in favor of lifespan handlers. ([fastapi.tiangolo.com][1])
---
## Deprecated Method: `@app.on_event`
# 1. Deprecated Method: `@app.on_event`
Older FastAPI versions use the `@app.on_event` decorator for lifecycle events:
Older FastAPI applications often use `@app.on_event("startup")` and `@app.on_event("shutdown")`.
```python
from fastapi import FastAPI
@@ -25,97 +28,355 @@ def on_shutdown():
print("App is shutting down")
```
### Characteristics
## Explanation
* `startup` runs once when the app starts
* `shutdown` runs once when the app is stopped
* Works for synchronous and asynchronous functions
* Still supported but **deprecated** in favor of the `lifespan` parameter
```python
@app.on_event("startup")
def on_startup():
print("App is loading")
```
This function runs once when the application starts.
```python
@app.on_event("shutdown")
def on_shutdown():
print("App is shutting down")
```
This function runs once when the application is shutting down.
## Important Note
FastAPI documentation recommends using the `lifespan` parameter instead of `@app.on_event()`. Also, when a `lifespan` handler is provided, FastAPI does not call the old `startup` and `shutdown` event handlers. You should use one approach consistently, not both. ([fastapi.tiangolo.com][1])
---
## Recommended Modern Approach: `lifespan` with `asynccontextmanager`
# 2. Recommended Method: `lifespan`
FastAPI now recommends using the `lifespan` parameter in the `FastAPI` constructor.
This uses Python's `asynccontextmanager` to define a **single lifecycle context**.
The modern approach is to define one lifecycle function using `asynccontextmanager`.
```python
from fastapi import FastAPI
from contextlib import asynccontextmanager
from fastapi import FastAPI
@asynccontextmanager
async def lifespan(app: FastAPI):
# Code to run before the app starts
print("App is loading")
yield # Application runs after this point
# Code to run after the app stops
yield
print("App is shutting down")
app = FastAPI(lifespan=lifespan)
```
### How It Works
---
1. Code **before `yield`** executes on startup
2. Code **after `yield`** executes on shutdown
3. Supports async operations, e.g., connecting to a database
# 3. How Lifespan Works
The `lifespan` function has two main sections:
```python
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup logic
print("App is loading")
yield
# Shutdown logic
print("App is shutting down")
```
## Code Before `yield`
This runs when the application starts.
Use this section for:
```text
Database connection setup
Cache connection setup
Loading configuration
Initializing shared services
Starting background clients
```
## Code After `yield`
This runs when the application shuts down.
Use this section for:
```text
Closing database connections
Closing cache clients
Flushing logs
Releasing resources
Stopping background services
```
FastAPI passes the lifespan context manager into the application and executes the code before `yield` on startup and after `yield` on shutdown. ([fastapi.tiangolo.com][1])
---
## Example: Using Lifespan for Database Initialization
# 4. Example Application
Create or update `main.py` with the following content:
```python
from fastapi import FastAPI
from contextlib import asynccontextmanager
from fastapi import FastAPI
@asynccontextmanager
async def lifespan(app: FastAPI):
app.state.db = await connect_to_db()
print("Database connected")
print("App is loading")
yield
await app.state.db.close()
print("Database disconnected")
print("App is shutting down")
app = FastAPI(lifespan=lifespan)
@app.get("/")
def root():
return {"message": "API is working"}
```
* `app.state` is used to store shared resources
* Clean startup and shutdown handling
* Ensures proper resource cleanup
---
## Benefits of the Lifespan Approach
# 5. Running the Application
* Centralized lifecycle management
* Cleaner async support
* Avoids multiple scattered `@app.on_event` decorators
* Better for testing and production-ready apps
---
## Running the Application
Start the service with `uvicorn`:
Start the service using `uvicorn`:
```bash
uvicorn main:app --reload
```
* On startup, `App is loading` prints to the console
* On shutdown (Ctrl+C), `App is shutting down` prints to the console
When the application starts, the terminal prints:
```text
App is loading
```
When you stop the application, for example with `Ctrl + C`, the terminal prints:
```text
App is shutting down
```
---
## Best Practices
# 6. Example: Database Initialization Pattern
* Always use `lifespan` for new applications
* Use `app.state` to store shared resources
* Close database connections, caches, or background services in shutdown
* Keep startup logic lightweight to avoid blocking the server
* Avoid printing in production; use logging instead
In real applications, lifespan is commonly used to initialize and close database connections.
```python
from contextlib import asynccontextmanager
from fastapi import FastAPI
async def connect_to_db():
# Replace this with a real database connection
return "database-connection"
@asynccontextmanager
async def lifespan(app: FastAPI):
app.state.db = await connect_to_db()
print("Database connected")
yield
# Replace this with real cleanup logic
print("Database disconnected")
app = FastAPI(lifespan=lifespan)
@app.get("/")
def root():
return {"message": "API is working"}
```
---
This approach provides a **modern, production-ready pattern** for managing application startup and shutdown events in FastAPI.
# 7. Using `app.state`
`app.state` is useful for storing shared application-level resources.
Example:
```python
app.state.db = await connect_to_db()
```
Later, this resource can be accessed from the application.
Common resources stored in `app.state` include:
```text
Database clients
Redis clients
HTTP clients
Configuration objects
Service clients
Loaded models
```
---
# 8. Better Database Cleanup Example
If the database client has a `close()` method, close it after `yield`.
```python
from contextlib import asynccontextmanager
from fastapi import FastAPI
@asynccontextmanager
async def lifespan(app: FastAPI):
app.state.db = await connect_to_db()
print("Database connected")
yield
await app.state.db.close()
print("Database disconnected")
app = FastAPI(lifespan=lifespan)
```
This ensures that the application does not leave open connections after shutdown.
---
# 9. Why Lifespan Is Better
The lifespan approach is better for modern FastAPI applications because it keeps startup and shutdown logic in one place.
It helps with:
```text
Centralized lifecycle management
Cleaner async resource handling
Better application structure
Easier testing
More predictable production behavior
Cleaner resource cleanup
```
---
# 10. Complete Recommended Version
```python
from contextlib import asynccontextmanager
from fastapi import FastAPI
@asynccontextmanager
async def lifespan(app: FastAPI):
print("Application startup started")
# Initialize shared resources here
app.state.service_status = "ready"
print("Application startup completed")
yield
print("Application shutdown started")
# Clean up shared resources here
app.state.service_status = "stopped"
print("Application shutdown completed")
app = FastAPI(lifespan=lifespan)
@app.get("/")
def root():
return {"message": "API is working"}
@app.get("/health")
def health_check():
return {
"status": "healthy",
"service": app.state.service_status
}
```
---
# 11. Testing the Application
Run the app:
```bash
uvicorn main:app --reload
```
Open:
```text
http://localhost:8000/
```
Expected response:
```json
{
"message": "API is working"
}
```
Open:
```text
http://localhost:8000/health
```
Expected response:
```json
{
"status": "healthy",
"service": "ready"
}
```
---
# 12. Best Practices
Use `lifespan` for new FastAPI applications.
Avoid using `@app.on_event()` in new code because it is deprecated.
Do not mix `lifespan` with `startup` and `shutdown` event decorators.
Use `app.state` for shared application resources.
Close database connections, cache clients, HTTP clients, and background services during shutdown.
Keep startup logic lightweight.
Avoid using `print()` in production.
Use structured logging instead of printing to the console.
Do not use `--reload` in production.

View File

@@ -0,0 +1,312 @@
# HTTP Requests in Python with `requests`
This document explains how to use the **`requests`** library to send HTTP requests, handle responses, work with APIs, upload/download files, manage headers, authentication, errors, and more.
> `requests` is not part of the standard library and must be installed:
```bash
pip install requests
```
---
## 1. Sending a Basic GET Request
### Code
```python
import requests
r = requests.get("http://myip.abbascloud.ir")
print(r.url)
print(r.status_code, r.ok)
print(r.text)
print(r.content)
print(r.json())
print(r.headers)
```
### Explanation
- `requests.get(url)` sends an HTTP GET request.
- `r.url`: final URL after redirects.
- `r.status_code`: HTTP status code (e.g. 200, 404).
- `r.ok`: `True` if status code is < 400.
- `r.text`: response body as string.
- `r.content`: response body as raw bytes.
- `r.json()`: parses JSON response into Python objects.
- `r.headers`: response headers as a dictionary.
---
## 2. Passing Query Parameters
### Code
```python
params = {
"q": "python",
"page": 1
}
response = requests.get("https://api.example.com/search", params=params)
print(response.url)
```
### Explanation
- `params` are appended to the URL as query strings.
- Automatically encoded by `requests`.
- Resulting URL:
```
https://api.example.com/search?q=python&page=1
```
---
## 3. Sending POST Requests (Form Data)
### Code
```python
data = {
"username": "alex",
"password": "secret"
}
requests.post(url, data=data)
```
### Explanation
- Sends data as `application/x-www-form-urlencoded`.
- Common for HTML form submissions.
---
## 4. Sending POST Requests (JSON)
### Code
```python
json_data = {
"name": "Alex",
"age": 25
}
requests.post(url, json=json_data)
```
### Explanation
- Automatically serializes data to JSON.
- Sets `Content-Type: application/json`.
- Preferred for REST APIs.
---
## 5. Custom Request Headers
### Code
```python
headers = {
"Authorization": "Bearer YOUR_TOKEN",
"User-Agent": "MyApp/1.0",
"Accept": "application/json"
}
response = requests.get(url, headers=headers)
```
### Explanation
- Used for authentication, API versioning, and content negotiation.
- Common headers:
- `Authorization`
- `User-Agent`
- `Accept`
---
## 6. Authentication (Basic Auth)
### Code
```python
from requests.auth import HTTPBasicAuth
requests.get(
"https://api.example.com",
auth=HTTPBasicAuth("username", "password")
)
```
### Explanation
- Sends credentials using HTTP Basic Authentication.
- Automatically encodes credentials in headers.
---
## 7. Working with Cookies
### Code
```python
response = requests.get(url)
print(response.cookies)
```
### Explanation
- Cookies are stored in a `RequestsCookieJar`.
- Useful for sessions and login persistence.
---
## 8. Uploading Files
### Code
```python
files = {
"file": open("example.txt", "rb")
}
response = requests.post(url, files=files)
```
### Explanation
- Sends files as `multipart/form-data`.
- Common for file uploads to APIs.
---
## 9. Downloading Files
### Simple Download
```python
response = requests.get("https://example.com/image.png")
with open("image.png", "wb") as f:
f.write(response.content)
```
- Downloads entire file into memory.
- Suitable for small files.
---
### Streaming Large Files
```python
response = requests.get(url, stream=True)
with open("big.zip", "wb") as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
```
- Downloads file in chunks.
- Prevents high memory usage.
- Recommended for large files.
---
## 10. Timeout and Error Handling
### Code
```python
try:
response = requests.get(url, timeout=5)
response.raise_for_status()
except requests.exceptions.Timeout:
print("Request timed out")
except requests.exceptions.HTTPError as e:
print("HTTP error:", e)
except requests.exceptions.RequestException as e:
print("Request failed:", e)
```
### Explanation
- `timeout`: maximum wait time (seconds).
- `raise_for_status()`: raises exception for 4xx / 5xx errors.
- `RequestException`: base class for all request errors.
---
## 11. Using Proxies
### Code
```python
proxies = {
"http": "http://127.0.0.1:8080",
"https": "http://127.0.0.1:8080"
}
requests.get(url, proxies=proxies)
```
### Explanation
- Routes requests through a proxy server.
- Useful for debugging, privacy, or corporate networks.
---
## 12. SSL Verification
### Code
```python
requests.get(url, verify=True) # default
requests.get(url, verify=False) # NOT recommended
```
### Explanation
- `verify=True` checks SSL certificates.
- Disabling SSL verification is insecure and should only be used for testing.
---
## 13. Real API Example (GitHub)
### Code
```python
import requests
API_URL = "https://api.github.com/users/octocat"
response = requests.get(API_URL)
if response.ok:
user = response.json()
print(user["login"], user["public_repos"])
else:
print("Error:", response.status_code)
```
### Explanation
- Sends a GET request to GitHubs public API.
- Parses JSON response.
- Accesses specific fields safely.
- Checks request success using `response.ok`.
---
## Summary
- `requests` simplifies HTTP communication
- Supports GET, POST, headers, params, JSON, files
- Handles authentication, cookies, proxies, and SSL
- Built-in error handling improves reliability
- Widely used for REST APIs and web services