Hajime 1.3
Lightweight Website Framework

## Overview
Hajime is a lightweight Python-based web framework that provides built-in support for routing, middleware, WebSocket handling, templating, database integration, and static file serving. It is designed to be simple, flexible, and easy to use for building web applications and APIs.

## 1.3 Version:
- getting data from form is fixed

## Features
- **Routing**: Supports HTTP request handling with different methods
- **Middleware**: Custom middleware functions for request filtering
- **WebSockets**: Built-in WebSocket support for real-time applications
- **Templating**: Simple template rendering with variable replacement and for-loops
- **Database Integration**: Works with SQLite and PostgreSQL databases using SQLAlchemy
- **Static File Serving**: Efficiently serves files from a static directory with caching
- **Session Management**: Basic session handling with cookies
- **Performance Optimizations**: Preloading of templates and static files

## Quick Start
Create a simple web server with Hajime:

```python
from Hajime import *

app = Hajime()

@app.route("/", methods=["GET"])
def home(environ):
    return "Hello, World!"

if __name__ == "__main__":
    app.launch()
```

Run the script, and the server will start at an available port. (Default for Hajime is 8000)

## Routing
Hajime provides an easy way to define routes with the `@app.route` decorator.

```python
@app.route("/hello", methods=["GET"])
def hello(environ):
    return "Hello from Hajime!"
```

Routes can handle different HTTP methods:

```python
@app.route("/submit", methods=["POST"])
def submit(environ):
    data = get_json(environ)
    return json_response({"message": "Data received", "data": data})
```

### Redirecting
```python
@app.route("/")
def home(environ):
    return '<h1>hello</h1>'

@app.route("/go-home")
def redirect_home(environ):
    return app.redirect('/')
```

## Middleware
Middleware functions can be registered using `app.use()` to handle request processing before passing control to the route handler.

```python
def auth_middleware(environ, params):
    session = environ.get("SESSION", {})
    if not session.get("user"):
        return "Unauthorized access"
    return None

app.use(auth_middleware)
```

## WebSockets
Define a WebSocket route using `@app.websocket`:

```python
@app.websocket("/ws")
async def websocket_handler(websocket):
    await websocket.send("Welcome to the WebSocket server!")
    while True:
        message = await websocket.receive()
        await websocket.send(f"You said: {message}")
```

### JavaScript WebSocket Client
```html
<script>
const socket = new WebSocket("ws://localhost:8765/ws");

socket.onopen = () => {
    console.log("Connected to WebSocket server");
    socket.send("Hello, Server!");
};

socket.onmessage = (event) => {
    console.log("Message from server:", event.data);
};

socket.onerror = (error) => {
    console.error("WebSocket error:", error);
};
</script>
```

## Template Rendering
Hajime supports HTML templates with variable replacement and for-loops. Templates are automatically preloaded for better performance.

```python
@app.route("/greet")
def greet(environ):
    return app.template("greet.html", name="Alice")
```

### greet.html
```html
<h1>Hello, {{name}}!</h1>
<!-- For-loop example -->
{% for key, value in items.items() %}
    <p>{{key}}: {{value}}</p>
{% endfor %}
```

## Database Support
Hajime includes a Database class that leverages SQLAlchemy to interact with PostgreSQL and SQLite.

```python
from Hajime import Database

# Connect to SQLite database
db = Database("sqlite", host="", user="", password="", database="data.db")

# Or connect to PostgreSQL
# db = Database("postgresql", host="localhost", user="user", password="pass", database="mydb", port=5432)

# Execute queries
db.execute_query("CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)")
```

Fetching data:
```python
users = db.fetch_all("SELECT * FROM users")
print(users)

user = db.fetch_one("SELECT * FROM users WHERE id = 1")
print(user)
```

Database utilities:
```python
# Get list of tables
tables = db.get_tables()

# Get data from a specific table
users_data = db.get_table_data("users")
```

## Static Files
Hajime serves static files from the `static/` directory and preloads them for better performance.

Access files with:
```
http://localhost:8000/static/style.css
```

## Session Management
Hajime supports session handling with cookies.

```python
@app.route("/login", methods=["POST"])
def login(environ):
    session_id, session = app.get_session(environ)
    session["user"] = "admin"
    app.set_session(session_id, session)
    return "Logged in!"
```

## 🏃‍♂️ Running the Server
Launch the HTTP and WebSocket servers:
```python
app.launch(port=8000, ws_port=8765)
```

The framework automatically finds available ports if the specified ones are in use.

## Error Handling
Custom error handlers can be defined using:
```python
@app.error_handler(404)
def not_found():
    return "Custom 404 Page Not Found"
```

## Form Data Handling
Hajime provides utilities to handle form data in POST requests:

```python
@app.route("/submit-form", methods=["POST"])
def submit_form(environ):
    form_data = get_form_data(environ)
    return f"Received: {form_data}"
```

## Support

For support, email FCzajkowski@proton.me, or Contact through X.com: FCzajkowski

---