Skip to main content

A high-performance Python web framework with Rust extensions

Project description

🌟 Haske Web Framework

Haske is a modern Python web framework that combines the simplicity of Flask, the power of FastAPI, and the performance of Rust extensions. It is designed for developers who want to build fast, scalable, and maintainable web applications without unnecessary complexity.


📖 Table of Contents

  1. Introduction
  2. Installation
  3. Quickstart
  4. Routing
  5. Requests & Responses
  6. Middleware
  7. Sessions
  8. Templates
  9. ORM & Database
  10. Authentication
  11. CLI
  12. WebSockets
  13. Error Handling
  14. Testing
  15. Deployment
  16. Contributing
  17. License

📌 Introduction

Haske was built to solve a common problem in Python web development:

  • Flask is simple, but too minimal for large apps.
  • Django is powerful, but heavy and opinionated.
  • FastAPI is fast, but focused mostly on APIs.

Haske combines the best of all worlds:

  • 🌀 Simple API — inspired by Flask.
  • Fast — powered by Rust extensions.
  • 🔧 Flexible — lets you add only what you need.
  • 🌍 Full-stack ready — supports templates, ORM, sessions, and WebSockets.

⚙️ Installation

Requirements

  • Python 3.8+
  • Rust (for building extensions)
  • pip / virtualenv

Install Haske

pip install haske

Or, from source:

git clone https://github.com/Python-Katsina/haske-python.git
cd haske-python
python setup.py

🚀 Quickstart

Create a file app.py:

from haske import Haske, Request, Response

app = Haske(__name__)

@app.route("/")
async def home(request: Request) -> Response:
    return {"message": "Hello, Haske!"}

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8000, reload=True)

Run the app:

python app.py

Visit: http://localhost:8000 🎉


🔀 Routing

Routing is how Haske connects URLs to functions.

Basic Route

@app.route("/hello")
async def say_hello(request: Request):
    return {"message": "Hello World"}

Path Parameters

@app.route("/user/{username}")
async def greet_user(request: Request, username: str):
    return {"message": f"Hello {username}"}

Query Parameters

@app.route("/search")
async def search(request: Request):
    query = request.query.get("q", "none")
    return {"search_for": query}

HTTP Methods

@app.route("/submit", methods=["POST"])
async def submit(request: Request):
    data = await request.json()
    return {"received": data}

📥 Requests & Responses

Haske provides easy access to HTTP requests and responses.

Request Object

@app.route("/headers")
async def headers(request: Request):
    return {"user_agent": request.headers.get("User-Agent")}

JSON Response

@app.route("/json")
async def json_response(request: Request):
    return {"framework": "Haske", "type": "JSON"}

Redirect

from haske.responses import RedirectResponse

@app.route("/go")
async def go(request: Request):
    return RedirectResponse(url="/hello")

🧩 Middleware

What is Middleware?

Middleware is code that runs before or after each request.
Uses include: logging, authentication, CORS, compression, etc.

Example: Logging Middleware

from haske.middleware import Middleware

class LoggingMiddleware(Middleware):
    async def before_request(self, request):
        print(f"➡️ Incoming request: {request.url}")

    async def after_response(self, request, response):
        print(f"⬅️ Response status: {response.status_code}")

app.add_middleware(LoggingMiddleware)

🔑 Sessions

What are Sessions?

HTTP is stateless — it doesn’t remember users between requests.
Sessions allow you to store user data (like logins or cart items) across multiple requests.

Why Sessions Matter

  • 🔐 Authentication (keep users logged in)
  • 🛒 Shopping carts
  • 🎛 Preferences & personalization

Example: Using Sessions

@app.route("/login", methods=["POST"])
async def login(request: Request):
    data = await request.json()
    username = data.get("username")

    # Save to session
    request.session["user"] = username
    return {"message": f"Welcome {username}"}

@app.route("/profile")
async def profile(request: Request):
    user = request.session.get("user")
    if not user:
        return {"error": "Not logged in"}
    return {"profile": f"User profile for {user}"}

🎨 Templates

Haske supports rendering HTML templates (Jinja2 or similar).

Example

@app.route("/welcome")
async def welcome(request: Request):
    return app.template("welcome.html", {"name": "Haske User"})

templates/welcome.html:

<html>
  <body>
    <h1>Welcome {{ name }}!</h1>
  </body>
</html>

🗄️ ORM & Database

Haske can integrate with SQLAlchemy or other ORMs.

Example: SQLAlchemy

from haske.orm import Model, Column, Integer, String

class User(Model):
    id = Column(Integer, primary_key=True)
    name = Column(String)

# Create
new_user = User(name="Alice")
db.session.add(new_user)
db.session.commit()

# Query
user = User.query.filter_by(name="Alice").first()

🔐 Authentication

Authentication is usually built on top of sessions.

Example

@app.route("/auth/login", methods=["POST"])
async def auth_login(request: Request):
    data = await request.json()
    if data["username"] == "admin" and data["password"] == "123":
        request.session["user"] = "admin"
        return {"status": "logged_in"}
    return {"error": "Invalid credentials"}

@app.route("/auth/protected")
async def protected(request: Request):
    if request.session.get("user") != "admin":
        return {"error": "Unauthorized"}
    return {"message": "Welcome, admin!"}

🖥️ CLI

Haske comes with a command-line interface.

Create New Project

haske new myproject

Run Server

haske run

📡 WebSockets

Haske supports real-time apps with WebSockets.

Example: Chat

@app.websocket("/ws")
async def websocket_endpoint(socket):
    await socket.send("Welcome to Haske Chat!")
    async for message in socket:
        await socket.send(f"You said: {message}")

⚠️ Error Handling

Custom Error Handler

@app.exception_handler(404)
async def not_found(request: Request, exc):
    return {"error": "Page not found"}

🧪 Testing

Haske makes testing simple.

Example: Using pytest

from haske.testing import TestClient

def test_homepage():
    client = TestClient(app)
    response = client.get("/")
    assert response.status_code == 200
    assert response.json()["message"] == "Hello, Haske!"

🚀 Deployment

Run with Uvicorn

uvicorn app:app --host 0.0.0.0 --port 8000 --workers 4

Run with Gunicorn

gunicorn -k uvicorn.workers.UvicornWorker app:app

🤝 Contributing

  1. Fork the repo.
  2. Create a feature branch.
  3. Submit a pull request.

We welcome contributions in:

  • Bug fixes
  • New features
  • Docs improvements

📜 License

MIT License © 2025 Python Katsina Community

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

haske-0.2.14-py3-none-any.whl (51.8 kB view details)

Uploaded Python 3

File details

Details for the file haske-0.2.14-py3-none-any.whl.

File metadata

  • Download URL: haske-0.2.14-py3-none-any.whl
  • Upload date:
  • Size: 51.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for haske-0.2.14-py3-none-any.whl
Algorithm Hash digest
SHA256 9200a831018734c24dbce366bf59f794f27da7084657b708fc1738a19525bbeb
MD5 21436b1fb60b5cf9bfae56e45ef086fb
BLAKE2b-256 bd99db70627f1a08ab00337074fa838193283e30488f2679f0b9be36fa9bb895

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page