From ef46853bca768424ddbc11bbbd00cd48a3178149 Mon Sep 17 00:00:00 2001 From: NEFORCEO Date: Thu, 26 Mar 2026 15:34:08 +0700 Subject: [PATCH] update 7 files, delete 14 files and create 18 files --- docs/en/api-reference.md | 133 +++++++++++++++++++---- docs/en/cli.md | 48 --------- docs/en/concepts/asgi.md | 70 ++++++++++++ docs/en/concepts/lifespan.md | 93 ++++++++++++++++ docs/en/concepts/websockets.md | 66 ++++++++++++ docs/en/configuration.md | 47 --------- docs/en/contributing.md | 83 +++++++++++++++ docs/en/dependencies.md | 18 ---- docs/en/deployment/docker.md | 166 +++++++++++++++++++++++++++++ docs/en/deployment/index.md | 163 ++++++++++++++++++++++++++++ docs/en/examples.md | 188 --------------------------------- docs/en/index.md | 76 +++++++++---- docs/en/installation.md | 28 +++++ docs/en/middleware.md | 35 ------ docs/en/quick-start.md | 40 ------- docs/en/security.md | 42 -------- docs/en/server-behavior.md | 82 ++++++++++++++ docs/en/settings.md | 106 +++++++++++++++++++ docs/index.md | 79 ++++++++++---- docs/ru/api-reference.md | 133 ++++++++++++++++++----- docs/ru/cli.md | 48 --------- docs/ru/concepts/asgi.md | 70 ++++++++++++ docs/ru/concepts/lifespan.md | 93 ++++++++++++++++ docs/ru/concepts/websockets.md | 66 ++++++++++++ docs/ru/configuration.md | 47 --------- docs/ru/contributing.md | 83 +++++++++++++++ docs/ru/dependencies.md | 18 ---- docs/ru/deployment/docker.md | 166 +++++++++++++++++++++++++++++ docs/ru/deployment/index.md | 163 ++++++++++++++++++++++++++++ docs/ru/examples.md | 188 --------------------------------- docs/ru/index.md | 73 ++++++++++--- docs/ru/installation.md | 28 +++++ docs/ru/middleware.md | 35 ------ docs/ru/quick-start.md | 40 ------- docs/ru/security.md | 42 -------- docs/ru/server-behavior.md | 82 ++++++++++++++ docs/ru/settings.md | 106 +++++++++++++++++++ mkdocs.yml | 159 ++++++++++++++++------------ uv.lock | 7 +- 39 files changed, 2200 insertions(+), 1010 deletions(-) delete mode 100644 docs/en/cli.md create mode 100644 docs/en/concepts/asgi.md create mode 100644 docs/en/concepts/lifespan.md create mode 100644 docs/en/concepts/websockets.md delete mode 100644 docs/en/configuration.md create mode 100644 docs/en/contributing.md delete mode 100644 docs/en/dependencies.md create mode 100644 docs/en/deployment/docker.md create mode 100644 docs/en/deployment/index.md delete mode 100644 docs/en/examples.md create mode 100644 docs/en/installation.md delete mode 100644 docs/en/middleware.md delete mode 100644 docs/en/quick-start.md delete mode 100644 docs/en/security.md create mode 100644 docs/en/server-behavior.md create mode 100644 docs/en/settings.md delete mode 100644 docs/ru/cli.md create mode 100644 docs/ru/concepts/asgi.md create mode 100644 docs/ru/concepts/lifespan.md create mode 100644 docs/ru/concepts/websockets.md delete mode 100644 docs/ru/configuration.md create mode 100644 docs/ru/contributing.md delete mode 100644 docs/ru/dependencies.md create mode 100644 docs/ru/deployment/docker.md create mode 100644 docs/ru/deployment/index.md delete mode 100644 docs/ru/examples.md create mode 100644 docs/ru/installation.md delete mode 100644 docs/ru/middleware.md delete mode 100644 docs/ru/quick-start.md delete mode 100644 docs/ru/security.md create mode 100644 docs/ru/server-behavior.md create mode 100644 docs/ru/settings.md diff --git a/docs/en/api-reference.md b/docs/en/api-reference.md index fcc38fd..2483d0d 100644 --- a/docs/en/api-reference.md +++ b/docs/en/api-reference.md @@ -1,50 +1,137 @@ # API Reference -## Config +## Command Line Interface + +### ncorn + +```bash +ncorn module:app [OPTIONS] +``` + +Main entry point for running ncorn server. + +### ncorn config + +```bash +ncorn config +``` + +Creates default `ncorn.json` configuration file. + +## Python API + +### Config ```python from ncorn.config import Config +``` + +Configuration class for ncorn server. +```python config = Config( host="127.0.0.1", port=8000, workers=1, reload=False, - max_body_size=16777216, - header_timeout=30.0, - body_timeout=60.0, - keepalive_timeout=5.0, - max_headers=100, - max_keepalive_requests=100, - rate_limit_requests=100, - rate_limit_window=60.0, + max_body_size=16 * 1024 * 1024, + ssl_keyfile=None, + ssl_certfile=None, + ssl_version=5, ) ``` -## HTTPServer +#### Parameters + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `host` | str | "127.0.0.1" | IP address to bind | +| `port` | int | 8000 | Port number | +| `workers` | int | 1 | Number of worker processes | +| `reload` | bool | False | Enable auto-reload | +| `max_body_size` | int | 16777216 | Max request body size | +| `max_header_size` | int | 8192 | Max single header size | +| `max_headers_total_size` | int | 65536 | Max total headers size | +| `header_timeout` | float | 30.0 | Header read timeout | +| `body_timeout` | float | 60.0 | Body read timeout | +| `request_timeout` | float | 10.0 | Request processing timeout | +| `keepalive_timeout` | float | 5.0 | Keep-alive timeout | +| `keepalive_requests` | int | 100 | Max requests per connection | +| `max_headers` | int | 100 | Max number of headers | +| `max_connections` | int | 1000 | Max concurrent connections | +| `max_connections_per_ip` | int | 50 | Max connections per IP | +| `rate_limit_requests` | int | 100 | Requests per window | +| `rate_limit_window` | float | 60.0 | Rate limit window | +| `ssl_keyfile` | str | None | SSL key file path | +| `ssl_certfile` | str | None | SSL certificate path | +| `ssl_version` | int | 5 | TLS version (2-5) | + +### HTTPServer ```python from ncorn.server import HTTPServer -from ncorn.config import Config -from myapp import app +``` -config = Config(host="0.0.0.0", port=8080) -server = HTTPServer(app, config) +HTTP server class. -# Start server +```python +server = HTTPServer(app, config) await server.start() - -# Stop server await server.stop() ``` -## Logger +#### Methods + +##### start(show_banner=True) + +Start the HTTP server. + +##### stop() + +Gracefully stop the server. + +### CLI Functions ```python -from ncorn.logging import logger +from ncorn.cli import import_app, parse_args, main +``` + +#### import_app(app_spec: str) + +Import FastAPI app from "module:app" string. + +#### parse_args(args: Optional[list[str]] = None) -> argparse.Namespace + +Parse command line arguments. + +#### main(args: Optional[list[str]] = None) -> None + +Main entry point. + +### Middleware -logger.info("Message") -logger.warning("Message") -logger.error("Message") -logger.success("Message") +```python +from ncorn.middleware import ( + ValidationMiddleware, + RateLimitMiddleware, + MiddlewareChain, +) ``` + +#### ValidationMiddleware + +Validates HTTP requests (headers, body size). + +#### RateLimitMiddleware + +Implements IP-based rate limiting. + +#### MiddlewareChain + +Chains multiple middleware together. + +## Exceptions + +### ncorn exceptions + +ncorn uses standard Python exceptions. Check individual middleware documentation for specific error handling. diff --git a/docs/en/cli.md b/docs/en/cli.md deleted file mode 100644 index f00b326..0000000 --- a/docs/en/cli.md +++ /dev/null @@ -1,48 +0,0 @@ -# CLI Reference - -## Basic Command - -```bash -ncorn module:app -``` - -## Options - -| Option | Description | Default | -|--------|-------------|---------| -| `app` | Application in format 'module:app' | Required | -| `--host` | Host to bind to | 127.0.0.1 | -| `--port` | Port to bind to | 8000 | -| `--reload` | Enable auto-reload on file changes | false | -| `--workers` | Number of worker processes | 1 | -| `--max-body-size` | Maximum request body size in bytes | 16777216 | -| `--header-timeout` | Header read timeout in seconds | 30.0 | -| `--rate-limit` | Rate limit requests per window | 100 | -| `--rate-limit-window` | Rate limit window in seconds | 60.0 | -| `--verbose` | Enable verbose logging | false | - -## Examples - -Run with custom host and port: - -```bash -ncorn example_app:app --host 0.0.0.0 --port 9000 -``` - -Run with auto-reload: - -```bash -ncorn example_app:app --reload -``` - -Run with multiple workers: - -```bash -ncorn example_app:app --workers 4 -``` - -Run with custom rate limiting: - -```bash -ncorn example_app:app --rate-limit 50 --rate-limit-window 30 -``` diff --git a/docs/en/concepts/asgi.md b/docs/en/concepts/asgi.md new file mode 100644 index 0000000..6ee9429 --- /dev/null +++ b/docs/en/concepts/asgi.md @@ -0,0 +1,70 @@ +# ASGI + +ASGI (Asynchronous Server Gateway Interface) is a standard interface between Python web servers and applications. + +## Overview + +ASGI is a specification that describes how async web applications should communicate with web servers. It was designed to replace WSGI (PEP 333) for async frameworks. + +## Key Concepts + +### Scope + +The `scope` is a dictionary containing information about the connection: + +```python +{ + "type": "http", + "method": "GET", + "path": "/", + "query_string": b"", + "headers": [(b"host", b"localhost")], + "client": ("127.0.0.1", 8000), + "server": ("127.0.0.1", 8000), + "scheme": "http", +} +``` + +### Receive + +The `receive` callable waits for incoming data: + +```python +message = await receive() +# Returns: {"type": "http.request", "body": b"...", "more_body": bool} +``` + +### Send + +The `send` callable sends response data: + +```python +# Start response +await send({ + "type": "http.response.start", + "status": 200, + "headers": [(b"content-type", b"application/json")], +}) + +# Send body +await send({ + "type": "http.response.body", + "body": b'{"message": "hello"}', +}) +``` + +## HTTP Types + +- `http` - Regular HTTP/1.1 connections +- `websocket` - WebSocket connections +- `lifespan` - Application lifecycle events + +## ncorn ASGI Implementation + +ncorn implements a full ASGI server: + +- Parses HTTP/1.1 requests +- Builds ASGI scope dictionary +- Handles request/response lifecycle +- Supports keep-alive connections +- Implements HTTP/1.1 only (WebSocket coming soon) diff --git a/docs/en/concepts/lifespan.md b/docs/en/concepts/lifespan.md new file mode 100644 index 0000000..9daeb4c --- /dev/null +++ b/docs/en/concepts/lifespan.md @@ -0,0 +1,93 @@ +# Lifespan + +The lifespan protocol allows applications to perform startup and shutdown tasks. + +## Overview + +The lifespan protocol is part of ASGI and enables applications to: + +- Initialize resources on startup +- Clean up resources on shutdown + +## Usage with FastAPI + +FastAPI handles lifespan automatically, but you can define custom handlers: + +```python +from contextlib import asynccontextmanager +from fastapi import FastAPI + +@asynccontextmanager +async def lifespan(app: FastAPI): + # Startup + print("Starting up...") + await connect_to_database() + + yield + + # Shutdown + print("Shutting down...") + await close_database() + +app = FastAPI(lifespan=lifespan) +``` + +## Manual ASGI Implementation + +If you're implementing ASGI directly: + +```python +async def app(scope, receive, send): + if scope["type"] == "lifespan": + while True: + message = await receive() + + if message["type"] == "lifespan.startup": + # Initialize resources + await send({"type": "lifespan.startup.complete"}) + + elif message["type"] == "lifespan.shutdown": + # Clean up resources + await send({"type": "lifespan.shutdown.complete"}) + break +``` + +## ncorn Lifespan + +ncorn fully supports the lifespan protocol: + +- Calls startup events when server starts +- Calls shutdown events when server stops +- Handles graceful shutdown properly + +## Startup Event + +Triggered when the server is ready to accept connections: + +```python +{"type": "lifespan.startup"} +``` + +Your app should respond with: + +```python +{"type": "lifespan.startup.complete"} +# or +{"type": "lifespan.startup.failed", "message": "error reason"} +``` + +## Shutdown Event + +Triggered when the server is shutting down: + +```python +{"type": "lifespan.shutdown"} +``` + +Your app should respond with: + +```python +{"type": "lifespan.shutdown.complete"} +# or +{"type": "lifespan.shutdown.failed", "message": "error reason"} +``` diff --git a/docs/en/concepts/websockets.md b/docs/en/concepts/websockets.md new file mode 100644 index 0000000..a6e7af2 --- /dev/null +++ b/docs/en/concepts/websockets.md @@ -0,0 +1,66 @@ +# WebSockets + +WebSockets provide full-duplex communication between client and server. + +## Status + +!!! warning "Coming Soon" + WebSocket support is planned for a future release. + +Currently, ncorn supports HTTP/1.1 only. WebSocket support will be added in a future version. + +## What are WebSockets? + +WebSockets differ from HTTP: + +- **HTTP**: Request-response model +- **WebSocket**: Bidirectional, persistent connection + +## ASGI WebSocket Scope + +```python +{ + "type": "websocket", + "path": "/ws", + "query_string": b"", + "headers": [...], + "client": ("127.0.0.1", 8000), + "server": ("127.0.0.1", 8000), + "subprotocols": [], + "asgi": {"version": "3.0"}, +} +``` + +## WebSocket Messages + +### Connect + +```python +{"type": "websocket.connect"} +``` + +### Receive + +```python +{"type": "websocket.receive", "text": "hello"} +# or +{"type": "websocket.receive", "bytes": b"hello"} +``` + +### Send + +```python +{"type": "websocket.send", "text": "hello"} +# or +{"type": "websocket.send", "bytes": b"hello"} +``` + +### Disconnect + +```python +{"type": "websocket.disconnect", "code": 1000} +``` + +## Alternative + +For now, you can use uvicorn alongside ncorn for WebSocket support, or use a reverse proxy that handles WebSocket upgrading. diff --git a/docs/en/configuration.md b/docs/en/configuration.md deleted file mode 100644 index b940d4c..0000000 --- a/docs/en/configuration.md +++ /dev/null @@ -1,47 +0,0 @@ -# Configuration - -## Server Configuration - -The server can be configured using command line options or programmatically. - -## Configuration Options - -### Network Settings - -- `host` - IP address to bind to (default: 127.0.0.1) -- `port` - Port number (default: 8000) -- `workers` - Number of worker processes (default: 1) - -### Timeouts - -- `header_timeout` - Maximum time to read request headers (default: 30.0 seconds) -- `body_timeout` - Maximum time to read request body (default: 60.0 seconds) -- `keepalive_timeout` - Keep-alive connection timeout (default: 5.0 seconds) - -### Request Limits - -- `max_body_size` - Maximum request body size (default: 16 MB) -- `max_headers` - Maximum number of headers (default: 100) -- `max_keepalive_requests` - Maximum requests per keep-alive connection (default: 100) - -### Rate Limiting - -- `rate_limit_requests` - Maximum requests per window (default: 100) -- `rate_limit_window` - Time window in seconds (default: 60.0) - -## Programmatic Configuration - -```python -from ncorn.config import Config -from ncorn.server import HTTPServer -from myapp import app - -config = Config( - host="0.0.0.0", - port=8080, - workers=4, - max_body_size=32 * 1024 * 1024, -) - -server = HTTPServer(app, config) -``` diff --git a/docs/en/contributing.md b/docs/en/contributing.md new file mode 100644 index 0000000..87124a7 --- /dev/null +++ b/docs/en/contributing.md @@ -0,0 +1,83 @@ +# Contributing + +Thank you for your interest in contributing to ncorn! + +## Development Setup + +1. Clone the repository: +```bash +git clone https://github.com/ndugram/ncorn.git +cd ncorn +``` + +2. Create a virtual environment: +```bash +python -m venv venv +source venv/bin/activate # On Windows: venv\Scripts\activate +``` + +3. Install development dependencies: +```bash +pip install -e . +pip install pytest httpx +``` + +## Code Style + +- Follow PEP 8 +- Use type hints +- Add docstrings using `annotated_doc` + +## Testing + +Run tests: +```bash +pytest +``` + +Run with coverage: +```bash +pytest --cov=ncorn --cov-report=html +``` + +## Project Structure + +``` +ncorn/ +├── __init__.py # Package init +├── cli.py # Command line interface +├── config.py # Configuration class +├── config_file.py # Config file loading +├── logging.py # Logging utilities +├── main.py # Main entry point +├── protocol.py # HTTP protocol parser +├── reload.py # Auto-reload functionality +├── server.py # HTTP server +├── middleware/ # Middleware modules +│ ├── base.py +│ ├── ipfilter.py +│ ├── ratelimit.py +│ ├── security.py +│ ├── validation.py +│ └── waf.py +└── asgi.py # ASGI adapter +``` + +## Pull Request Process + +1. Fork the repository +2. Create a feature branch (`git checkout -b feature/amazing-feature`) +3. Make your changes +4. Add tests if applicable +5. Ensure all tests pass +6. Commit your changes (`git commit -m 'Add amazing feature'`) +7. Push to the branch (`git push origin feature/amazing-feature`) +8. Open a Pull Request + +## Reporting Issues + +Please report bugs and feature requests via GitHub Issues. + +## License + +By contributing, you agree that your contributions will be licensed under the MIT License. diff --git a/docs/en/dependencies.md b/docs/en/dependencies.md deleted file mode 100644 index 59d4563..0000000 --- a/docs/en/dependencies.md +++ /dev/null @@ -1,18 +0,0 @@ -# Dependencies - -ncorn has minimal dependencies: - -- `httptools` - HTTP parsing -- `rich` - Colored logging - -## Installation - -```bash -pip install ncorn -``` - -## Development Dependencies - -```bash -pip install -e ".[dev]" -``` diff --git a/docs/en/deployment/docker.md b/docs/en/deployment/docker.md new file mode 100644 index 0000000..d7500cb --- /dev/null +++ b/docs/en/deployment/docker.md @@ -0,0 +1,166 @@ +# Docker + +ncorn can be containerized using Docker for easy deployment. + +## Basic Dockerfile + +```dockerfile +FROM python:3.11-slim + +WORKDIR /app + +# Install ncorn +RUN pip install ncorn + +# Copy application +COPY . . + +# Run ncorn +CMD ["ncorn", "app:app", "--host", "0.0.0.0", "--port", "8000"] +``` + +## Building and Running + +```bash +docker build -t ncorn-app . +docker run -d -p 8000:8000 --name myapp ncorn-app +``` + +## Docker with SSL + +```dockerfile +FROM python:3.11-slim + +WORKDIR /app + +RUN pip install ncorn + +COPY certs/ ./certs/ +COPY app.py . + +CMD ["ncorn", "app:app", "--host", "0.0.0.0", "--port", "443", \ + "--ssl-keyfile", "certs/key.pem", \ + "--ssl-certfile", "certs/cert.pem"] +``` + +## Multi-stage Build + +For smaller images: + +```dockerfile +# Build stage +FROM python:3.11-slim as builder + +WORKDIR /app +RUN pip install --user ncorn + +# Runtime stage +FROM python:3.11-slim + +WORKDIR /app +COPY --from=builder /root/.local /root/.local +COPY --from=builder /app /app + +ENV PATH=/root/.local/bin:$PATH + +CMD ["ncorn", "app:app", "--host", "0.0.0.0", "--port", "8000"] +``` + +## Docker Compose + +```yaml +version: '3.8' + +services: + web: + build: . + ports: + - "8000:8000" + environment: + - NCORN_HOST=0.0.0.0 + - NCORN_PORT=8000 + volumes: + - .:/app + + # With SSL + web-ssl: + build: . + ports: + - "443:443" + volumes: + - ./certs:/app/certs:ro + command: > + ncorn app:app + --host 0.0.0.0 + --port 443 + --ssl-keyfile certs/key.pem + --ssl-certfile certs/cert.pem +``` + +## Production Docker + +```dockerfile +FROM python:3.11-slim + +WORKDIR /app + +RUN pip install --no-cache-dir ncorn + +# Create non-root user +RUN useradd -m appuser +USER appuser + +COPY --chown=appuser:appuser . . + +EXPOSE 8000 + +CMD ["ncorn", "app:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"] +``` + +## Health Check + +```yaml +services: + web: + build: . + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8000/health"] + interval: 30s + timeout: 10s + retries: 3 + ports: + - "8000:8000" +``` + +## Kubernetes + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: ncorn-app +spec: + containers: + - name: web + image: ncorn-app:latest + ports: + - containerPort: 8000 + env: + - name: NCORN_HOST + value: "0.0.0.0" + - name: NCORN_PORT + value: "8000" + resources: + limits: + memory: "512Mi" + cpu: "500m" +``` + +## Best Practices + +1. **Use non-root user** in containers +2. **Set proper resource limits** +3. **Use health checks** +4. **Enable SSL in production** +5. **Use multi-stage builds** for smaller images +6. **Don't cache dependencies** in production (`--no-cache-dir`) diff --git a/docs/en/deployment/index.md b/docs/en/deployment/index.md new file mode 100644 index 0000000..1ea9f7a --- /dev/null +++ b/docs/en/deployment/index.md @@ -0,0 +1,163 @@ +# Deployment + +This guide covers various deployment options for ncorn. + +## Production Checklist + +Before deploying to production: + +1. ✅ Use SSL/TLS certificates +2. ✅ Set appropriate timeouts +3. ✅ Configure rate limiting +4. ✅ Use multiple workers +5. ✅ Set up logging and monitoring +6. ✅ Configure health checks + +## Basic Production Deployment + +```bash +ncorn app:app --host 0.0.0.0 --port 443 \ + --ssl-keyfile /path/to/key.pem \ + --ssl-certfile /path/to/cert.pem \ + --workers 4 \ + --rate-limit 100 \ + --rate-limit-window 60 +``` + +## Multi-Worker Deployment + +For better performance, use multiple workers: + +```bash +ncorn app:app --workers 4 +``` + +Each worker: +- Runs in a separate process +- Handles requests independently +- Shares the same port + +## Behind Reverse Proxy + +While ncorn has native SSL support, you can also run behind nginx: + +```nginx +server { + listen 80; + server_name example.com; + + location / { + proxy_pass http://127.0.0.1:8000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } +} +``` + +## Process Management + +### Systemd + +Create `/etc/systemd/system/ncorn.service`: + +```ini +[Unit] +Description=ncorn ASGI server +After=network.target + +[Service] +Type=simple +User=www-data +Group=www-data +WorkingDirectory=/path/to/project +ExecStart=/usr/bin/ncorn app:app --host 0.0.0.0 --port 8000 --workers 4 +Restart=always + +[Install] +WantedBy=multi-user.target +``` + +Then: + +```bash +sudo systemctl enable ncorn +sudo systemctl start ncorn +``` + +### Supervisor + +```ini +[program:ncorn] +command=/usr/bin/ncorn app:app --host 0.0.0.0 --port 8000 --workers 4 +directory=/path/to/project +user=www-data +autostart=true +autorestart=true +``` + +## SSL Certificates + +### Self-Signed (Development) + +```bash +openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes +``` + +### Let's Encrypt (Production) + +Use certbot: + +```bash +certbot certonly --standalone -d example.com +``` + +Then configure ncorn: + +```bash +ncorn app:app \ + --ssl-keyfile /etc/letsencrypt/live/example.com/privkey.pem \ + --ssl-certfile /etc/letsencrypt/live/example.com/fullchain.pem +``` + +## Health Checks + +For load balancers and orchestrators: + +```python +from fastapi import FastAPI + +app = FastAPI() + +@app.get("/health") +async def health(): + return {"status": "healthy"} +``` + +## Performance Tuning + +### Worker Count + +A good starting point is 2-4 workers per CPU core: + +```bash +ncorn app:app --workers $(nproc) +``` + +### Timeouts + +Adjust based on your application: + +```bash +ncorn app:app \ + --header-timeout 30 \ + --body-timeout 60 \ + --keepalive-timeout 5 +``` + +### Connection Limits + +```bash +ncorn app:app \ + --max-connections 1000 \ + --max-connections-per-ip 50 +``` diff --git a/docs/en/examples.md b/docs/en/examples.md deleted file mode 100644 index 1c0eb4b..0000000 --- a/docs/en/examples.md +++ /dev/null @@ -1,188 +0,0 @@ -# Examples - -## Basic FastAPI Application - -```python -from fastapi import FastAPI, HTTPException -from pydantic import BaseModel - -app = FastAPI(title="Example App") - -class Item(BaseModel): - name: str - price: float - -@app.get("/") -async def root(): - return {"message": "Hello from ncorn!"} - -@app.get("/items/{item_id}") -async def read_item(item_id: int): - if item_id < 1 or item_id > 100: - raise HTTPException(status_code=404, detail="Item not found") - return {"item_id": item_id, "name": f"Item {item_id}"} - -@app.post("/items") -async def create_item(item: Item): - return {"name": item.name, "price": item.price} -``` - -Run with: - -```bash -ncorn example:app -``` - -## REST API with CRUD Operations - -```python -from fastapi import FastAPI, HTTPException -from pydantic import BaseModel - -app = FastAPI() - -items = {} -item_id = 0 - -class Item(BaseModel): - name: str - price: float - description: str | None = None - -@app.post("/items") -async def create_item(item: Item): - global item_id - item_id += 1 - items[item_id] = item - return {"id": item_id, **item.dict()} - -@app.get("/items/{item_id}") -async def get_item(item_id: int): - if item_id not in items: - raise HTTPException(status_code=404, detail="Item not found") - return {"id": item_id, **items[item_id].dict()} - -@app.put("/items/{item_id}") -async def update_item(item_id: int, item: Item): - if item_id not in items: - raise HTTPException(status_code=404, detail="Item not found") - items[item_id] = item - return {"id": item_id, **item.dict()} - -@app.delete("/items/{item_id}") -async def delete_item(item_id: int): - if item_id not in items: - raise HTTPException(status_code=404, detail="Item not found") - del items[item_id] - return {"deleted": True} -``` - -## Query Parameters and Validation - -```python -from fastapi import FastAPI, Query -from pydantic import BaseModel, Field - -app = FastAPI() - -class User(BaseModel): - username: str = Field(min_length=3, max_length=50) - email: str - age: int = Field(ge=0, le=150) - -@app.get("/users") -async def list_users( - limit: int = Query(default=10, ge=1, le=100), - offset: int = Query(default=0, ge=0), -): - return {"limit": limit, "offset": offset, "users": []} - -@app.post("/users") -async def create_user(user: User): - return user -``` - -## Request Body Types - -```python -from fastapi import FastAPI -from pydantic import BaseModel -from typing import List - -app = FastAPI() - -class Item(BaseModel): - name: str - price: float - -class Order(BaseModel): - items: List[Item] - priority: bool = False - -@app.post("/order") -async def create_order(order: Order): - total = sum(item.price for item in order.items) - return { - "items": order.items, - "total": total, - "priority": order.priority, - } -``` - -## Error Handling - -```python -from fastapi import FastAPI, HTTPException - -app = FastAPI() - -@app.get("/error") -async def trigger_error(): - raise HTTPException(status_code=400, detail="Custom error message") -``` - -## Dependencies - -```python -from fastapi import FastAPI, Depends - -app = FastAPI() - -def get_current_user(): - return {"username": "user123"} - -@app.get("/protected") -async def protected_route(user = Depends(get_current_user)): - return user -``` - -## With Custom Configuration - -```python -from ncorn.config import Config -from ncorn.server import HTTPServer -from myapp import app - -config = Config( - host="0.0.0.0", - port=9000, - workers=4, - max_body_size=32 * 1024 * 1024, - rate_limit_requests=200, - rate_limit_window=60.0, -) - -server = HTTPServer(app, config) -``` - -## Testing with cURL - -```bash -# GET request -curl http://localhost:8000/ - -# POST request -curl -X POST http://localhost:8000/items \ - -H "Content-Type: application/json" \ - -d '{"name": "test", "price": 9.99}' -``` diff --git a/docs/en/index.md b/docs/en/index.md index 147f4fd..3acc83d 100644 --- a/docs/en/index.md +++ b/docs/en/index.md @@ -1,34 +1,74 @@ -# Welcome to ncorn +# Welcome -ncorn is a production-ready ASGI web server designed specifically for FastAPI applications. +![ncorn](../logo.png) -## Features +_ncorn is a production-ready ASGI web server for FastAPI applications._ + +--- + +**Documentation**: [https://ncorn.ndugram.dev](https://ncorn.readthedocs.io/) + +**Source Code**: [https://github.com/ndugram/ncorn](https://github.com/ndugram/ncorn) -- Async TCP server using asyncio -- HTTP/1.1 parser using httptools -- ASGI adapter layer -- Middleware system (server-level) -- Request validation (headers, body size limits) -- Rate limiting -- Graceful shutdown -- Keep-alive connections +--- -## Security Features +**ncorn** is an ASGI web server implementation for Python, designed specifically for FastAPI applications. -- Max body size limit -- Header validation -- Slowloris protection (timeouts) -- IP-based rate limiting +Until recently Python has lacked a minimal low-level server/application interface for async frameworks. The [ASGI specification](https://asgi.readthedocs.io/en/latest/) fills this gap, and means we're now able to start building a common set of tooling usable across all async frameworks. + +ncorn is built with a focus on **performance** and **production-readiness**, featuring built-in security measures and SSL/TLS support. + +## Features -## Quick Start +- **Fast Performance** - Built on asyncio for high performance +- **ASGI Compatible** - Full ASGI interface support for FastAPI +- **Production Ready** - Rate limiting, request validation, slowloris protection +- **SSL/TLS** - Native HTTPS support without reverse proxy +- **Multi-Worker** - Support for multiple worker processes +- **Auto-Reload** - Development mode with file watching +- **Clean Logging** - Beautiful uvicorn-style console output +- **Security** - Header validation, body size limits, IP rate limiting + +## Quickstart + +ncorn is available on PyPI so installation is as simple as: ```bash pip install ncorn -ncorn module:app ``` +Let's create a simple FastAPI application: + +```python +from fastapi import FastAPI + +app = FastAPI() + +@app.get("/") +async def root(): + return {"message": "Hello from ncorn!"} +``` + +Then we can run it with ncorn: + +```bash +ncorn main:app +``` + +## Running with HTTPS + +ncorn has built-in SSL/TLS support - no need for external reverse proxy: + +```bash +ncorn main:app --ssl-keyfile certs/key.pem --ssl-certfile certs/cert.pem +``` + +This will start the server on `https://127.0.0.1:8000` + ## Requirements - Python 3.11+ - httptools - rich +- annotated-doc + diff --git a/docs/en/installation.md b/docs/en/installation.md new file mode 100644 index 0000000..b82b14b --- /dev/null +++ b/docs/en/installation.md @@ -0,0 +1,28 @@ +# Installation + +ncorn is available on PyPI and can be installed with pip: + +```bash +pip install ncorn +``` + +## Requirements + +- Python 3.11+ +- httptools >= 0.5.0 +- rich >= 13.0.0 +- annotated-doc >= 0.0.4 + +## Development Version + +If you want the latest development version: + +```bash +pip install git+https://github.com/ndugram/ncorn.git +``` + +## Verify Installation + +```bash +ncorn --version +``` diff --git a/docs/en/middleware.md b/docs/en/middleware.md deleted file mode 100644 index 055e1e6..0000000 --- a/docs/en/middleware.md +++ /dev/null @@ -1,35 +0,0 @@ -# Middleware - -ncorn includes server-level middleware for request processing. - -## Available Middleware - -### ValidationMiddleware - -Validates HTTP methods, headers, and paths. - -### RateLimitMiddleware - -IP-based rate limiting to prevent abuse. - -## Custom Middleware - -You can create custom middleware by extending `BaseMiddleware`: - -```python -from ncorn.middleware.base import BaseMiddleware, ASGIApp - -class CustomMiddleware(BaseMiddleware): - async def __call__(self, scope, receive, send): - # Process request - await self.app(scope, receive, send) - # Process response -``` - -## Middleware Order - -Middleware is executed in the following order: - -1. ValidationMiddleware -2. RateLimitMiddleware -3. Your application diff --git a/docs/en/quick-start.md b/docs/en/quick-start.md deleted file mode 100644 index 487d9c1..0000000 --- a/docs/en/quick-start.md +++ /dev/null @@ -1,40 +0,0 @@ -# Quick Start - -## Installation - -```bash -pip install ncorn -``` - -## Basic Usage - -Create a FastAPI application: - -```python -from fastapi import FastAPI - -app = FastAPI() - -@app.get("/") -async def root(): - return {"message": "Hello from ncorn!"} -``` - -Run with ncorn: - -```bash -ncorn module:app -``` - -## Command Line Options - -```bash -ncorn module:app --host 0.0.0.0 --port 8080 -``` - -## Options - -- `--host` - Host to bind to (default: 127.0.0.1) -- `--port` - Port to bind to (default: 8000) -- `--reload` - Enable auto-reload on file changes -- `--workers` - Number of worker processes (default: 1) diff --git a/docs/en/security.md b/docs/en/security.md deleted file mode 100644 index 6724712..0000000 --- a/docs/en/security.md +++ /dev/null @@ -1,42 +0,0 @@ -# Security - -ncorn includes several security features to protect your application. - -## Built-in Security Features - -### Request Body Size Limit - -Limits the maximum size of incoming request bodies to prevent DoS attacks. - -```bash -ncorn app:app --max-body-size 8388608 # 8 MB -``` - -### Header Validation - -Validates HTTP headers and rejects malformed requests. - -### Timeout Protection - -- `header_timeout` - Time limit for reading request headers -- `body_timeout` - Time limit for reading request body -- Prevents Slowloris attacks - -```bash -ncorn app:app --header-timeout 30 --body-timeout 60 -``` - -### IP Rate Limiting - -Limits the number of requests from a single IP address. - -```bash -ncorn app:app --rate-limit 100 --rate-limit-window 60 -``` - -## Best Practices - -1. Always set appropriate body size limits -2. Use rate limiting in production -3. Keep timeouts as low as possible for your use case -4. Run behind a reverse proxy like nginx for SSL/TLS termination diff --git a/docs/en/server-behavior.md b/docs/en/server-behavior.md new file mode 100644 index 0000000..bd26860 --- /dev/null +++ b/docs/en/server-behavior.md @@ -0,0 +1,82 @@ +# Server Behavior + +## Lifecycle + +ncorn follows the ASGI lifespan protocol to manage the application lifecycle. + +### Startup + +1. Load configuration from file, environment, or CLI arguments +2. Parse and validate application +3. Create SSL context if SSL is configured +4. Start ASGI server +5. Call lifespan `startup` event if defined + +### Shutdown + +1. Receive shutdown signal (SIGINT, SIGTERM) +2. Stop accepting new connections +3. Wait for active requests to complete (grace period) +4. Call lifespan `shutdown` event if defined +5. Close all connections +6. Exit process + +## Connection Handling + +### Keep-Alive + +ncorn supports HTTP keep-alive connections to reuse TCP connections for multiple requests. + +- Configurable via `--keepalive-timeout` +- Maximum requests per connection via `--keepalive-requests` + +### Request Processing + +1. Accept incoming TCP connection +2. Parse HTTP request headers +3. Validate headers (size, count, format) +4. Read request body if present +5. Call ASGI application +6. Send response +7. Keep connection alive or close + +### Timeouts + +ncorn implements multiple timeout layers: + +- **header_timeout** - Time to receive all headers +- **body_timeout** - Time to read request body +- **keepalive_timeout** - Time to wait for next request on keep-alive connection +- **request_timeout** - Time for application to process request + +## Multi-Worker Mode + +When using `--workers > 1`, ncorn spawns multiple processes: + +- Each worker runs its own event loop +- Workers share the same port (socket inheritance) +- Workers are restarted independently if they crash + +## SSL/TLS + +ncorn has native SSL/TLS support: + +- TLS 1.3 (default), TLS 1.2, TLS 1.1, TLS 1.0 +- Custom certificate and key files +- No reverse proxy required + +## Logging + +ncorn provides uvicorn-style logging: + +``` +21:50:53.290 | INFO | SSL enabled: TLSv1.3 +21:50:53.291 | ncorn | Application startup complete +21:50:53.291 | ncorn | Ncorn running on https://127.0.0.1:8443 +``` + +Each request is logged with: +- HTTP method +- Path +- Status code +- Latency diff --git a/docs/en/settings.md b/docs/en/settings.md new file mode 100644 index 0000000..301a98c --- /dev/null +++ b/docs/en/settings.md @@ -0,0 +1,106 @@ +# Settings + +ncorn can be configured via command line options, configuration file, or programmatically. + +## Command Line Options + +```bash +ncorn module:app [OPTIONS] +``` + +### Basic Options + +| Option | Description | Default | +|--------|-------------|---------| +| `app` | Application in format 'module:app' | Required | +| `--host` | Host to bind to | 127.0.0.1 | +| `--port` | Port to bind to | 8000 | +| `--reload` | Enable auto-reload on file changes | false | +| `--workers` | Number of worker processes | 1 | + +### Request Limits + +| Option | Description | Default | +|--------|-------------|---------| +| `--max-body-size` | Maximum request body size in bytes | 16777216 (16MB) | +| `--max-headers` | Maximum number of headers | 100 | +| `--keepalive-requests` | Max requests per keep-alive connection | 100 | + +### Timeouts + +| Option | Description | Default | +|--------|-------------|---------| +| `--header-timeout` | Header read timeout in seconds | 30.0 | +| `--body-timeout` | Body read timeout in seconds | 60.0 | +| `--keepalive-timeout` | Keep-alive timeout in seconds | 5.0 | + +### Rate Limiting + +| Option | Description | Default | +|--------|-------------|---------| +| `--rate-limit` | Rate limit requests per window | 100 | +| `--rate-limit-window` | Rate limit window in seconds | 60.0 | + +### SSL/TLS + +| Option | Description | Default | +|--------|-------------|---------| +| `--ssl-keyfile` | Path to SSL key file | None | +| `--ssl-certfile` | Path to SSL certificate file | None | +| `--ssl-version` | TLS version (2=TLSv1, 3=TLSv1.1, 4=TLSv1.2, 5=TLSv1.3) | 5 | + +### Other Options + +| Option | Description | Default | +|--------|-------------|---------| +| `--verbose` | Enable verbose logging | false | + +## Configuration File + +ncorn can also be configured via `ncorn.json` file: + +```json +{ + "host": "0.0.0.0", + "port": 8000, + "workers": 4, + "reload": false, + "max_body_size": 16777216, + "ssl_keyfile": "certs/key.pem", + "ssl_certfile": "certs/cert.pem", + "ssl_version": 5 +} +``` + +Command line options override config file settings. + +## Programmatic Configuration + +You can also configure ncorn programmatically: + +```python +from ncorn.config import Config +from ncorn.server import HTTPServer +from myapp import app + +config = Config( + host="0.0.0.0", + port=8080, + workers=4, + max_body_size=32 * 1024 * 1024, + ssl_keyfile="certs/key.pem", + ssl_certfile="certs/cert.pem", +) + +server = HTTPServer(app, config) +``` + +## Environment Variables + +ncorn supports configuration through environment variables: + +- `NCORN_HOST` - Server host +- `NCORN_PORT` - Server port +- `NCORN_WORKERS` - Number of workers +- `NCORN_SSL_KEYFILE` - SSL key file path +- `NCORN_SSL_CERTFILE` - SSL certificate file path diff --git a/docs/index.md b/docs/index.md index b0ba2c7..a209c42 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,39 +1,74 @@ -# ncorn +# Welcome -Production-ready ASGI web server designed specifically for FastAPI applications. +![ncorn](logo.png) -## Features +_ncorn is a production-ready ASGI web server for FastAPI applications._ + +--- + +**Documentation**: [https://ncorn.ndugram.dev](https://ncorn.readthedocs.io/) + +**Source Code**: [https://github.com/ndugram/ncorn](https://github.com/ndugram/ncorn) -- Async TCP server using asyncio -- HTTP/1.1 parser using httptools -- ASGI adapter layer -- Middleware system (server-level) -- Request validation (headers, body size limits) -- Rate limiting -- Graceful shutdown -- Keep-alive connections +--- -## Security Features +**ncorn** is an ASGI web server implementation for Python, designed specifically for FastAPI applications. -- Max body size limit -- Header validation -- Slowloris protection (timeouts) -- IP-based rate limiting +Until recently Python has lacked a minimal low-level server/application interface for async frameworks. The [ASGI specification](https://asgi.readthedocs.io/en/latest/) fills this gap, and means we're now able to start building a common set of tooling usable across all async frameworks. + +ncorn is built with a focus on **performance** and **production-readiness**, featuring built-in security measures and SSL/TLS support. + +## Features -## Quick Start +- **Fast Performance** - Built on asyncio for high performance +- **ASGI Compatible** - Full ASGI interface support for FastAPI +- **Production Ready** - Rate limiting, request validation, slowloris protection +- **SSL/TLS** - Native HTTPS support without reverse proxy +- **Multi-Worker** - Support for multiple worker processes +- **Auto-Reload** - Development mode with file watching +- **Clean Logging** - Beautiful uvicorn-style console output +- **Security** - Header validation, body size limits, IP rate limiting + +## Quickstart + +ncorn is available on PyPI so installation is as simple as: ```bash pip install ncorn -ncorn module:app ``` +Let's create a simple FastAPI application: + +```python +from fastapi import FastAPI + +app = FastAPI() + +@app.get("/") +async def root(): + return {"message": "Hello from ncorn!"} +``` + +Then we can run it with ncorn: + +```bash +ncorn main:app +``` + +## Running with HTTPS + +ncorn has built-in SSL/TLS support - no need for external reverse proxy: + +```bash +ncorn main:app --ssl-keyfile certs/key.pem --ssl-certfile certs/cert.pem +``` + +This will start the server on `https://127.0.0.1:8000` + ## Requirements - Python 3.11+ - httptools - rich +- annotated-doc -## Links - -- [GitHub](https://github.com/ndugram/ncorn) -- [Documentation](https://ncorn.readthedocs.io/) diff --git a/docs/ru/api-reference.md b/docs/ru/api-reference.md index b035387..93fbc2c 100644 --- a/docs/ru/api-reference.md +++ b/docs/ru/api-reference.md @@ -1,50 +1,135 @@ -# Справка по API +# API Справочник -## Config +## Командная строка + +### ncorn + +```bash +ncorn module:app [ОПЦИИ] +``` + +Основная точка входа для запуска ncorn сервера. + +### ncorn config + +```bash +ncorn config +``` + +Создаёт файл конфигурации `ncorn.json` по умолчанию. + +## Python API + +### Config ```python from ncorn.config import Config +``` +Класс конфигурации для ncorn сервера. + +```python config = Config( host="127.0.0.1", port=8000, workers=1, reload=False, - max_body_size=16777216, - header_timeout=30.0, - body_timeout=60.0, - keepalive_timeout=5.0, - max_headers=100, - max_keepalive_requests=100, - rate_limit_requests=100, - rate_limit_window=60.0, + max_body_size=16 * 1024 * 1024, + ssl_keyfile=None, + ssl_certfile=None, + ssl_version=5, ) ``` -## HTTPServer +#### Параметры + +| Параметр | Тип | По умолчанию | Описание | +|----------|------|--------------|----------| +| `host` | str | "127.0.0.1" | IP адрес для привязки | +| `port` | int | 8000 | Номер порта | +| `workers` | int | 1 | Количество воркеров | +| `reload` | bool | False | Включить авто-перезагрузку | +| `max_body_size` | int | 16777216 | Макс. размер тела запроса | +| `max_header_size` | int | 8192 | Макс. размер одного заголовка | +| `max_headers_total_size` | int | 65536 | Макс. общий размер заголовков | +| `header_timeout` | float | 30.0 | Таймаут чтения заголовков | +| `body_timeout` | float | 60.0 | Таймаут чтения тела | +| `request_timeout` | float | 10.0 | Таймаут обработки запроса | +| `keepalive_timeout` | float | 5.0 | Таймаут keep-alive | +| `keepalive_requests` | int | 100 | Макс. запросов на соединение | +| `max_headers` | int | 100 | Макс. количество заголовков | +| `max_connections` | int | 1000 | Макс. одновременных соединений | +| `max_connections_per_ip` | int | 50 | Макс. соединений с одного IP | +| `rate_limit_requests` | int | 100 | Запросов в окно | +| `rate_limit_window` | float | 60.0 | Окно rate limiting | +| `ssl_keyfile` | str | None | Путь к SSL ключу | +| `ssl_certfile` | str | None | Путь к SSL сертификату | +| `ssl_version` | int | 5 | Версия TLS (2-5) | + +### HTTPServer ```python from ncorn.server import HTTPServer -from ncorn.config import Config -from myapp import app +``` -config = Config(host="0.0.0.0", port=8080) -server = HTTPServer(app, config) +Класс HTTP сервера. -# Запуск сервера +```python +server = HTTPServer(app, config) await server.start() - -# Остановка сервера await server.stop() ``` -## Logger +#### Методы + +##### start(show_banner=True) + +Запустить HTTP сервер. + +##### stop() + +Корректно остановить сервер. + +### CLI функции ```python -from ncorn.logging import logger +from ncorn.cli import import_app, parse_args, main +``` + +#### import_app(app_spec: str) + +Импортировать FastAPI приложение из строки "module:app". + +#### parse_args(args: Optional[list[str]] = None) -> argparse.Namespace + +Парсить аргументы командной строки. + +#### main(args: Optional[list[str]] = None) -> None + +Основная точка входа. -logger.info("Сообщение") -logger.warning("Сообщение") -logger.error("Сообщение") -logger.success("Сообщение") +### Middleware + +```python +from ncorn.middleware import ( + ValidationMiddleware, + RateLimitMiddleware, + MiddlewareChain, +) ``` + +#### ValidationMiddleware + +Валидирует HTTP запросы (заголовки, размер тела). + +#### RateLimitMiddleware + +Реализует IP-based rate limiting. + +#### MiddlewareChain + +Объединяет несколько middleware вместе. + +## Исключения + +ncorn использует стандартные исключения Python. Смотрите документацию отдельных middleware для обработки ошибок. diff --git a/docs/ru/cli.md b/docs/ru/cli.md deleted file mode 100644 index f286cea..0000000 --- a/docs/ru/cli.md +++ /dev/null @@ -1,48 +0,0 @@ -# CLI Справка - -## Базовая команда - -```bash -ncorn module:app -``` - -## Опции - -| Опция | Описание | По умолчанию | -|-------|----------|--------------| -| `app` | Приложение в формате 'module:app' | Обязательно | -| `--host` | Хост для привязки | 127.0.0.1 | -| `--port` | Порт для привязки | 8000 | -| `--reload` | Включить автоперезагрузку | false | -| `--workers` | Количество рабочих процессов | 1 | -| `--max-body-size` | Максимальный размер тела запроса в байтах | 16777216 | -| `--header-timeout` | Таймаут чтения заголовков в секундах | 30.0 | -| `--rate-limit` | Лимит запросов в окно | 100 | -| `--rate-limit-window` | Окно лимита в секундах | 60.0 | -| `--verbose` | Подробное логирование | false | - -## Примеры - -Запуск с кастомным хостом и портом: - -```bash -ncorn example_app:app --host 0.0.0.0 --port 9000 -``` - -Запуск с автоперезагрузкой: - -```bash -ncorn example_app:app --reload -``` - -Запуск с несколькими воркерами: - -```bash -ncorn example_app:app --workers 4 -``` - -Запуск с кастомным rate limiting: - -```bash -ncorn example_app:app --rate-limit 50 --rate-limit-window 30 -``` diff --git a/docs/ru/concepts/asgi.md b/docs/ru/concepts/asgi.md new file mode 100644 index 0000000..2911906 --- /dev/null +++ b/docs/ru/concepts/asgi.md @@ -0,0 +1,70 @@ +# ASGI + +ASGI (Asynchronous Server Gateway Interface) — это стандартный интерфейс между Python веб-серверами и приложениями. + +## Обзор + +ASGI — это спецификация, которая описывает, как асинхронные веб-приложения должны общаться с веб-серверами. Она была разработана для замены WSGI (PEP 333) для асинхронных фреймворков. + +## Основные понятия + +### Scope + +`scope` — это словарь, содержащий информацию о соединении: + +```python +{ + "type": "http", + "method": "GET", + "path": "/", + "query_string": b"", + "headers": [(b"host", b"localhost")], + "client": ("127.0.0.1", 8000), + "server": ("127.0.0.1", 8000), + "scheme": "http", +} +``` + +### Receive + +Функция `receive` ожидает входящие данные: + +```python +message = await receive() +# Возвращает: {"type": "http.request", "body": b"...", "more_body": bool} +``` + +### Send + +Функция `send` отправляет данные ответа: + +```python +# Начало ответа +await send({ + "type": "http.response.start", + "status": 200, + "headers": [(b"content-type", b"application/json")], +}) + +# Отправка тела +await send({ + "type": "http.response.body", + "body": b'{"message": "hello"}', +}) +``` + +## Типы HTTP + +- `http` — обычные HTTP/1.1 соединения +- `websocket` — WebSocket соединения +- `lifespan` — события жизненного цикла приложения + +## Реализация ASGI в ncorn + +ncorn реализует полноценный ASGI сервер: + +- Парсит HTTP/1.1 запросы +- Строит ASGI scope словарь +- Обрабатывает жизненный цикл запроса/ответа +- Поддерживает keep-alive соединения +- Поддерживает только HTTP/1.1 (WebSocket скоро) diff --git a/docs/ru/concepts/lifespan.md b/docs/ru/concepts/lifespan.md new file mode 100644 index 0000000..16c6bc0 --- /dev/null +++ b/docs/ru/concepts/lifespan.md @@ -0,0 +1,93 @@ +# Lifespan + +Протокол lifespan позволяет приложениям выполнять задачи при запуске и остановке. + +## Обзор + +Протокол lifespan является частью ASGI и позволяет приложениям: + +- Инициализировать ресурсы при запуске +- Очищать ресурсы при остановке + +## Использование с FastAPI + +FastAPI автоматически обрабатывает lifespan, но вы можете определить свои обработчики: + +```python +from contextlib import asynccontextmanager +from fastapi import FastAPI + +@asynccontextmanager +async def lifespan(app: FastAPI): + # Запуск + print("Запуск...") + await connect_to_database() + + yield + + # Остановка + print("Остановка...") + await close_database() + +app = FastAPI(lifespan=lifespan) +``` + +## Ручная реализация ASGI + +Если вы реализуете ASGI напрямую: + +```python +async def app(scope, receive, send): + if scope["type"] == "lifespan": + while True: + message = await receive() + + if message["type"] == "lifespan.startup": + # Инициализация ресурсов + await send({"type": "lifespan.startup.complete"}) + + elif message["type"] == "lifespan.shutdown": + # Очистка ресурсов + await send({"type": "lifespan.shutdown.complete"}) + break +``` + +## Lifespan в ncorn + +ncorn полностью поддерживает протокол lifespan: + +- Вызывает события запуска при старте сервера +- Вызывает события остановки при выключении сервера +- Корректно обрабатывает graceful shutdown + +## Событие запуска + +Вызывается, когда сервер готов принимать соединения: + +```python +{"type": "lifespan.startup"} +``` + +Ваше приложение должно ответить: + +```python +{"type": "lifespan.startup.complete"} +# или +{"type": "lifespan.startup.failed", "message": "причина ошибки"} +``` + +## Событие остановки + +Вызывается, когда сервер выключается: + +```python +{"type": "lifespan.shutdown"} +``` + +Ваше приложение должно ответить: + +```python +{"type": "lifespan.shutdown.complete"} +# или +{"type": "lifespan.shutdown.failed", "message": "причина ошибки"} +``` diff --git a/docs/ru/concepts/websockets.md b/docs/ru/concepts/websockets.md new file mode 100644 index 0000000..5d4ba76 --- /dev/null +++ b/docs/ru/concepts/websockets.md @@ -0,0 +1,66 @@ +# WebSockets + +WebSockets обеспечивают полнодуплексную связь между клиентом и сервером. + +## Статус + +!!! warning "Скоро" + Поддержка WebSocket планируется в будущем выпуске. + +На данный момент ncorn поддерживает только HTTP/1.1. Поддержка WebSocket будет добавлена в будущей версии. + +## Что такое WebSockets? + +WebSockets отличаются от HTTP: + +- **HTTP**: модель запрос-ответ +- **WebSocket**: двустороннее, постоянное соединение + +## ASGI WebSocket Scope + +```python +{ + "type": "websocket", + "path": "/ws", + "query_string": b"", + "headers": [...], + "client": ("127.0.0.1", 8000), + "server": ("127.0.0.1", 8000), + "subprotocols": [], + "asgi": {"version": "3.0"}, +} +``` + +## Сообщения WebSocket + +### Подключение + +```python +{"type": "websocket.connect"} +``` + +### Получение + +```python +{"type": "websocket.receive", "text": "hello"} +# или +{"type": "websocket.receive", "bytes": b"hello"} +``` + +### Отправка + +```python +{"type": "websocket.send", "text": "hello"} +# или +{"type": "websocket.send", "bytes": b"hello"} +``` + +### Отключение + +```python +{"type": "websocket.disconnect", "code": 1000} +``` + +## Альтернатива + +На данный момент вы можете использовать uvicorn вместе с ncorn для поддержки WebSocket, или использовать reverse proxy, который обрабатывает WebSocket upgrading. diff --git a/docs/ru/configuration.md b/docs/ru/configuration.md deleted file mode 100644 index 4f09fdf..0000000 --- a/docs/ru/configuration.md +++ /dev/null @@ -1,47 +0,0 @@ -# Конфигурация - -## Конфигурация сервера - -Сервер можно настроить с помощью параметров командной строки или программно. - -## Параметры конфигурации - -### Сетевые настройки - -- `host` - IP адрес для привязки (по умолчанию: 127.0.0.1) -- `port` - Номер порта (по умолчанию: 8000) -- `workers` - Количество рабочих процессов (по умолчанию: 1) - -### Таймауты - -- `header_timeout` - Максимальное время чтения заголовков запроса (по умолчанию: 30.0 сек) -- `body_timeout` - Максимальное время чтения тела запроса (по умолчанию: 60.0 сек) -- `keepalive_timeout` - Таймаут keep-alive соединения (по умолчанию: 5.0 сек) - -### Ограничения запросов - -- `max_body_size` - Максимальный размер тела запроса (по умолчанию: 16 МБ) -- `max_headers` - Максимальное количество заголовков (по умолчанию: 100) -- `max_keepalive_requests` - Максимум запросов на keep-alive соединение (по умолчанию: 100) - -### Rate Limiting - -- `rate_limit_requests` - Максимум запросов в окно (по умолчанию: 100) -- `rate_limit_window` - Временное окно в секундах (по умолчанию: 60.0) - -## Программная конфигурация - -```python -from ncorn.config import Config -from ncorn.server import HTTPServer -from myapp import app - -config = Config( - host="0.0.0.0", - port=8080, - workers=4, - max_body_size=32 * 1024 * 1024, -) - -server = HTTPServer(app, config) -``` diff --git a/docs/ru/contributing.md b/docs/ru/contributing.md new file mode 100644 index 0000000..33eb226 --- /dev/null +++ b/docs/ru/contributing.md @@ -0,0 +1,83 @@ +# Контрибьютинг + +Спасибо за ваш интерес к контрибьютингу в ncorn! + +## Настройка окружения разработки + +1. Клонируйте репозиторий: +```bash +git clone https://github.com/ndugram/ncorn.git +cd ncorn +``` + +2. Создайте виртуальное окружение: +```bash +python -m venv venv +source venv/bin/activate # На Windows: venv\Scripts\activate +``` + +3. Установите зависимости для разработки: +```bash +pip install -e . +pip install pytest httpx +``` + +## Стиль кода + +- Следуйте PEP 8 +- Используйте type hints +- Добавляйте docstrings через `annotated_doc` + +## Тестирование + +Запуск тестов: +```bash +pytest +``` + +Запуск с покрытием: +```bash +pytest --cov=ncorn --cov-report=html +``` + +## Структура проекта + +``` +ncorn/ +├── __init__.py # Инициализация пакета +├── cli.py # Интерфейс командной строки +├── config.py # Класс конфигурации +├── config_file.py # Загрузка конфигурации +├── logging.py # Утилиты логирования +├── main.py # Основная точка входа +├── protocol.py # Парсер HTTP протокола +├── reload.py # Функциональность авто-перезагрузки +├── server.py # HTTP сервер +├── middleware/ # Модули middleware +│ ├── base.py +│ ├── ipfilter.py +│ ├── ratelimit.py +│ ├── security.py +│ ├── validation.py +│ └── waf.py +└── asgi.py # ASGI адаптер +``` + +## Процесс Pull Request + +1. Сделайте форк репозитория +2. Создайте ветку для фичи (`git checkout -b feature/awesome-feature`) +3. Внесите изменения +4. Добавьте тесты, если применимо +5. Убедитесь, что все тесты проходят +6. Закоммитьте изменения (`git commit -m 'Add awesome feature'`) +7. Отправьте в ветку (`git push origin feature/awesome-feature`) +8. Откройте Pull Request + +## Сообщение об ошибках + +Пожалуйста, сообщайте об ошибках и запросах фич через GitHub Issues. + +## Лицензия + +Контрибьютая, вы соглашаетесь, что ваши изменения будут лицензированы под MIT License. diff --git a/docs/ru/dependencies.md b/docs/ru/dependencies.md deleted file mode 100644 index e733412..0000000 --- a/docs/ru/dependencies.md +++ /dev/null @@ -1,18 +0,0 @@ -# Зависимости - -У ncorn минимальные зависимости: - -- `httptools` - HTTP парсинг -- `rich` - Цветное логирование - -## Установка - -```bash -pip install ncorn -``` - -## Зависимости для разработки - -```bash -pip install -e ".[dev]" -``` diff --git a/docs/ru/deployment/docker.md b/docs/ru/deployment/docker.md new file mode 100644 index 0000000..614013f --- /dev/null +++ b/docs/ru/deployment/docker.md @@ -0,0 +1,166 @@ +# Docker + +ncorn можно контейнеризировать с помощью Docker для удобного развёртывания. + +## Базовый Dockerfile + +```dockerfile +FROM python:3.11-slim + +WORKDIR /app + +# Установка ncorn +RUN pip install ncorn + +# Копирование приложения +COPY . . + +# Запуск ncorn +CMD ["ncorn", "app:app", "--host", "0.0.0.0", "--port", "8000"] +``` + +## Сборка и запуск + +```bash +docker build -t ncorn-app . +docker run -d -p 8000:8000 --name myapp ncorn-app +``` + +## Docker с SSL + +```dockerfile +FROM python:3.11-slim + +WORKDIR /app + +RUN pip install ncorn + +COPY certs/ ./certs/ +COPY app.py . + +CMD ["ncorn", "app:app", "--host", "0.0.0.0", "--port", "443", \ + "--ssl-keyfile", "certs/key.pem", \ + "--ssl-certfile", "certs/cert.pem"] +``` + +## Мультистейдж сборка + +Для меньших образов: + +```dockerfile +# Стадия сборки +FROM python:3.11-slim as builder + +WORKDIR /app +RUN pip install --user ncorn + +# Рантайм стадия +FROM python:3.11-slim + +WORKDIR /app +COPY --from=builder /root/.local /root/.local +COPY --from=builder /app /app + +ENV PATH=/root/.local/bin:$PATH + +CMD ["ncorn", "app:app", "--host", "0.0.0.0", "--port", "8000"] +``` + +## Docker Compose + +```yaml +version: '3.8' + +services: + web: + build: . + ports: + - "8000:8000" + environment: + - NCORN_HOST=0.0.0.0 + - NCORN_PORT=8000 + volumes: + - .:/app + + # С SSL + web-ssl: + build: . + ports: + - "443:443" + volumes: + - ./certs:/app/certs:ro + command: > + ncorn app:app + --host 0.0.0.0 + --port 443 + --ssl-keyfile certs/key.pem + --ssl-certfile certs/cert.pem +``` + +## Docker для продакшена + +```dockerfile +FROM python:3.11-slim + +WORKDIR /app + +RUN pip install --no-cache-dir ncorn + +# Создание не-root пользователя +RUN useradd -m appuser +USER appuser + +COPY --chown=appuser:appuser . . + +EXPOSE 8000 + +CMD ["ncorn", "app:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"] +``` + +## Health Check + +```yaml +services: + web: + build: . + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8000/health"] + interval: 30s + timeout: 10s + retries: 3 + ports: + - "8000:8000" +``` + +## Kubernetes + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: ncorn-app +spec: + containers: + - name: web + image: ncorn-app:latest + ports: + - containerPort: 8000 + env: + - name: NCORN_HOST + value: "0.0.0.0" + - name: NCORN_PORT + value: "8000" + resources: + limits: + memory: "512Mi" + cpu: "500m" +``` + +## Лучшие практики + +1. **Используйте не-root пользователя** в контейнерах +2. **Установите правильные лимиты ресурсов** +3. **Используйте health checks** +4. **Включите SSL в продакшене** +5. **Используйте мультистейдж сборки** для меньших образов +6. **Не кэшируйте зависимости** в продакшене (`--no-cache-dir`) diff --git a/docs/ru/deployment/index.md b/docs/ru/deployment/index.md new file mode 100644 index 0000000..65569cf --- /dev/null +++ b/docs/ru/deployment/index.md @@ -0,0 +1,163 @@ +# Деплой + +Это руководство охватывает различные варианты развёртывания ncorn. + +## Чеклист для продакшена + +Перед развёртыванием в продакшене: + +1. ✅ Используйте SSL/TLS сертификаты +2. ✅ Установите соответствующие таймауты +3. ✅ Настройте rate limiting +4. ✅ Используйте несколько воркеров +5. ✅ Настройте логирование и мониторинг +6. ✅ Настройте health checks + +## Базовый деплой для продакшена + +```bash +ncorn app:app --host 0.0.0.0 --port 443 \ + --ssl-keyfile /path/to/key.pem \ + --ssl-certfile /path/to/cert.pem \ + --workers 4 \ + --rate-limit 100 \ + --rate-limit-window 60 +``` + +## Деплой с несколькими воркерами + +Для лучшей производительности используйте несколько воркеров: + +```bash +ncorn app:app --workers 4 +``` + +Каждый воркер: +- Запускается в отдельном процессе +- Обрабатывает запросы независимо +- Использует тот же порт + +## За reverse proxy + +Хотя ncorn имеет нативную поддержку SSL, вы также можете запустить за nginx: + +```nginx +server { + listen 80; + server_name example.com; + + location / { + proxy_pass http://127.0.0.1:8000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } +} +``` + +## Управление процессами + +### Systemd + +Создайте `/etc/systemd/system/ncorn.service`: + +```ini +[Unit] +Description=ncorn ASGI server +After=network.target + +[Service] +Type=simple +User=www-data +Group=www-data +WorkingDirectory=/path/to/project +ExecStart=/usr/bin/ncorn app:app --host 0.0.0.0 --port 8000 --workers 4 +Restart=always + +[Install] +WantedBy=multi-user.target +``` + +Затем: + +```bash +sudo systemctl enable ncorn +sudo systemctl start ncorn +``` + +### Supervisor + +```ini +[program:ncorn] +command=/usr/bin/ncorn app:app --host 0.0.0.0 --port 8000 --workers 4 +directory=/path/to/project +user=www-data +autostart=true +autorestart=true +``` + +## SSL сертификаты + +### Самоподписанные (для разработки) + +```bash +openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes +``` + +### Let's Encrypt (для продакшена) + +Используйте certbot: + +```bash +certbot certonly --standalone -d example.com +``` + +Затем настройте ncorn: + +```bash +ncorn app:app \ + --ssl-keyfile /etc/letsencrypt/live/example.com/privkey.pem \ + --ssl-certfile /etc/letsencrypt/live/example.com/fullchain.pem +``` + +## Health Checks + +Для балансировщиков нагрузки и оркестраторов: + +```python +from fastapi import FastAPI + +app = FastAPI() + +@app.get("/health") +async def health(): + return {"status": "healthy"} +``` + +## Оптимизация производительности + +### Количество воркеров + +Хорошей отправной точкой будет 2-4 воркера на ядро CPU: + +```bash +ncorn app:app --workers $(nproc) +``` + +### Таймауты + +Настройте под ваше приложение: + +```bash +ncorn app:app \ + --header-timeout 30 \ + --body-timeout 60 \ + --keepalive-timeout 5 +``` + +### Лимиты соединений + +```bash +ncorn app:app \ + --max-connections 1000 \ + --max-connections-per-ip 50 +``` diff --git a/docs/ru/examples.md b/docs/ru/examples.md deleted file mode 100644 index 3f61494..0000000 --- a/docs/ru/examples.md +++ /dev/null @@ -1,188 +0,0 @@ -# Примеры - -## Базовое приложение FastAPI - -```python -from fastapi import FastAPI, HTTPException -from pydantic import BaseModel - -app = FastAPI(title="Example App") - -class Item(BaseModel): - name: str - price: float - -@app.get("/") -async def root(): - return {"message": "Hello from ncorn!"} - -@app.get("/items/{item_id}") -async def read_item(item_id: int): - if item_id < 1 or item_id > 100: - raise HTTPException(status_code=404, detail="Item not found") - return {"item_id": item_id, "name": f"Item {item_id}"} - -@app.post("/items") -async def create_item(item: Item): - return {"name": item.name, "price": item.price} -``` - -Запуск: - -```bash -ncorn example:app -``` - -## REST API с CRUD операциями - -```python -from fastapi import FastAPI, HTTPException -from pydantic import BaseModel - -app = FastAPI() - -items = {} -item_id = 0 - -class Item(BaseModel): - name: str - price: float - description: str | None = None - -@app.post("/items") -async def create_item(item: Item): - global item_id - item_id += 1 - items[item_id] = item - return {"id": item_id, **item.dict()} - -@app.get("/items/{item_id}") -async def get_item(item_id: int): - if item_id not in items: - raise HTTPException(status_code=404, detail="Item not found") - return {"id": item_id, **items[item_id].dict()} - -@app.put("/items/{item_id}") -async def update_item(item_id: int, item: Item): - if item_id not in items: - raise HTTPException(status_code=404, detail="Item not found") - items[item_id] = item - return {"id": item_id, **item.dict()} - -@app.delete("/items/{item_id}") -async def delete_item(item_id: int): - if item_id not in items: - raise HTTPException(status_code=404, detail="Item not found") - del items[item_id] - return {"deleted": True} -``` - -## Параметры запроса и валидация - -```python -from fastapi import FastAPI, Query -from pydantic import BaseModel, Field - -app = FastAPI() - -class User(BaseModel): - username: str = Field(min_length=3, max_length=50) - email: str - age: int = Field(ge=0, le=150) - -@app.get("/users") -async def list_users( - limit: int = Query(default=10, ge=1, le=100), - offset: int = Query(default=0, ge=0), -): - return {"limit": limit, "offset": offset, "users": []} - -@app.post("/users") -async def create_user(user: User): - return user -``` - -## Типы тела запроса - -```python -from fastapi import FastAPI -from pydantic import BaseModel -from typing import List - -app = FastAPI() - -class Item(BaseModel): - name: str - price: float - -class Order(BaseModel): - items: List[Item] - priority: bool = False - -@app.post("/order") -async def create_order(order: Order): - total = sum(item.price for item in order.items) - return { - "items": order.items, - "total": total, - "priority": order.priority, - } -``` - -## Обработка ошибок - -```python -from fastapi import FastAPI, HTTPException - -app = FastAPI() - -@app.get("/error") -async def trigger_error(): - raise HTTPException(status_code=400, detail="Custom error message") -``` - -## Зависимости - -```python -from fastapi import FastAPI, Depends - -app = FastAPI() - -def get_current_user(): - return {"username": "user123"} - -@app.get("/protected") -async def protected_route(user = Depends(get_current_user)): - return user -``` - -## Кастомная конфигурация - -```python -from ncorn.config import Config -from ncorn.server import HTTPServer -from myapp import app - -config = Config( - host="0.0.0.0", - port=9000, - workers=4, - max_body_size=32 * 1024 * 1024, - rate_limit_requests=200, - rate_limit_window=60.0, -) - -server = HTTPServer(app, config) -``` - -## Тестирование с cURL - -```bash -# GET запрос -curl http://localhost:8000/ - -# POST запрос -curl -X POST http://localhost:8000/items \ - -H "Content-Type: application/json" \ - -d '{"name": "test", "price": 9.99}' -``` diff --git a/docs/ru/index.md b/docs/ru/index.md index 60bf95a..156de82 100644 --- a/docs/ru/index.md +++ b/docs/ru/index.md @@ -1,34 +1,73 @@ -# Добро пожаловать в ncorn +# Добро пожаловать -ncorn - это production-ready ASGI веб-сервер, разработанный специально для приложений FastAPI. +![ncorn](../logo.png) -## Возможности +_ncorn — готовый к продакшену ASGI веб-сервер для FastAPI приложений._ + +--- + +**Документация**: [https://ncorn.ndugram.dev](https://ncorn.readthedocs.io/) + +**Исходный код**: [https://github.com/ndugram/ncorn](https://github.com/ndugram/ncorn) + +--- + +**ncorn** — это реализация ASGI веб-сервера для Python, разработанная специально для FastAPI приложений. -- Асинхронный TCP-сервер с использованием asyncio -- HTTP/1.1 парсер на базе httptools -- ASGI адаптер -- Система middleware (серверного уровня) -- Валидация запросов (заголовки, ограничения размера тела) -- Ограничение частоты запросов (rate limiting) -- Graceful shutdown -- Keep-alive соединения +До недавнего времени в Python не было минимального низкоуровневого интерфейса сервер/приложение для асинхронных фреймворков. [Спецификация ASGI](https://asgi.readthedocs.io/en/latest/) заполняет этот пробел, что позволяет создавать общий набор инструментов для всех асинхронных фреймворков. -## Функции безопасности +ncorn построен с упором на **производительность** и **готовность к продакшену**, с встроенными мерами безопасности и поддержкой SSL/TLS. -- Ограничение максимального размера тела запроса -- Валидация заголовков -- Защита от Slowloris (таймауты) -- IP-based rate limiting +## Возможности + +- **Высокая производительность** — построен на asyncio +- **ASGI совместимость** — полная поддержка ASGI интерфейса для FastAPI +- **Готов к продакшену** — rate limiting, валидация запросов, защита от slowloris +- **SSL/TLS** — нативная поддержка HTTPS без reverse proxy +- **Несколько воркеров** — поддержка нескольких процессов +- **Авто-перезагрузка** — режим разработки с отслеживанием файлов +- **Красивое логирование** — красивый вывод в стиле uvicorn +- **Безопасность** — валидация заголовков, ограничения размера тела, IP rate limiting ## Быстрый старт +ncorn доступен на PyPI, установка проста: + ```bash pip install ncorn -ncorn module:app ``` +Создадим простое FastAPI приложение: + +```python +from fastapi import FastAPI + +app = FastAPI() + +@app.get("/") +async def root(): + return {"message": "Привет от ncorn!"} +``` + +Запустим его с ncorn: + +```bash +ncorn main:app +``` + +## Запуск с HTTPS + +ncorn имеет встроенную поддержку SSL/TLS — не нужен внешний reverse proxy: + +```bash +ncorn main:app --ssl-keyfile certs/key.pem --ssl-certfile certs/cert.pem +``` + +Сервер запустится на `https://127.0.0.1:8000` + ## Требования - Python 3.11+ - httptools - rich +- annotated-doc diff --git a/docs/ru/installation.md b/docs/ru/installation.md new file mode 100644 index 0000000..ff2e45d --- /dev/null +++ b/docs/ru/installation.md @@ -0,0 +1,28 @@ +# Установка + +ncorn доступен на PyPI и может быть установлен через pip: + +```bash +pip install ncorn +``` + +## Требования + +- Python 3.11+ +- httptools >= 0.5.0 +- rich >= 13.0.0 +- annotated-doc >= 0.0.4 + +## Версия для разработки + +Если вам нужна последняя версия из git: + +```bash +pip install git+https://github.com/ndugram/ncorn.git +``` + +## Проверка установки + +```bash +ncorn --version +``` diff --git a/docs/ru/middleware.md b/docs/ru/middleware.md deleted file mode 100644 index abc1e7f..0000000 --- a/docs/ru/middleware.md +++ /dev/null @@ -1,35 +0,0 @@ -# Middleware - -ncorn включает middleware на уровне сервера для обработки запросов. - -## Доступные Middleware - -### ValidationMiddleware - -Валидирует HTTP методы, заголовки и пути. - -### RateLimitMiddleware - -IP-based rate limiting для предотвращения злоупотреблений. - -## Создание своего middleware - -Вы можете создать свой middleware расширив `BaseMiddleware`: - -```python -from ncorn.middleware.base import BaseMiddleware, ASGIApp - -class CustomMiddleware(BaseMiddleware): - async def __call__(self, scope, receive, send): - # Обработка запроса - await self.app(scope, receive, send) - # Обработка ответа -``` - -## Порядок выполнения middleware - -Middleware выполняется в следующем порядке: - -1. ValidationMiddleware -2. RateLimitMiddleware -3. Ваше приложение diff --git a/docs/ru/quick-start.md b/docs/ru/quick-start.md deleted file mode 100644 index af70706..0000000 --- a/docs/ru/quick-start.md +++ /dev/null @@ -1,40 +0,0 @@ -# Быстрый старт - -## Установка - -```bash -pip install ncorn -``` - -## Базовое использование - -Создайте приложение FastAPI: - -```python -from fastapi import FastAPI - -app = FastAPI() - -@app.get("/") -async def root(): - return {"message": "Hello from ncorn!"} -``` - -Запустите с ncorn: - -```bash -ncorn module:app -``` - -## Параметры командной строки - -```bash -ncorn module:app --host 0.0.0.0 --port 8080 -``` - -## Опции - -- `--host` - Хост для привязки (по умолчанию: 127.0.0.1) -- `--port` - Порт для привязки (по умолчанию: 8000) -- `--reload` - Включить автоперезагрузку при изменении файлов -- `--workers` - Количество рабочих процессов (по умолчанию: 1) diff --git a/docs/ru/security.md b/docs/ru/security.md deleted file mode 100644 index 809ac80..0000000 --- a/docs/ru/security.md +++ /dev/null @@ -1,42 +0,0 @@ -# Безопасность - -ncorn включает несколько функций безопасности для защиты вашего приложения. - -## Встроенные функции безопасности - -### Ограничение размера тела запроса - -Ограничивает максимальный размер входящих тел запросов для предотвращения DoS-атак. - -```bash -ncorn app:app --max-body-size 8388608 # 8 МБ -``` - -### Валидация заголовков - -Проверяет HTTP заголовки и отклоняет неправильно сформированные запросы. - -### Защита по таймаутам - -- `header_timeout` - Лимит времени для чтения заголовков запроса -- `body_timeout` - Лимит времени для чтения тела запроса -- Предотвращает атаки Slowloris - -```bash -ncorn app:app --header-timeout 30 --body-timeout 60 -``` - -### Ограничение частоты запросов (Rate Limiting) - -Ограничивает количество запросов с одного IP адреса. - -```bash -ncorn app:app --rate-limit 100 --rate-limit-window 60 -``` - -## Рекомендации - -1. Всегда устанавливайте соответствующие ограничения размера тела -2. Используйте rate limiting в продакшене -3. Устанавливайте минимально возможные таймауты для вашего случая -4. Запускайте за reverse proxy типа nginx для SSL/TLS терминации diff --git a/docs/ru/server-behavior.md b/docs/ru/server-behavior.md new file mode 100644 index 0000000..a075042 --- /dev/null +++ b/docs/ru/server-behavior.md @@ -0,0 +1,82 @@ +# Поведение сервера + +## Жизненный цикл + +ncorn следует протоколу ASGI lifespan для управления жизненным циклом приложения. + +### Запуск + +1. Загрузка конфигурации из файла, окружения или CLI аргументов +2. Парсинг и валидация приложения +3. Создание SSL контекста, если SSL настроен +4. Запуск ASGI сервера +5. Вызов события lifespan `startup`, если определено + +### Остановка + +1. Получение сигнала остановки (SIGINT, SIGTERM) +2. Прекращение принятия новых соединений +3. Ожидание завершения активных запросов (grace период) +4. Вызов события lifespan `shutdown`, если определено +5. Закрытие всех соединений +6. Завершение процесса + +## Обработка соединений + +### Keep-Alive + +ncorn поддерживает HTTP keep-alive соединения для повторного использования TCP соединений. + +- Настраивается через `--keepalive-timeout` +- Максимум запросов на соединение через `--keepalive-requests` + +### Обработка запросов + +1. Принятие входящего TCP соединения +2. Парсинг заголовков HTTP запроса +3. Валидация заголовков (размер, количество, формат) +4. Чтение тела запроса, если есть +5. Вызов ASGI приложения +6. Отправка ответа +7. Keep-alive соединение или закрытие + +### Таймауты + +ncorn реализует несколько уровней таймаутов: + +- **header_timeout** — время на получение всех заголовков +- **body_timeout** — время на чтение тела запроса +- **keepalive_timeout** — время ожидания следующего запроса на keep-alive +- **request_timeout** — время на обработку запроса приложением + +## Режим нескольких воркеров + +При использовании `--workers > 1`, ncorn создаёт несколько процессов: + +- Каждый воркер работает в своём event loop +- Воркеры используют тот же порт (наследование сокета) +- Воркеры перезапускаются независимо при краше + +## SSL/TLS + +ncorn имеет нативную поддержку SSL/TLS: + +- TLS 1.3 (по умолчанию), TLS 1.2, TLS 1.1, TLS 1.0 +- Пользовательские файлы сертификатов и ключей +- Не требует reverse proxy + +## Логирование + +ncorn предоставляет логирование в стиле uvicorn: + +``` +21:50:53.290 | INFO | SSL enabled: TLSv1.3 +21:50:53.291 | ncorn | Application startup complete +21:50:53.291 | ncorn | Ncorn running on https://127.0.0.1:8443 +``` + +Каждый запрос логируется с: +- HTTP методом +- Путём +- Кодом статуса +- Задержкой diff --git a/docs/ru/settings.md b/docs/ru/settings.md new file mode 100644 index 0000000..0f3fa55 --- /dev/null +++ b/docs/ru/settings.md @@ -0,0 +1,106 @@ +# Настройки + +ncorn можно настроить через параметры командной строки, конфигурационный файл или программно. + +## Параметры командной строки + +```bash +ncorn module:app [ОПЦИИ] +``` + +### Основные параметры + +| Параметр | Описание | По умолчанию | +|----------|----------|--------------| +| `app` | Приложение в формате 'module:app' | Обязательно | +| `--host` | Хост для привязки | 127.0.0.1 | +| `--port` | Порт для привязки | 8000 | +| `--reload` | Включить авто-перезагрузку | false | +| `--workers` | Количество воркеров | 1 | + +### Ограничения запросов + +| Параметр | Описание | По умолчанию | +|----------|----------|--------------| +| `--max-body-size` | Максимальный размер тела запроса | 16777216 (16MB) | +| `--max-headers` | Максимальное количество заголовков | 100 | +| `--keepalive-requests` | Макс. запросов на keep-alive соединение | 100 | + +### Таймауты + +| Параметр | Описание | По умолчанию | +|----------|----------|--------------| +| `--header-timeout` | Таймаут чтения заголовков | 30.0 | +| `--body-timeout` | Таймаут чтения тела | 60.0 | +| `--keepalive-timeout` | Таймаут keep-alive | 5.0 | + +### Rate Limiting + +| Параметр | Описание | По умолчанию | +|----------|----------|--------------| +| `--rate-limit` | Лимит запросов в окно | 100 | +| `--rate-limit-window` | Окно rate limiting | 60.0 | + +### SSL/TLS + +| Параметр | Описание | По умолчанию | +|----------|----------|--------------| +| `--ssl-keyfile` | Путь к SSL ключу | None | +| `--ssl-certfile` | Путь к SSL сертификату | None | +| `--ssl-version` | Версия TLS (2=TLSv1, 3=TLSv1.1, 4=TLSv1.2, 5=TLSv1.3) | 5 | + +### Другие параметры + +| Параметр | Описание | По умолчанию | +|----------|----------|--------------| +| `--verbose` | Подробное логирование | false | + +## Конфигурационный файл + +ncorn также поддерживает конфигурацию через файл `ncorn.json`: + +```json +{ + "host": "0.0.0.0", + "port": 8000, + "workers": 4, + "reload": false, + "max_body_size": 16777216, + "ssl_keyfile": "certs/key.pem", + "ssl_certfile": "certs/cert.pem", + "ssl_version": 5 +} +``` + +Параметры командной строки переопределяют настройки из файла. + +## Программная настройка + +Вы также можете настроить ncorn программно: + +```python +from ncorn.config import Config +from ncorn.server import HTTPServer +from myapp import app + +config = Config( + host="0.0.0.0", + port=8080, + workers=4, + max_body_size=32 * 1024 * 1024, + ssl_keyfile="certs/key.pem", + ssl_certfile="certs/cert.pem", +) + +server = HTTPServer(app, config) +``` + +## Переменные окружения + +ncorn поддерживает настройку через переменные окружения: + +- `NCORN_HOST` — хост сервера +- `NCORN_PORT` — порт сервера +- `NCORN_WORKERS` — количество воркеров +- `NCORN_SSL_KEYFILE` — путь к SSL ключу +- `NCORN_SSL_CERTFILE` — путь к SSL сертификату diff --git a/mkdocs.yml b/mkdocs.yml index ad179c8..f14545a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,101 +1,122 @@ site_name: ncorn site_description: Production-ready ASGI web server for FastAPI applications -site_author: White NEFOR site_url: https://ncorn.readthedocs.io/ - -docs_dir: docs - -repo_url: https://github.com/ndugram/ncorn repo_name: ndugram/ncorn +repo_url: https://github.com/ndugram/ncorn +edit_uri: edit/main/docs/ -copyright: | - Copyright © 2026 White NEFOR - -extra: - social: - - icon: fontawesome/brands/github - link: https://github.com/ndugram/ncorn - - alternate: - - link: / - name: English - - link: /ru/ - name: Russian - -nav: - - Home: index.md - - English: - - Quick Start: en/quick-start.md - - CLI: en/cli.md - - Configuration: en/configuration.md - - Examples: en/examples.md - - Dependencies: en/dependencies.md - - Security: en/security.md - - Middleware: en/middleware.md - - API Reference: en/api-reference.md - - Russian: - - Main: ru/index.md - - Quick Start: ru/quick-start.md - - CLI: ru/cli.md - - Configuration: ru/configuration.md - - Examples: ru/examples.md - - Dependencies: ru/dependencies.md - - Security: ru/security.md - - Middleware: ru/middleware.md - - API Reference: ru/api-reference.md +strict: true theme: name: material - language: en logo: logo.png favicon: logo.png - icon: - repo: fontawesome/brands/github - palette: - - scheme: default - primary: deep orange - accent: orange + - scheme: "default" + media: "(prefers-color-scheme: light)" toggle: - icon: material/weather-night - name: Switch to dark mode - - - scheme: slate - primary: deep orange - accent: orange + icon: "material/lightbulb" + name: "Switch to dark mode" + - scheme: "slate" + media: "(prefers-color-scheme: dark)" + primary: "deep orange" + accent: "orange" toggle: - icon: material/weather-sunny - name: Switch to light mode + icon: "material/lightbulb-outline" + name: "Switch to light mode" + + icon: + repo: fontawesome/brands/github features: - - navigation.instant - - navigation.tracking - - navigation.tabs - - navigation.tabs.sticky - - navigation.tabs.hover + - content.code.annotate + - content.code.copy + - content.tabs.link + - navigation.footer + - navigation.path - navigation.sections - - navigation.expand - navigation.top - - content.code.copy - - content.code.annotate + - navigation.tracking - search.suggest - search.highlight + - toc.follow + +extra: + social: + - icon: fontawesome/brands/github + link: https://github.com/ndugram/ncorn + - icon: fontawesome/brands/discord + link: https://discord.gg/ncorn + - icon: fontawesome/brands/twitter + link: https://x.com/ncorn_dev + + alternate: + - link: / + name: English + - link: /ru/ + name: Russian markdown_extensions: - - admonition - - tables - attr_list + - admonition + - codehilite: + css_class: highlight - toc: permalink: true - - pymdownx.highlight: - anchor_linenums: true + - pymdownx.details - pymdownx.inlinehilite - pymdownx.snippets - pymdownx.superfences - - pymdownx.details - pymdownx.tabbed: alternate_style: true + - pymdownx.emoji: + emoji_index: !!python/name:material.extensions.emoji.twemoji + emoji_generator: !!python/name:material.extensions.emoji.to_svg + - pymdownx.tasklist: + custom_checkbox: true + - pymdownx.extra: plugins: - - search \ No newline at end of file + - search + - mkdocstrings: + handlers: + python: + inventory: + - https://docs.python.org/3/objects.inv + +nav: + - Welcome: + - en: en/index.md + - ru: ru/index.md + - Installation: + - en: en/installation.md + - ru: ru/installation.md + - Settings: + - en: en/settings.md + - ru: ru/settings.md + - Server Behavior: + - en: en/server-behavior.md + - ru: ru/server-behavior.md + - Concepts: + - en: en/concepts/asgi.md + - ru: ru/concepts/asgi.md + - Lifespan: + - en: en/concepts/lifespan.md + - ru: ru/concepts/lifespan.md + - WebSockets: + - en: en/concepts/websockets.md + - ru: ru/concepts/websockets.md + - Deployment: + - Deployment: + - en: en/deployment/index.md + - ru: ru/deployment/index.md + - Docker: + - en: en/deployment/docker.md + - ru: ru/deployment/docker.md + - API Reference: + - en: en/api-reference.md + - ru: ru/api-reference.md + - Contributing: + - en: en/contributing.md + - ru: ru/contributing.md diff --git a/uv.lock b/uv.lock index f86ee0e..9676375 100644 --- a/uv.lock +++ b/uv.lock @@ -1,6 +1,11 @@ version = 1 revision = 3 requires-python = ">=3.11" +resolution-markers = [ + "python_full_version >= '3.14'", + "python_full_version == '3.13.*'", + "python_full_version < '3.13'", +] [[package]] name = "annotated-doc" @@ -70,7 +75,7 @@ wheels = [ [[package]] name = "ncorn" -version = "1.0.0" +version = "1.0.1" source = { editable = "." } dependencies = [ { name = "annotated-doc" },