Overview

HARP’s architecture is designed around modularity, loose coupling, and extensibility. This page provides a high-level overview of the architecture and core concepts.

Codebase structure

The codebase is divided into two main parts:

Core (harp package)

Provides the base functionality and tools for building proxy services. The core is framework code that applications build upon.

Applications (harp_apps package)

Independent modules that provide features. Both built-in and user-provided applications use the same integration mechanism.

HARP Architecture Overview

Core packages

  • ASGI (harp.asgi) - Building blocks for ASGI (Asynchronous Server Gateway Interface)

  • Command line (harp.commandline) - Core commands and building blocks for application-specific commands

  • Config (harp.config) - Configuration management system supporting various formats and sources

  • Controllers (harp.controllers) - Building blocks for web controllers, turning requests into responses

  • Errors (harp.errors) - Exception classes and error handling tools

  • Event dispatcher (harp.event_dispatcher) - Event handling system based on whistle

  • HTTP (harp.http) - Building blocks for HTTP

  • Meta (harp.meta) - Metadata management tools

  • Models (harp.models) - Data modeling for core objects (plain old Python objects, not tied to storage)

  • Typing (harp.typing) - Type and interface definitions

  • Utils (harp.utils) - Collection of utility functions and helper classes

  • Views (harp.views) - Presentation layer for controllers

Core concepts

HARP employs several software engineering patterns to organize the codebase and ensure components work together while remaining loosely coupled.

Dependency injection and inversion of control

Dependency Injection (DI) is a design pattern where an object’s dependencies are provided by an external source rather than the object creating them itself.

Inversion of Control (IoC) is a design principle where the control of object creation and management is transferred from the application code to a container or framework.

Both principles make the code more modular and easier to test. HARP uses rodi for dependency injection.

👀 Read more about Dependency Injection

Event-driven architecture

An Event-Driven Architecture (EDA) allows components to communicate and extend each other without tight coupling. Events can be network-based (like in microservice architectures) or internal to a process (like in HARP).

HARP uses Whistle, a simple Python event dispatcher, allowing applications to easily expose or hook into system events.

👀 Read more about Events

Pluggable applications

Applications are independent modules that integrate with HARP through a standard protocol. Both core features and third-party extensions use the same mechanism.

Applications hook into the system through lifecycle events (on_bind, on_bound, on_ready, on_shutdown) and can register services, listen to events, and extend functionality.

👀 Read more about Applications

Request flow

When an HTTP request comes into HARP, the following sequence of operations happens:

HARP Sequence of Operations

Once the Services Provider is initialized, most services are instantiated lazily, on demand, just in time.