Compare commits

...

24 Commits

Author SHA1 Message Date
42f8df2589 Docker SDK: Added Network doc ( not complated ) 2026-02-04 01:31:31 +03:30
RadinPirouz
90f5451ff8 Docker Lib : Added Container Doc 2026-01-25 15:34:35 +03:30
RadinPirouz
2e229ceadd Docker Lib: Added Images Doc 2026-01-25 15:25:49 +03:30
RadinPirouz
32615bf615 docker doc : updated setup doc 2026-01-24 00:13:06 +03:30
RadinPirouz
7de5efab3f Docker Lib doc : added structure of doc 2026-01-23 23:28:44 +03:30
RadinPirouz
6fbd717868 update services doc to libs 2026-01-23 23:21:00 +03:30
RadinPirouz
6be588aa58 fastapi doc : Life Span Doc 2026-01-23 17:40:40 +03:30
RadinPirouz
01a3efd424 fastapi doc : File Post ADoc 2026-01-23 17:27:39 +03:30
RadinPirouz
38943392c2 fastapi doc : body post doc 2026-01-23 16:26:18 +03:30
RadinPirouz
78f6dcb356 fastapi doc : from post doc 2026-01-23 16:20:35 +03:30
RadinPirouz
ad45fd4ee2 fastapi doc : post types 2026-01-23 16:13:30 +03:30
RadinPirouz
a2aed1117f fastapi doc : change Query and added path Param 2026-01-22 23:59:35 +03:30
RadinPirouz
6cf2b3c3ef fastapi doc : added Query Adavaned Param 2026-01-22 23:53:01 +03:30
RadinPirouz
a5812354c2 fastapi doc : added Json Responces 2026-01-21 14:54:25 +03:30
RadinPirouz
aa3957945c fastapi doc: added status,httpexpetion doc 2026-01-21 01:30:40 +03:30
RadinPirouz
729e73bae8 fastapi doc: added query parameter 2026-01-20 18:04:07 +03:30
d91d177fa9 fastapi: added delete doc 2026-01-20 00:03:37 +03:30
fa455aaa33 fastapi: added put doc 2026-01-19 23:52:28 +03:30
b8e9dc2ae7 fastapi: added post doc 2026-01-19 21:42:45 +03:30
2ee6a1aba3 fastapi: renamed get doc 2026-01-19 21:24:10 +03:30
7067c77714 changed redis dir 2026-01-19 21:17:42 +03:30
RadinPirouz
88ac98c62f fast api: clean get post json doc 2026-01-19 18:30:36 +03:30
RadinPirouz
22ed791ad4 fast api: clean Simple Route doc 2026-01-19 18:28:33 +03:30
RadinPirouz
bbaa4c99f1 fast api: clean setup doc 2026-01-19 18:26:16 +03:30
27 changed files with 3397 additions and 60 deletions

View File

@@ -0,0 +1,274 @@
# Docker SDK for Python Setup and First Steps
This document introduces the **Docker SDK for Python (`docker` library)** and explains how to connect to the Docker Engine, inspect its status, and authenticate with a registry. The goal is not just to show code, but to clearly explain **what each part does, why it exists, and when you would use it**.
This guide assumes you already understand basic Docker concepts (images, containers, daemon) and are approaching this from a DevOps perspective.
---
## 1. Installing the Docker SDK for Python
Before Python can communicate with Docker, we need to install the official SDK.
```bash
pip install docker
```
### What this does
* Installs the **docker** Python package (often called *docker-py*).
* This package acts as a **client wrapper** around Dockers REST API.
* All interactions ultimately talk to the Docker daemon (`dockerd`) over a socket or TCP connection.
Important note:
* Installing the library alone is not enough.
* Docker **must already be installed and running** on the system.
---
## 2. Connecting to Docker Using Environment Configuration
The simplest and most common way to create a Docker client is by using environment-based configuration.
```python
import docker
client = docker.from_env()
version = client.version()
ping_docker = client.ping()
print(version, ping_docker)
```
### Step-by-step explanation
#### `import docker`
* Imports the Docker SDK.
* This module exposes high-level objects for interacting with Docker resources.
#### `docker.from_env()`
* Automatically creates a `DockerClient` instance.
* Reads Docker connection details from environment variables such as:
* `DOCKER_HOST`
* `DOCKER_TLS_VERIFY`
* `DOCKER_CERT_PATH`
* On Linux, this usually resolves to:
* `unix:///var/run/docker.sock`
This is why `from_env()` is preferred:
* Works across Linux, macOS, Windows, and CI systems
* Requires no hardcoded connection strings
#### `client.version()`
* Calls the Docker Engine `/version` API endpoint.
* Returns detailed metadata such as:
* Docker Engine version
* API version
* Go version
* OS and architecture
This is commonly used for:
* Debugging
* Compatibility checks
* Logging runtime environment details
#### `client.ping()`
* Sends a lightweight request to the Docker daemon.
* Returns `True` if Docker is reachable and responsive.
This is a **health check**, often used in:
* Startup validation
* Monitoring scripts
* CI/CD pipelines
---
## 3. What Does “from_env” Actually Mean?
Using `from_env()` tells the SDK:
> “Figure out how to connect to Docker using the same configuration the Docker CLI uses.”
Behind the scenes, it:
* Detects whether Docker is local or remote
* Determines socket vs TCP
* Applies TLS settings if required
### When should you use it?
* Local development
* Kubernetes nodes
* CI runners
* Most production automation
### When not to use it?
* When you need explicit control over connection parameters
* When connecting to a **remote Docker daemon** with custom networking
---
## 4. Creating a Docker Client Explicitly
Instead of relying on environment detection, you can create a client manually.
```python
import docker
client = docker.DockerClient(base_url='unix://var/run/docker.sock')
version = client.version()
ping_docker = client.ping()
print(version, ping_docker)
```
### Explanation
#### `docker.DockerClient(...)`
* Directly instantiates a Docker client object.
* Requires you to specify how to reach the Docker daemon.
#### `base_url='unix://var/run/docker.sock'`
* Points to the Unix socket used by Docker on Linux systems.
* This socket is owned by root and the `docker` group.
Important implications:
* Your Python process must have permission to access the socket
* Usually means running as root or a user in the `docker` group
### When this approach is useful
* Controlled environments
* Educational examples
* Explicit infrastructure scripts
### Why it is less common
* Not portable across OSes
* Hardcodes infrastructure assumptions
---
## 5. Inspecting Docker and Authenticating
Once connected, the client can retrieve detailed system information and authenticate with registries.
```python
import docker
client = docker.DockerClient(base_url='unix://var/run/docker.sock')
version = client.version()
ping_docker = client.ping()
information = client.info()
client.login(
username='user',
password='password',
registry='registry_link'
)
print(information, ping_docker)
```
### `client.info()`
* Calls the Docker `/info` endpoint.
* Returns a comprehensive snapshot of the Docker host, including:
* Number of containers (running/stopped)
* Number of images
* Storage driver
* Cgroup and kernel features
* Security options (AppArmor, seccomp)
This is extremely valuable for:
* Capacity planning
* Debugging runtime issues
* Auditing host configuration
### `client.login(...)`
* Authenticates Docker with a container registry.
* Stores credentials in Dockers credential store.
Parameters:
* `username`: registry account username
* `password`: registry password or access token
* `registry`: registry URL (e.g. Docker Hub or private registry)
Common use cases:
* Pulling private images
* Pushing images in CI/CD pipelines
* Automating registry interactions
Security note:
* Avoid hardcoding credentials in source code
* Prefer environment variables or secret managers
---
## 6. High-Level vs Low-Level API (Important Concept)
What you are using here is the **high-level Docker client**.
Characteristics:
* Pythonic object model
* Resource-oriented (containers, images, networks)
* Easier to read and maintain
The SDK also exposes a **low-level API**:
* Direct access to Docker REST endpoints
* More control, less abstraction
As a DevOps engineer, you will typically:
* Use high-level API for automation
* Drop to low-level API for advanced edge cases
---
## 7. Summary
In this setup phase, you learned how to:
* Install the Docker SDK for Python
* Connect to Docker using environment-based configuration
* Explicitly define Docker connection settings
* Verify Docker availability
* Retrieve system-level Docker information
* Authenticate with container registries
This foundation is critical before moving on to:
* Managing containers
* Building images
* Working with volumes and networks
---
## References
Official Docker SDK for Python documentation:
* [https://docker-py.readthedocs.io/](https://docker-py.readthedocs.io/)

View File

@@ -0,0 +1,360 @@
# Docker SDK for Python Working with Images
This document explains how to **manage Docker images** using the Docker SDK for Python. Instead of treating the SDK as a set of function calls, well approach images the same way Docker itself does: as immutable artifacts that are pulled, built, tagged, pushed, inspected, and eventually cleaned up.
All examples assume:
* Docker is installed and running
* The Python process has access to the Docker socket
---
## 1. Creating the Docker Client
```python
import docker
client = docker.DockerClient(base_url='unix://var/run/docker.sock')
ping_docker = client.ping()
```
### Explanation
* `DockerClient` establishes a connection to the Docker daemon.
* `ping()` verifies that Docker is reachable before doing any real work.
This is a common pattern in automation:
* Fail fast if Docker is unavailable
* Avoid partial execution later in the script
---
## 2. Pulling Images from a Registry
```python
def pull_image(name_image, tag_image):
image = client.images.pull(name_image, tag=tag_image)
print(image)
```
### What this does
* Downloads an image from a registry (Docker Hub or private registry).
* If the image already exists locally, Docker may reuse layers.
Parameters:
* `name_image`: repository name (e.g. `alpine`, `nginx`, `myrepo/app`)
* `tag_image`: specific version or variant (e.g. `3.20`, `latest`)
Returned value:
* An `Image` object representing the pulled image
Why this matters:
* Pulling explicitly avoids relying on implicit image downloads
* Makes automation predictable and repeatable
---
## 3. Building Images from a Dockerfile
### Basic build
```python
def build_image():
image, logs = client.images.build(
path=".",
tag="myapp:1.0"
)
for log in logs:
if "stream" in log:
print(log["stream"].strip())
```
### Explanation
* `path="."` tells Docker to use the current directory as the build context.
* Docker automatically looks for a file named `Dockerfile`.
* `tag="myapp:1.0"` assigns a name and version to the resulting image.
The build process returns:
* `image`: the final built image object
* `logs`: a stream of build output messages
Printing build logs is important because:
* Docker build failures are only visible in logs
* CI pipelines rely on this output for debugging
---
## 4. Advanced Build with Custom Dockerfile and Build Arguments
```python
def build_image_2():
image, logs = client.images.build(
path=".",
dockerfile="Dockerfile.prod",
tag="myapp:prod",
buildargs={
"APP_ENV": "production",
"VERSION": "1.0.0"
}
)
```
### Explanation
This version adds more control:
* `dockerfile="Dockerfile.prod"`
* Allows multiple Dockerfiles per project
* Common for dev vs prod builds
* `buildargs`
* Passed to `ARG` instructions inside the Dockerfile
* Enables parameterized builds without editing the Dockerfile
Typical DevOps use cases:
* Environment-specific builds
* Injecting version numbers
* Feature flags during build time
---
## 5. Tagging Images
```python
def tag_image():
image = client.images.get("myapp:1.0")
image.tag("myrepo/myapp", tag="latest")
```
### Explanation
* Docker images are immutable, but tags are not.
* This creates an additional reference to the same image ID.
Why tagging is important:
* One image can have multiple tags
* Tags represent lifecycle stages (`1.0`, `prod`, `latest`)
This is how promotion pipelines work:
* Build once
* Tag many times
* Push selectively
---
## 6. Removing Images
```python
def remove_image():
client.images.remove("myapp:1.0", force=True)
```
### Explanation
* Removes the image reference from the local Docker host.
* `force=True` removes the image even if it is in use by stopped containers.
Use with care:
* Running containers still prevent deletion
* Forced removal is destructive
---
## 7. Pushing Images to a Registry
```python
def push_image():
client.images.push(
repository="myrepo/myapp",
tag="latest"
)
```
### Explanation
* Uploads the image layers to a registry.
* Requires prior authentication (`client.login`).
Important notes:
* Only new or changed layers are pushed
* Tags determine what remote users pull
This step is usually automated in:
* CI/CD pipelines
* Release workflows
---
## 8. Cleaning Up Unused Images
```python
def prune_images():
result = client.images.prune()
print(result)
```
### Explanation
* Removes dangling images (untagged and unused).
* Helps reclaim disk space on build servers.
The result includes:
* Number of images removed
* Amount of disk space freed
This is essential for:
* CI runners
* Long-lived build machines
---
## 9. Inspecting Image Metadata
```python
def inspect_image():
alpine_image = client.images.get("alpine:3.20")
print(alpine_image.attrs)
print(alpine_image.attrs["Id"])
print(alpine_image.attrs["Size"])
print(alpine_image.attrs["Config"]["Env"])
print(alpine_image.attrs["Config"]["Cmd"])
```
### Explanation
* `attrs` exposes the raw Docker image inspection data.
* This is equivalent to `docker image inspect`.
Useful fields:
* `Id`: content-addressable image hash
* `Size`: image size in bytes
* `Config.Env`: environment variables baked into the image
* `Config.Cmd`: default command
This information is often used for:
* Debugging unexpected behavior
* Auditing images
* Validating build output
---
## 10. Listing Local Images
```python
def image_list():
images = client.images.list()
for item in images:
print(item.id, item.tags)
```
### Explanation
* Lists all images stored locally.
* Each image may have multiple tags or none.
This mirrors:
* `docker images`
---
## 11. Ensuring an Image Exists
```python
def ensure_image(name):
try:
client.images.get(name)
print(f"{name} exists")
except docker.errors.ImageNotFound:
print(f"Pulling {name}")
client.images.pull(name)
```
### Explanation
This is a very common DevOps pattern:
* Check if the image exists locally
* Pull it only if necessary
Benefits:
* Avoids unnecessary network calls
* Makes scripts idempotent
---
## 12. Important Exceptions to Know
When working with images, you must handle failures explicitly.
### `docker.errors.ImageNotFound`
* Raised when an image does not exist locally
* Common when calling `get()`
### `docker.errors.BuildError`
* Raised when an image build fails
* Usually due to Dockerfile errors or missing files
### `docker.errors.APIError`
* Raised for general Docker API failures
* Includes permission issues, daemon errors, and network problems
Catching these exceptions is critical for:
* Reliable automation
* Meaningful error reporting
* CI/CD stability
---
## 13. Summary
In this section, you learned how to:
* Pull images from registries
* Build images using Dockerfiles
* Use build arguments and multiple Dockerfiles
* Tag and push images
* Inspect and list images
* Clean up unused images
* Handle common Docker image errors
This image workflow is the backbone of:
* CI pipelines
* Release automation
* Platform engineering systems
---
## References
Official Docker SDK for Python documentation:
* [https://docker-py.readthedocs.io/](https://docker-py.readthedocs.io/)

View File

@@ -0,0 +1,284 @@
# Docker SDK for Python Working with Containers
This document explains how to **manage Docker containers** using the Docker SDK for Python. Containers are the runtime unit of Docker, so this section focuses on lifecycle management: listing, creating, running, starting, stopping, restarting, pausing, and inspecting logs.
The goal is to understand **how container state changes**, how the Python SDK maps to Docker CLI behavior, and how these operations are typically used in real DevOps automation.
---
## 1. Creating the Docker Client
```python
import docker
import time
client = docker.DockerClient(base_url='unix://var/run/docker.sock')
ping_docker = client.ping()
```
### Explanation
* Establishes a connection to the Docker daemon via the Unix socket.
* `ping()` is used as a sanity check before executing container operations.
In production-grade scripts, this check prevents:
* Silent failures
* Partial execution when Docker is down
---
## 2. Listing Running Containers
```python
def get_containers_list():
containers = client.containers.list()
for c in containers:
print(c.id, c.name, c.status)
```
### Explanation
* `containers.list()` returns **only running containers** by default.
* Each returned object represents a live container instance.
Common attributes:
* `id`: unique container identifier
* `name`: human-readable container name
* `status`: runtime state (running)
This is equivalent to:
* `docker ps`
---
## 3. Listing All Containers (Including Stopped)
```python
def get_all_containers_list():
containers = client.containers.list(all=True)
for c in containers:
print(c.id, c.name, c.status)
```
### Explanation
* `all=True` includes stopped, exited, and created containers.
* Useful for cleanup, auditing, and lifecycle reconciliation.
Equivalent CLI command:
* `docker ps -a`
---
## 4. Creating a Container (Without Starting It)
```python
def create_container():
container = client.containers.create(
image="nginx:latest",
name="my_nginx",
ports={"80/tcp": 8080},
detach=True
)
```
### Explanation
This creates a container in the **created** state.
Key parameters:
* `image`: base image for the container
* `name`: explicit container name
* `ports`: port mapping (container → host)
* `detach=True`: container runs in background when started
Important distinction:
* `create()` does **not** start the container
* This mirrors `docker create`
Use cases:
* Deferred startup
* Multi-step initialization
---
## 5. Running a Container (Create + Start)
```python
def run_container():
container = client.containers.run(
"nginx:latest",
name="nginx_run",
ports={"80/tcp": 8081},
detach=True
)
```
### Explanation
* `run()` is a convenience method.
* Internally performs `create()` followed by `start()`.
Equivalent CLI command:
* `docker run -d -p 8081:80 nginx:latest`
This is the most common approach for:
* Short-lived workloads
* Simple services
---
## 6. Managing Container Lifecycle
```python
def start_container():
container = client.containers.get("my_nginx")
container.start()
time.sleep(1000)
container.restart()
time.sleep(1000)
container.pause()
container.unpause()
time.sleep(1000)
container.stop(timeout=10)
```
### Explanation
This function demonstrates multiple lifecycle transitions.
#### `containers.get(name)`
* Retrieves an existing container by name or ID.
* Raises an exception if the container does not exist.
#### `start()`
* Transitions container from `created` or `stopped``running`.
#### `restart()`
* Stops and immediately starts the container.
* Often used after configuration changes.
#### `pause()` / `unpause()`
* Freezes container processes using cgroups.
* Network and filesystem state remain intact.
#### `stop(timeout=10)`
* Sends SIGTERM, then SIGKILL after timeout.
* Allows graceful shutdown.
The `sleep()` calls simulate:
* Long-running services
* Observing container behavior between states
---
## 7. Reading Container Logs
```python
def log_container():
container = client.containers.get("my_nginx")
logs = container.logs(tail=20)
print(logs.decode())
```
### Explanation
* Retrieves logs from the containers stdout/stderr.
* `tail=20` limits output to the last 20 lines.
Important details:
* Logs are returned as bytes
* Decoding is required for readable output
Equivalent CLI command:
* `docker logs --tail 20 my_nginx`
This is critical for:
* Debugging runtime issues
* Health checks
* Observability tooling
---
## 8. Conditional Execution Based on Docker Availability
```python
if ping_docker:
get_containers_list()
```
### Explanation
* Ensures container operations only run if Docker is reachable.
* Prevents unhandled API errors.
This pattern is common in:
* Entry-point scripts
* Health probes
* Automation jobs
---
## 9. Container States (Conceptual Model)
Understanding container states is essential:
* `created`: container exists but is not running
* `running`: container processes are active
* `paused`: execution is suspended
* `exited`: container stopped normally
* `dead`: container failed unexpectedly
Every method in this document transitions the container between these states.
---
## 10. Summary
In this section, you learned how to:
* List running and stopped containers
* Create containers separately from starting them
* Run containers in a single step
* Control container lifecycle states
* Read container logs
* Safely execute operations based on Docker availability
This container-level control is the foundation for:
* Service orchestration
* CI/CD job execution
* Debugging and recovery automation
---
## References
Official Docker SDK for Python documentation:
* [https://docker-py.readthedocs.io/](https://docker-py.readthedocs.io/)

View File

@@ -0,0 +1,68 @@
```python
import docker
import time
docker_client = docker.DockerClient(base_url="unix://var/run/docker.sock")
docker_client.ping()
print("All Networks:\n")
all_networks = docker_client.networks.list()
for network in all_networks:
print(network.name, network.id)
print("\nNetworks Named host and bridge:\n")
system_networks = docker_client.networks.list(names=["host", "bridge"])
for network in system_networks:
print(network.name, network.id)
print("\nNetwork With Custom ID:\n")
custom_id_networks = docker_client.networks.list(
ids=["29c9e588bb8e0db6445f2a2278a1c2f42e39dc163c0a404f744dc4139fe47d21"]
)
for network in custom_id_networks:
print(network.name, network.id)
print("\nNetwork With Custom ID (Including Attributes):\n")
custom_id_networks = docker_client.networks.list(
ids=["29c9e588bb8e0db6445f2a2278a1c2f42e39dc163c0a404f744dc4139fe47d21"]
)
for network in custom_id_networks:
print(network.name, network.id, network.attrs)
print("\nNetwork With Custom Filter:\n")
filtered_networks = docker_client.networks.list(
names=["gitea_default"],
filters={"driver": "bridge"}
)
for network in filtered_networks:
if network.attrs["Driver"]:
print(network.name, network.id)
print("\nNetwork With Custom Filter (Greedy):\n")
filtered_networks = docker_client.networks.list(
names=["gitea_default"],
filters={"driver": "bridge"},
greedy=True
)
for network in filtered_networks:
if network.attrs["Driver"]:
print(network.name, network.id, network.attrs)
```
```python
```

View File

View File

View File

View File

View File

@@ -0,0 +1,100 @@
# FastAPI Environment Setup
This document describes the initial setup required to prepare a Python environment for developing a FastAPI application.
The steps below ensure isolation, dependency management, and reproducibility across environments.
---
## Prerequisites
Before starting, ensure the following are installed on your system:
* Python 3.8 or higher
* `pip` (Python package manager)
* `venv` module (included by default with most Python installations)
You can verify your Python version with:
```bash
python3 --version
```
---
## Step 1: Create a Virtual Environment
A virtual environment isolates project dependencies and prevents conflicts with system-wide Python packages.
From the project root directory, run:
```bash
python3 -m venv .venv
```
This command creates a `.venv` directory containing the isolated Python environment.
---
## Step 2: Activate the Virtual Environment
Activate the virtual environment before installing any dependencies.
### Linux / macOS
```bash
source .venv/bin/activate
```
### Windows (PowerShell)
```powershell
.venv\Scripts\Activate.ps1
```
After activation, your shell prompt should indicate that the virtual environment is active.
---
## Step 3: Install FastAPI
With the virtual environment activated, install FastAPI using `pip`:
```bash
pip install fastapi
```
This installs the FastAPI framework and its required dependencies.
> Note: In a real application, FastAPI is commonly used with an ASGI server such as `uvicorn`, which can be installed later if needed.
---
## Step 4: Freeze Dependencies
To ensure reproducibility across environments (local, CI/CD, staging, production), export the installed dependencies to a requirements file:
```bash
pip freeze > requirement.txt
```
This file should be committed to version control and used by deployment pipelines to install exact dependency versions.
---
## Resulting Files
After completing the steps above, your project directory should include:
* `.venv/` Python virtual environment (should not be committed to VCS)
* `requirement.txt` Dependency lock file
---
## Best Practices
* Always activate the virtual environment before working on the project
* Do not commit `.venv/` to source control
* Keep `requirement.txt` updated when adding or upgrading dependencies
* Use the same `requirement.txt` in CI/CD pipelines for consistent builds
---

View File

@@ -0,0 +1,90 @@
# 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.
---
## Create a Simple FastAPI Application
Create a Python file named `main.py` and add the following content:
```python
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
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.
---
## Running the Application
FastAPI applications are typically run using **uvicorn**, an ASGI server designed for high performance.
### Option 1: Run Using FastAPI CLI (Development Mode)
FastAPI provides a development-friendly CLI wrapper that uses `uvicorn` internally:
```bash
fastapi dev main.py
```
This command:
* Starts the application in development mode
* Enables auto-reload on code changes
* Automatically binds to a local development interface
---
### Option 2: Run Directly with Uvicorn (Recommended)
For explicit control over runtime configuration, run the application directly with `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
---
## Accessing the Application
Once running, the application will be available at:
* API Endpoint:
`http://localhost:1234/`
* Interactive API Docs (Swagger UI):
`http://localhost:1234/docs`
* Alternative API Docs (ReDoc):
`http://localhost:1234/redoc`
---
## Best Practices
* 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

View File

@@ -0,0 +1,169 @@
# 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.
---
## Example Application
Create or update `main.py` with the following content:
```python
from fastapi import FastAPI
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}
return {"message": "User not found"}
```
---
## Code Overview
### Application Initialization
```python
app = FastAPI()
```
Initializes the FastAPI application instance.
---
### In-Memory Data Store
```python
users = [
{"name": "abbas", "age": 20},
{"name": "mmd", "age": 37},
{"name": "asghar", "age": 19},
]
```
* Simulates a database using a Python list
* Each user is represented as a JSON-compatible dictionary
* Suitable for development and testing purposes
---
## Defined Endpoints
### Root Endpoint
```http
GET /
```
**Response:**
```json
{
"message": "API is working"
}
```
Used as a health check or readiness probe.
---
### Get All Users
```http
GET /users
```
**Response:**
```json
[
{"name": "abbas", "age": 20},
{"name": "mmd", "age": 37},
{"name": "asghar", "age": 19}
]
```
Returns the full list of users as JSON.
---
### Get User by Name (Path Parameter)
```http
GET /user/{name_input}
```
**Example Request:**
```http
GET /user/abbas
```
**Successful Response:**
```json
{
"information": {
"name": "abbas",
"age": 20
}
}
```
**Failure Response:**
```json
{
"message": "User not found"
}
```
---
## Path Parameters
* `name_input` is a dynamic path parameter
* Automatically validated and converted to `str` by FastAPI
* Used to filter data at runtime
---
## Running the Application
Use `uvicorn` to start the service:
```bash
uvicorn main:app --reload
```
---
## Best Practices
* 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

View File

@@ -0,0 +1,127 @@
# 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.
---
## Example Application (POST Request)
Extend `main.py` with the following code:
```python
from fastapi import FastAPI
app = FastAPI()
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(name: str, age: int):
new_user = {"name": name, "age": age}
users.append(new_user)
return {"msg": "User created successfully"}
```
---
## Code Overview
### POST Endpoint Definition
```python
@app.post("/new_user")
def create_user(name: str, age: int):
```
* Registers an HTTP **POST** endpoint at `/new_user`
* Accepts input parameters:
* `name` → string
* `age` → integer
* FastAPI automatically validates input types
---
### Creating a New Resource
```python
new_user = {"name": name, "age": age}
users.append(new_user)
```
* Constructs a new user object
* Appends it to the in-memory `users` list
* Simulates creating a record in a database
---
### JSON Response
```python
return {"msg": "User created successfully"}
```
* Returns a structured JSON response
* Automatically serialized by FastAPI
---
## Example Request
### Using `curl`
```bash
curl -X POST "http://localhost:8000/new_user?name=ali&age=25"
```
### Response
```json
{
"msg": "User created successfully"
}
```
---
## Verifying the Result
After creating a user, retrieve the updated list:
```http
GET /users
```
Response will now include the newly added user.
---
## Running the Application
Start the FastAPI service using `uvicorn`:
```bash
uvicorn main:app --reload
```
---
## 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

View File

@@ -0,0 +1,162 @@
# FastAPI PUT Method
This document demonstrates how to use the **HTTP PUT method** in FastAPI to update an existing resource.
It builds on previous GET and POST examples and completes a basic CRUD-style workflow.
---
## Example Application
Create or update `main.py` with the following content:
```python
from fastapi import FastAPI
app = FastAPI()
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 show_users():
return users
@app.post("/create_user")
def create_user(name: str, age: int):
new_user = {"name": name, "age": age}
users.append(new_user)
return {"msg": f"user {name} with age {age} created"}
@app.put("/update_user/{target_name}")
def update_user(target_name: str, age: int):
for user in users:
if user["name"] == target_name:
user["age"] = age
return {"msg": f"user {target_name} updated"}
return {"msg": "user not found"}
```
---
## Code Overview
### PUT Endpoint Definition
```python
@app.put("/update_user/{target_name}")
def update_user(target_name: str, age: int):
```
* Registers an HTTP **PUT** endpoint
* `target_name` is a **path parameter**
* `age` is a **query parameter**
* Used to update an existing users data
---
### Update Logic
```python
for user in users:
if user["name"] == target_name:
user["age"] = age
```
* Iterates over the in-memory users list
* Matches user by name
* Updates the `age` field in place
---
### Success Response
```json
{
"msg": "user abbas updated"
}
```
Returned when the target user exists and is updated successfully.
---
### Failure Response
```json
{
"msg": "user not found"
}
```
Returned when no matching user exists.
---
## Example Requests
### Update User Age (PUT)
```bash
curl -X PUT "http://localhost:8000/update_user/abbas?age=25"
```
### Verify Update
```http
GET /users
```
Updated response:
```json
[
{"name": "abbas", "age": 25},
{"name": "mmd", "age": 37},
{"name": "asghar", "age": 19}
]
```
---
## Running the Application
Start the service using `uvicorn`:
```bash
uvicorn main:app --reload
```
---
## HTTP Method Summary
| Method | Endpoint | Purpose |
| ------ | --------------------- | ----------------------- |
| GET | `/` | Health check |
| GET | `/users` | Retrieve all users |
| POST | `/create_user` | Create a new user |
| PUT | `/update_user/{name}` | Update an existing user |
---
## Best Practices
* Use **PUT** for full updates and **PATCH** for partial updates
* Return proper HTTP status codes (`404`, `200`, `201`)
* Avoid using in-memory data stores in production
* Use Pydantic models for request bodies instead of query parameters
* Add input validation and error handling
* Separate routes, services, and models as the project grows
* Make PUT operations idempotent

View File

@@ -0,0 +1,172 @@
# FastAPI DELETE Method (Remove Resource)
This document demonstrates how to use the **HTTP DELETE method** in FastAPI to remove an existing resource.
It completes the CRUD workflow using **GET, POST, PUT, and DELETE** operations.
---
## Example Application
Create or update `main.py` with the following content:
```python
from fastapi import FastAPI
app = FastAPI()
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 show_users():
return users
@app.post("/create_user")
def create_user(name: str, age: int):
new_user = {"name": name, "age": age}
users.append(new_user)
return {"msg": f"user {name} with age {age} created"}
@app.put("/update_user/{target_name}")
def update_user(target_name: str, age: int):
for user in users:
if user["name"] == target_name:
user["age"] = age
return {"msg": f"user {target_name} updated"}
return {"msg": "user not found"}
@app.delete("/delete_user/{target_name}")
def delete_user(target_name: str):
for user in users:
if user["name"] == target_name:
users.remove(user)
return {"msg": f"user {target_name} deleted"}
return {"msg": "user not found"}
```
---
## Code Overview
### DELETE Endpoint Definition
```python
@app.delete("/delete_user/{target_name}")
def delete_user(target_name: str):
```
* Registers an HTTP **DELETE** endpoint
* `target_name` is a **path parameter**
* Used to remove a user from the data store
---
### Delete Logic
```python
for user in users:
if user["name"] == target_name:
users.remove(user)
```
* Iterates through the users list
* Finds a matching user by name
* Removes the user from the list
---
### Success Response
```json
{
"msg": "user abbas deleted"
}
```
Returned when the user is successfully removed.
---
### Failure Response
```json
{
"msg": "user not found"
}
```
Returned when the specified user does not exist.
---
## Example Requests
### Delete a User
```bash
curl -X DELETE "http://localhost:8000/delete_user/abbas"
```
---
### Verify Deletion
```http
GET /users
```
Response:
```json
[
{"name": "mmd", "age": 37},
{"name": "asghar", "age": 19}
]
```
---
## Running the Application
Start the service with `uvicorn`:
```bash
uvicorn main:app --reload
```
---
## CRUD Endpoint Summary
| Method | Endpoint | Description |
| ------ | --------------------- | ------------------ |
| GET | `/` | Health check |
| GET | `/users` | Retrieve all users |
| POST | `/create_user` | Create a user |
| PUT | `/update_user/{name}` | Update a user |
| DELETE | `/delete_user/{name}` | Delete a user |
---
## Best Practices
* Use **DELETE** only for resource removal
* Return appropriate HTTP status codes (`204`, `404`)
* Ensure delete operations are idempotent
* Avoid modifying in-memory data in production
* Add authentication and authorization for destructive operations
* Log delete actions for auditability
* Use database transactions when deleting persistent data

View File

@@ -0,0 +1,199 @@
# FastAPI Query Parameters
This document demonstrates how to use **query parameters** in FastAPI using multiple typing styles, including:
* Native Python union types (`str | None`)
* `Optional` from `typing`
* `Annotated` with `Query` validation
---
## Example Application
Create or update `main.py` with the following content:
```python
from fastapi import FastAPI, Query
from typing import Optional, Annotated
app = FastAPI()
users = [
{"name": "abbas", "age": 20},
{"name": "abbas", "age": 32},
{"name": "abbas", "age": 54},
{"name": "abbas", "age": 15},
{"name": "mmd", "age": 37},
{"name": "asghar", "age": 19},
]
@app.get("/")
def home_page():
return {"msg": "API is working"}
@app.get("/user")
def get_users(target_name: str | None = None):
if target_name:
return [item for item in users if item["name"] == target_name]
return users
@app.get("/user2")
def get_users_optional(target_name: Optional[str] = None):
if target_name:
return [item for item in users if item["name"] == target_name]
return users
@app.get("/user3")
def get_users_annotated(
target_name: Annotated[str | None, Query(max_length=50)] = None
):
if target_name:
return [item for item in users if item["name"] == target_name]
return users
```
---
## Query Parameter Overview
Query parameters are key-value pairs appended to the URL after `?`.
**Example:**
```
/user?target_name=abbas
```
---
## Defined Endpoints
### 1. Basic Query Parameter (Python Union Type)
```python
@app.get("/user")
def get_users(target_name: str | None = None):
```
* Uses Python 3.10+ union syntax
* `target_name` is optional
* If not provided, all users are returned
**Example Request:**
```
GET /user?target_name=abbas
```
---
### 2. Optional Query Parameter (`typing.Optional`)
```python
@app.get("/user2")
def get_users_optional(target_name: Optional[str] = None):
```
* Uses `Optional[str]` for compatibility with older Python versions
* Behavior is identical to the first endpoint
**Example Request:**
```
GET /user2?target_name=abbas
```
---
### 3. Validated Query Parameter (`Annotated + Query`)
```python
@app.get("/user3")
def get_users_annotated(
target_name: Annotated[str | None, Query(max_length=50)] = None
):
```
* Uses `Annotated` for metadata binding
* Adds validation rules:
* `max_length=50`
* Automatically returns validation errors if constraints are violated
**Example Invalid Request:**
```
GET /user3?target_name=verylongnamethatexceedslimit...
```
**Response:**
```json
{
"detail": [
{
"type": "string_too_long",
"loc": ["query", "target_name"],
"msg": "String should have at most 50 characters",
"input": "..."
}
]
}
```
---
## Example Responses
### Filtered Response
```json
[
{"name": "abbas", "age": 20},
{"name": "abbas", "age": 32},
{"name": "abbas", "age": 54},
{"name": "abbas", "age": 15}
]
```
---
### Default Response (No Query Parameter)
```json
[
{"name": "abbas", "age": 20},
{"name": "abbas", "age": 32},
{"name": "abbas", "age": 54},
{"name": "abbas", "age": 15},
{"name": "mmd", "age": 37},
{"name": "asghar", "age": 19}
]
```
---
## Running the Application
Start the service using `uvicorn`:
```bash
uvicorn main:app --reload
```
---
## Best Practices
* Use query parameters for filtering and searching
* Always provide defaults for optional parameters
* Use `Query()` for validation and constraints
* Return full datasets when no filters are applied
* Avoid large in-memory datasets in production
* Use pagination for large result sets
* Combine query parameters with database queries in real systems

View File

@@ -0,0 +1,192 @@
# FastAPI HTTP Status Codes and Error Handling
This document demonstrates how to use **HTTP status codes** in FastAPI to accurately represent the result of an API operation.
Correct status codes improve API reliability, observability, and client-side behavior.
---
## Example Application
Create or update `main.py` with the following content:
```python
from fastapi import FastAPI, status, HTTPException
app = FastAPI()
users = [
{"name": "abbas", "age": 20},
{"name": "mmd", "age": 37},
{"name": "asghar", "age": 19},
]
@app.get("/", status_code=status.HTTP_200_OK)
def home_page():
return {"msg": "API is working"}
@app.get("/users", status_code=status.HTTP_200_OK)
def show_users():
return users
@app.post("/create_user", status_code=status.HTTP_201_CREATED)
def create_user(name: str, age: int):
new_user = {"name": name, "age": age}
users.append(new_user)
return {"msg": f"user {name} with age {age} created"}
@app.put("/update_user/{target_name}", status_code=status.HTTP_202_ACCEPTED)
def update_user(target_name: str, age: int):
for user in users:
if user["name"] == target_name:
user["age"] = age
return {"msg": f"user {target_name} updated"}
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found"
)
@app.delete("/delete_user/{target_name}", status_code=status.HTTP_204_NO_CONTENT)
def delete_user(target_name: str):
for user in users:
if user["name"] == target_name:
users.remove(user)
return
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found"
)
```
---
## Status Code Overview
HTTP status codes communicate the result of an API request to clients and monitoring systems.
| Code | Meaning | Usage |
| ---- | ---------- | --------------------------------- |
| 200 | OK | Successful GET requests |
| 201 | Created | Resource successfully created |
| 202 | Accepted | Update request accepted |
| 204 | No Content | Resource deleted successfully |
| 404 | Not Found | Requested resource does not exist |
---
## Endpoint Behavior
### Root Endpoint
```http
GET /
```
* Returns HTTP **200 OK**
* Used as a health check
---
### Create User
```http
POST /create_user
```
* Returns HTTP **201 Created**
* Indicates successful resource creation
---
### Update User
```http
PUT /update_user/{target_name}
```
* Returns HTTP **202 Accepted** on success
* Raises HTTP **404 Not Found** if user does not exist
---
### Delete User
```http
DELETE /delete_user/{target_name}
```
* Returns HTTP **204 No Content** on success
* Returns no response body
* Raises HTTP **404 Not Found** if user does not exist
---
## Error Handling with `HTTPException`
```python
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="User not found"
)
```
* Immediately stops request processing
* Returns structured error responses
* Automatically serialized by FastAPI
**Error Response Example:**
```json
{
"detail": "User not found"
}
```
---
## Example Requests
### Create User
```bash
curl -X POST "http://localhost:8000/create_user?name=ali&age=25"
```
### Update User
```bash
curl -X PUT "http://localhost:8000/update_user/ali?age=30"
```
### Delete User
```bash
curl -X DELETE "http://localhost:8000/delete_user/ali"
```
---
## Running the Application
Start the application using `uvicorn`:
```bash
uvicorn main:app --reload
```
---
## Best Practices
* Always return meaningful HTTP status codes
* Use `status` module instead of hard-coded numbers
* Use `HTTPException` for predictable error handling
* Do not return response bodies with `204 No Content`
* Align status codes with REST conventions
* Ensure monitoring systems rely on status codes, not messages
* Standardize error formats across services

View File

@@ -0,0 +1,122 @@
# 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,238 @@
# FastAPI Advanced Path and Query Parameters
This document demonstrates advanced usage of **path parameters** and **query parameters** in FastAPI, including:
* Validation rules
* Aliases
* Descriptions for OpenAPI
* Deprecation flags
* Clear separation of responsibilities between path and query parameters
---
## Example Application
Create or update `main.py` with the following content:
```python
from fastapi import FastAPI, Query, Path, status
from fastapi.responses import JSONResponse
app = FastAPI()
users_db = [
{"id": "1", "name": "radin"}
]
@app.get("/user/{target_id}")
def get_user_by_path(
target_id: int = Path(
...,
alias="User ID",
description="Enter target unique ID",
deprecated=True,
)
):
for item in users_db:
if int(item["id"]) == target_id:
return JSONResponse(
content={"msg": f"Your target user name is {item['name']}"},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={"msg": "user not found"},
status_code=status.HTTP_404_NOT_FOUND,
)
@app.get("/user")
def get_user_by_query(
target: int | None = Query(
default=None,
gt=0,
alias="User ID",
description="Enter target unique ID",
)
):
for item in users_db:
if item["id"] == str(target):
return JSONResponse(
content={"msg": f"Your target user name is {item['name']}"},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={"msg": "user not found"},
status_code=status.HTTP_404_NOT_FOUND,
)
```
---
## Path Parameter Example
### Endpoint
```http
GET /user/{target_id}
```
**Example Request:**
```
/user/1
```
### Characteristics
* Always required
* Defined as part of the route
* Used to identify a specific resource
* Missing value results in **404 Not Found**
* Supports validation, aliases, and documentation metadata
---
## Query Parameter Example
### Endpoint
```http
GET /user?User%20ID=1
```
### Characteristics
* Optional by default
* Used for filtering and searching
* Not part of the route path
* Supports validation and documentation metadata
* Uses default values when not provided
---
## Advanced Parameter Configuration
### `Path()` Example
```python
Path(
...,
alias="User ID",
description="Enter target unique ID",
deprecated=True
)
```
* `...` → parameter is required
* `alias` → custom name in documentation and URL
* `description` → shown in Swagger UI
* `deprecated` → marked as deprecated in OpenAPI
---
### `Query()` Example
```python
Query(
default=None,
gt=0,
alias="User ID",
description="Enter target unique ID"
)
```
* `gt=0` → value must be greater than zero
* Optional parameter with validation rules
* Appears in API documentation
---
## Path vs Query Parameters
### 1. Path Parameters
**What they are**
Values embedded directly in the URL path that identify a specific resource.
**When to use**
When the parameter is mandatory and uniquely identifies a resource.
**Example URL**
```
/users/42
```
**FastAPI Example**
```python
@app.get("/users/{user_id}")
def get_user(user_id: int):
return {"user_id": user_id}
```
**Key Points**
* Always required
* Part of the route definition
* Used for IDs and unique identifiers
* Missing value → 404 error
---
### 2. Query Parameters
**What they are**
Key-value pairs appended to the URL after `?`.
**When to use**
For optional filtering, searching, sorting, and pagination.
**Example URL**
```
/users?limit=10&active=true
```
**FastAPI Example**
```python
@app.get("/users")
def list_users(limit: int = 10, active: bool = True):
return {"limit": limit, "active": active}
```
**Key Points**
* Optional by default
* Not part of the route path
* Used to modify or filter results
* Defaults are used when missing
---
## Side-by-Side Comparison
| Feature | Path Parameter | Query Parameter |
| ------------- | ------------------- | --------------------------------- |
| Location | Inside URL path | After `?` |
| Required | Yes | No (by default) |
| Purpose | Identify a resource | Filter or modify results |
| Example | `/items/5` | `/items?limit=10` |
| Missing Value | 404 Not Found | Default value or validation error |
---
## Best Practices
* Use path parameters for resource identification
* Use query parameters for filtering and modifiers
* Avoid spaces in parameter aliases for production APIs
* Deprecate parameters instead of removing them
* Use validation (`gt`, `lt`, `regex`) for safer APIs
* Keep URL design consistent across services
* Prefer response models over manual JSON responses when possible

View File

@@ -0,0 +1,226 @@
# POST Request Types and Content Types
This document explains the **body types of POST requests** and the most common **Content-Types** used in APIs.
Understanding these formats is essential for building interoperable and production-ready FastAPI services.
---
## POST Request Body Types
A POST request sends data to the server in the **request body**.
The format of this data is defined by the **Content-Type** header.
---
## 1. Form Data
### Description
Used primarily for HTML form submissions. Common in browser-based applications.
### Content-Type
```
application/x-www-form-urlencoded
```
or
```
multipart/form-data
```
### Characteristics
* Key-value pairs
* Supports file uploads (multipart)
* Common in login and upload forms
### Example
```http
POST /login
Content-Type: application/x-www-form-urlencoded
username=admin&password=secret
```
---
## 2. JSON
### Description
The most common data format for REST APIs.
### Content-Type
```
application/json
```
### Characteristics
* Structured, readable, and language-independent
* Easily parsed and validated
* Default choice for FastAPI APIs
### Example
```json
{
"name": "abbas",
"age": 25
}
```
---
## 3. XML
### Description
An older but still widely used data format in enterprise systems and legacy APIs.
### Content-Type
```
application/xml
```
or
```
text/xml
```
### Characteristics
* Verbose and schema-driven
* Common in SOAP-based services
* Less common in modern REST APIs
### Example
```xml
<user>
<name>abbas</name>
<age>25</age>
</user>
```
---
## 4. Plain Text
### Description
Used when sending raw text without structure.
### Content-Type
```
text/plain
```
### Characteristics
* No schema or structure
* Useful for logs, messages, or simple payloads
* Requires custom parsing on the server
### Example
```
Hello FastAPI
```
---
## 5. Binary Data
### Description
Used for sending non-textual data such as images, videos, or files.
### Content-Type
```
application/octet-stream
```
### Characteristics
* Raw binary format
* Common for file uploads and downloads
* Requires stream handling
### Example
```
(binary file data)
```
---
## 6. GraphQL
### Description
GraphQL uses POST requests to execute queries and mutations.
### Content-Type
```
application/json
```
### Characteristics
* Single endpoint
* Flexible client-driven queries
* Requires GraphQL server support
### Example
```json
{
"query": "query { users { id name } }"
}
```
---
## Common Content Types Summary
| Content-Type | Usage |
| ----------------------------------- | -------------------------- |
| `application/json` | REST APIs (default) |
| `application/x-www-form-urlencoded` | HTML forms |
| `multipart/form-data` | Forms with file uploads |
| `application/xml` | Legacy / SOAP APIs |
| `text/plain` | Raw text |
| `application/octet-stream` | Binary data |
| `application/graphql` | GraphQL (rare, often JSON) |
---
## FastAPI Considerations
* JSON is the recommended default for FastAPI
* Use Pydantic models for JSON validation
* Use `Form()` and `File()` for form and file uploads
* Always validate content type in production APIs
* Document supported content types clearly
---
## Best Practices
* Choose the simplest format that meets requirements
* Prefer `application/json` for APIs
* Avoid XML unless required by integration
* Secure file uploads (size limits, scanning)
* Validate all incoming request bodies
* Be explicit about supported Content-Types

View File

@@ -0,0 +1,165 @@
# FastAPI POST Requests with Form Data
This document demonstrates how to handle **form-based POST requests** in FastAPI using the `Form()` dependency.
Form data is commonly used in **HTML forms**, authentication flows, and legacy systems.
---
## Example Application
Create or update `main.py` with the following content:
```python
from fastapi import FastAPI, Form, status
from fastapi.responses import JSONResponse
app = FastAPI()
users_db = [
{"id": "1", "name": "radin", "password": "123"}
]
@app.post("/user/")
def get_user_from_form(
target: int = Form(
...,
gt=0,
alias="User ID",
description="Enter target unique ID",
)
):
for item in users_db:
if item["id"] == str(target):
return JSONResponse(
content={"msg": f"Your target user name is {item['name']}"},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={"msg": "user not found"},
status_code=status.HTTP_404_NOT_FOUND,
)
```
---
## Form Data Overview
### What is Form Data
Form data is sent in the request body using:
```
Content-Type: application/x-www-form-urlencoded
```
or
```
multipart/form-data
```
FastAPI requires the `Form()` dependency to explicitly declare form inputs.
---
## Endpoint Behavior
### Endpoint
```http
POST /user/
```
### Request Body (Form Data)
```
User ID=1
```
### Example Using `curl`
```bash
curl -X POST "http://localhost:8000/user/" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "User ID=1"
```
---
## Response Examples
### Success Response
```json
{
"msg": "Your target user name is radin"
}
```
Status Code: **200 OK**
---
### Failure Response
```json
{
"msg": "user not found"
}
```
Status Code: **404 Not Found**
---
## `Form()` Parameter Configuration
```python
Form(
...,
gt=0,
alias="User ID",
description="Enter target unique ID"
)
```
| Parameter | Description |
| ------------- | ------------------------------- |
| `...` | Field is required |
| `gt=0` | Value must be greater than zero |
| `alias` | Custom form field name |
| `description` | Displayed in API docs |
---
## Swagger / OpenAPI Behavior
* Form fields appear as input fields
* Aliases are reflected in the UI
* Validation rules are enforced automatically
* Errors are returned with clear messages
---
## Running the Application
Start the service using `uvicorn`:
```bash
uvicorn main:app --reload
```
---
## Best Practices
* Use form data only when required (e.g. HTML forms)
* Prefer JSON for APIs and services
* Avoid exposing sensitive fields in plain form data
* Use HTTPS for all form submissions
* Validate and sanitize all inputs
* Use authentication and hashing for passwords
* Do not store credentials in plain text

View File

@@ -0,0 +1,161 @@
# FastAPI POST Requests with JSON Body (`Body`)
This document demonstrates how to receive data from the **request body** using `Body()` in FastAPI.
This approach is commonly used when clients send **JSON payloads**.
---
## Example Application
Create or update `main.py` with the following content:
```python
from fastapi import FastAPI, Body, status
from fastapi.responses import JSONResponse
app = FastAPI()
users_db = [
{"id": "1", "name": "radin", "password": "123"}
]
@app.post("/user/")
def get_user_from_body(
target: int = Body(
...,
embed=True,
gt=0,
alias="User ID",
description="Enter target unique ID",
)
):
for item in users_db:
if item["id"] == str(target):
return JSONResponse(
content={"msg": f"Your target user name is {item['name']}"},
status_code=status.HTTP_200_OK,
)
return JSONResponse(
content={"msg": "user not found"},
status_code=status.HTTP_404_NOT_FOUND,
)
```
---
## JSON Body Overview
### What Is a Request Body
The request body contains structured data sent by the client, most commonly as **JSON**.
**Content-Type:**
```
application/json
```
---
## Request Format
### Example JSON Payload
```json
{
"User ID": 1
}
```
* `embed=True` requires the value to be wrapped inside a JSON object
* The key name is controlled by the `alias`
---
## Example Request Using `curl`
```bash
curl -X POST "http://localhost:8000/user/" \
-H "Content-Type: application/json" \
-d '{"User ID": 1}'
```
---
## Response Examples
### Success Response
```json
{
"msg": "Your target user name is radin"
}
```
Status Code: **200 OK**
---
### Failure Response
```json
{
"msg": "user not found"
}
```
Status Code: **404 Not Found**
---
## `Body()` Parameter Configuration
```python
Body(
...,
embed=True,
gt=0,
alias="User ID",
description="Enter target unique ID"
)
```
| Parameter | Purpose |
| ------------- | -------------------------------- |
| `...` | Field is required |
| `embed=True` | Wraps the value in a JSON object |
| `gt=0` | Validates input value |
| `alias` | Custom JSON key name |
| `description` | Shown in API documentation |
---
## Swagger / OpenAPI Behavior
* JSON schema is automatically generated
* Validation errors are returned if rules are violated
* Aliases and descriptions appear in Swagger UI
* Request body is clearly documented
---
## Running the Application
Start the service using `uvicorn`:
```bash
uvicorn main:app --reload
```
---
## Best Practices
* Prefer request body over query parameters for POST requests
* Use Pydantic models instead of raw `Body()` for complex payloads
* Keep JSON structures consistent
* Avoid spaces in JSON keys for production APIs
* Never send sensitive data in plain text
* Use HTTPS for all JSON-based APIs

View File

@@ -0,0 +1,167 @@
# 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.
---
## 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 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.
Returns the size of the uploaded file.
"""
return {"file_size": len(file)}
@app.post("/uploadfile")
def upload_file_uploadfile(file: UploadFile):
"""
Receive file as UploadFile.
Returns filename, content type, and size.
"""
content = file.read()
return {
"filename": file.filename,
"content_type": file.content_type,
"file_size": len(content)
}
@app.post("/uploadmultifile")
def upload_multiple_files(files: List[UploadFile]):
"""
Receive multiple files as UploadFile list.
Returns filenames and content types.
"""
return [
{"filename": file.filename, "content_type": file.content_type}
for file in files
]
```
---
## File Upload Methods
### 1. `File` as Bytes
* Accepts the uploaded file as raw bytes
* Suitable for small files or direct in-memory processing
* Fast but lacks metadata (filename, content type)
**Example Request (curl):**
```bash
curl -X POST "http://localhost:8000/file" \
-F "file=@example.txt"
```
**Response:**
```json
{
"file_size": 128
}
```
---
### 2. `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)
**Example Request (curl):**
```bash
curl -X POST "http://localhost:8000/uploadfile" \
-F "file=@example.txt"
```
**Response:**
```json
{
"filename": "example.txt",
"content_type": "text/plain",
"file_size": 128
}
```
---
### 3. Multiple File Uploads
* Accepts a list of `UploadFile`
* Allows uploading multiple files in one request
* Useful for batch uploads or form submissions
**Example Request (curl):**
```bash
curl -X POST "http://localhost:8000/uploadmultifile" \
-F "files=@file1.txt" \
-F "files=@file2.txt"
```
**Response:**
```json
[
{"filename": "file1.txt", "content_type": "text/plain"},
{"filename": "file2.txt", "content_type": "text/plain"}
]
```
---
## Content-Type
For file uploads, the request must include:
```
Content-Type: multipart/form-data
```
* Each file is sent as a separate part in the multipart request
---
## Running the Application
Start the service using `uvicorn`:
```bash
uvicorn main:app --reload
```
---
## Best Practices
* 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

View File

@@ -0,0 +1,121 @@
# FastAPI Application Lifespan (Startup & 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.
---
## Deprecated Method: `@app.on_event`
Older FastAPI versions use the `@app.on_event` decorator for lifecycle events:
```python
from fastapi import FastAPI
app = FastAPI()
@app.on_event("startup")
def on_startup():
print("App is loading")
@app.on_event("shutdown")
def on_shutdown():
print("App is shutting down")
```
### Characteristics
* `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
---
## Recommended Modern Approach: `lifespan` with `asynccontextmanager`
FastAPI now recommends using the `lifespan` parameter in the `FastAPI` constructor.
This uses Python's `asynccontextmanager` to define a **single lifecycle context**.
```python
from fastapi import FastAPI
from contextlib import asynccontextmanager
@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
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
---
## Example: Using Lifespan for Database Initialization
```python
from fastapi import FastAPI
from contextlib import asynccontextmanager
@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)
```
* `app.state` is used to store shared resources
* Clean startup and shutdown handling
* Ensures proper resource cleanup
---
## Benefits of the Lifespan Approach
* 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`:
```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
---
## Best Practices
* 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
---
This approach provides a **modern, production-ready pattern** for managing application startup and shutdown events in FastAPI.

View File

@@ -1,12 +0,0 @@
```bash
python3 -m venv .venv
```
```bash
pip install fastapi
```
```bash
pip freeze > requirment.txt
```

View File

@@ -1,21 +0,0 @@
```python
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def home_dir():
return {"message": "Home Pag"}
```
```bash
fastapi dev main.py
```
use uvicorn as defualt runner
or
we can run with uvicorn command
```bash
uvicorn main:app --reload --host 0.0.0.0 --port 1234
```

View File

@@ -1,27 +0,0 @@
```python
from fastapi import FastAPI
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 home_dir():
return users
@app.get("/user/{name_input}")
def read_item(name_input: str):
for item in users:
if item["name"] == name_input:
return {"information": item}
return {"message" , "not worked"}
```