# HTTP Server & Health Checks

# HTTP Server & Health Checks

<details>
<summary>Relevant source files</summary>

The following files were used as context for generating this wiki page:

- [src/http/__tests__/http-server.test.ts](src/http/__tests__/http-server.test.ts)
- [src/http/health-check.ts](src/http/health-check.ts)
- [src/http/http-server.ts](src/http/http-server.ts)
- [src/ports/health-check-port.ts](src/ports/health-check-port.ts)

</details>



The `http` module provides a lightweight, dependency-free HTTP server factory designed primarily for exposing service health status and simple administrative routes. It leverages Node.js's native `http` module to minimize overhead and avoid external dependencies like Express or Fastify.

## Overview

The primary purpose of the HTTP layer in the Primebrick SDK is to provide a standardized `/health` endpoint for orchestrators (like Kubernetes or Docker Compose) to monitor service viability. It decouples the logic of "what makes a service healthy" from the "how to serve that information over HTTP" through the use of the `HealthCheckPort` interface.

### Key Components
*   **`createHttpServer`**: A factory function that initializes and starts the Node.js `Server` [src/http/http-server.ts:17-17]().
*   **`HealthCheck`**: A utility class that aggregates various health indicators (DB, NATS, custom) into a single result [src/http/health-check.ts:16-16]().
*   **`HealthCheckPort`**: A port interface that allows the SDK to check database connectivity without knowing the specific database driver being used [src/ports/health-check-port.ts:8-11]().

---

## HTTP Server Factory

The `createHttpServer` function creates a server based on `HttpServerOptions`. It handles the `/health` route automatically and allows consumers to inject custom logic via a `routeHandler` callback.

### HttpServerOptions
| Property | Type | Description |
| :--- | :--- | :--- |
| `port` | `number` | The port to listen on. |
| `healthCheck` | `HealthCheck` | (Optional) Instance to run diagnostic checks. |
| `serviceName` | `string` | (Optional) Identifier for the service. |
| `routeHandler` | `Function` | (Optional) Callback for custom routing logic. |

**Sources:** [src/http/http-server.ts:4-10]()

### Request Flow
The server processes incoming `IncomingMessage` requests and evaluates them against the built-in health route before passing them to the optional `routeHandler`.

```mermaid
graph TD
    A["Incoming Request (req, res)"] --> B{"Path == '/health'?"}
    B -- "Yes" --> C{"HealthCheck Provided?"}
    C -- "Yes" --> D["hc.runAll()"]
    D --> E["Respond 200/503 with JSON"]
    C -- "No" --> F["Respond 200 {'status': 'healthy'}"]
    B -- "No" --> G{"routeHandler Provided?"}
    G -- "Yes" --> H["Execute routeHandler(req, res, url)"]
    H -- "Handled" --> I["End Request"]
    H -- "Not Handled" --> J["Respond 404 Not Found"]
    G -- "No" --> J
```
**Sources:** [src/http/http-server.ts:18-43]()

---

## Health Check System

The `HealthCheck` class manages the execution of diagnostic pings. It is designed to be DB-agnostic by relying on the `HealthCheckPort` [src/http/health-check.ts:12-15]().

### HealthCheckPort Interface
To use database health checks, the consuming microservice must provide an implementation of this interface:
```typescript
export interface HealthCheckPort {
  ping(): Promise<boolean>;
}
```
**Sources:** [src/ports/health-check-port.ts:8-11]()

### Aggregating Results
The `HealthCheck` class can combine the mandatory DB check with optional custom checks (e.g., checking if a NATS connection is active or a specific directory is writable).

| Method | Role | Logic |
| :--- | :--- | :--- |
| `checkDb()` | DB Ping | Calls `dbPing.ping()`. Returns `{ ok: false }` if it throws [src/http/health-check.ts:22-29](). |
| `runAll()` | Batch Execution | Executes `checkDb` and all `customChecks` concurrently [src/http/health-check.ts:31-43](). |
| `isHealthy()` | Status Evaluation | Returns `true` only if **every** check in the result set has `ok: true` [src/http/health-check.ts:45-47](). |

### Data Structures
The `HealthCheckResult` shape ensures consistent reporting across different types of checks.
```typescript
export interface HealthCheckResult {
  ok: boolean;
  [key: string]: unknown; // Allows for 'error' or 'detail' fields
}
```
**Sources:** [src/http/health-check.ts:3-6]()

---

## Code Entity Map

The following diagram maps the logical components of the HTTP and Health modules to their specific code entities.

```mermaid
classDiagram
    class HttpServerFactory {
        <<Function>>
        createHttpServer(options: HttpServerOptions)
    }
    class HttpServerOptions {
        <<Interface>>
        port: number
        healthCheck: HealthCheck
        routeHandler: Function
    }
    class HealthCheck {
        <<Class>>
        +checkDb() HealthCheckResult
        +runAll() Record~string, HealthCheckResult~
        +isHealthy(results) boolean
    }
    class HealthCheckPort {
        <<Interface>>
        +ping() Promise~boolean~
    }
    
    HttpServerFactory ..> HttpServerOptions : "uses"
    HttpServerOptions --> HealthCheck : "references"
    HealthCheck o-- HealthCheckPort : "delegates DB ping to"
    HttpServerFactory ..> HealthCheck : "calls runAll() on /health"
```
**Sources:** [src/http/http-server.ts:4-17](), [src/http/health-check.ts:16-20](), [src/ports/health-check-port.ts:8-11]()

---

## Example Implementation

When a request hits `GET /health`, the server interacts with the `HealthCheck` class to determine the response code.

1.  **Healthy State**: If `db.ping()` returns `true` and all `customChecks` pass, the server returns **200 OK** with `status: "healthy"` [src/http/http-server.ts:26-27]().
2.  **Degraded State**: If any check fails (e.g., DB is down), the server returns **503 Service Unavailable** with `status: "degraded"` and the specific error details in the `checks` object [src/http/http-server.ts:26-27]().

### Custom Route Handling
The `routeHandler` allows services to implement custom endpoints without a full web framework:
```typescript
const server = await createHttpServer({
  port: 3000,
  routeHandler: async (req, res, url) => {
    if (url.pathname === "/api/custom") {
      res.end("Custom Logic");
      return true; // Mark as handled
    }
    return false; // Continue to 404
  }
});
```
**Sources:** [src/http/http-server.ts:36-39](), [src/http/__tests__/http-server.test.ts:39-42]()

---
