Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Architecture

## Overview

This is a minimal "Hello World" web application consisting of a single
static HTML page served by Python's built-in HTTP server. No external
frameworks, databases, or build tools are required.

## File Structure

```
.
├── index.html # Static HTML page displaying "Hello World"
├── server.py # Python HTTP server (stdlib only)
├── Dockerfile # Container image definition
├── docker-compose.yml # One-command container orchestration
├── RUNNING.md # Instructions for running the application
├── ARCHITECTURE.md # This file – architecture documentation
└── tests/
└── test_server.py # Automated tests for the server
```

## Technology Choices

| Component | Choice | Rationale |
| -------------- | --------------------------------------- | ------------------------------------------------- |
| Web server | `http.server` (Python standard library) | Zero dependencies; ships with every Python 3 install |
| Containerisation | Docker + Docker Compose | Reproducible environment; single-command startup |
| Frontend | Plain HTML + inline CSS | No build step needed for a single static page |
| Testing | `unittest` (Python standard library) | No extra test runner required |

## How It Works

1. `server.py` starts a `TCPServer` on `0.0.0.0:8000` using
`SimpleHTTPRequestHandler` pointed at the current working directory.
2. When a browser requests `/`, the handler automatically serves
`index.html` as the directory index.
3. `index.html` renders a centred "Hello World" heading on a white
background.

## Design Decisions

* **No framework** – A full web framework (Flask, FastAPI, etc.) would
be overkill for serving a single static file. The standard library
provides everything needed.
* **Bind to `0.0.0.0`** – Ensures the server is reachable from outside
a Docker container (where `127.0.0.1` would not be accessible from
the host).
* **`allow_reuse_address = True`** – Prevents "Address already in use"
errors during quick restart cycles in development.
* **`functools.partial`** – Used to pass the `directory` argument to
`SimpleHTTPRequestHandler` cleanly, avoiding a custom subclass.
9 changes: 9 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
FROM python:3.12-slim

WORKDIR /app

COPY index.html server.py ./

EXPOSE 8000

CMD ["python", "server.py"]
62 changes: 62 additions & 0 deletions RUNNING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Running the Hello World App

## Prerequisites

### With Docker

* [Docker](https://docs.docker.com/get-docker/) (v20+ recommended)
* [Docker Compose](https://docs.docker.com/compose/install/) (v2+)

### Without Docker

* [Python 3](https://www.python.org/downloads/) (3.8 or later)

## Quick Start (Docker)

```bash
# 1. Clone the repository and enter the directory
git clone <repo-url> && cd <repo-directory>

# 2. Build and start the container
docker compose up --build -d

# 3. Open in your browser
open http://localhost:8000 # macOS
# or visit http://localhost:8000 manually
```

## Quick Start (Without Docker)

```bash
# 1. Clone the repository and enter the directory
git clone <repo-url> && cd <repo-directory>

# 2. Start the server
python server.py

# 3. Open http://localhost:8000 in your browser
```

## Stop the App

### Docker

```bash
docker compose down
```

### Without Docker

Press `Ctrl+C` in the terminal where `server.py` is running.

## Running Tests

```bash
python -m pytest tests/ -v
```

## What You Should See

A white page with the text **Hello World** centred on the screen.

> **Note:** No authentication or demo credentials are required.
6 changes: 6 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
services:
web:
build: .
ports:
- "8000:8000"
restart: unless-stopped
22 changes: 22 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello World</title>
<style>
body {
background-color: #ffffff;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
font-family: sans-serif;
}
</style>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
39 changes: 39 additions & 0 deletions server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
"""Lightweight Python HTTP server that serves static files from the current directory.

Uses only the Python standard library. Designed to be run directly or
imported and started programmatically via :func:`run_server`.
"""

from __future__ import annotations

import functools
import http.server
import socketserver
from typing import Optional


def run_server(port: int = 8000, directory: str = ".") -> None:
"""Start an HTTP server serving *directory* on *port*.

The server binds to ``0.0.0.0`` so it is reachable from outside a
Docker container.

Args:
port: TCP port to listen on. Defaults to ``8000``.
directory: Filesystem directory to serve. Defaults to ``"."``.
"""
handler = functools.partial(
http.server.SimpleHTTPRequestHandler,
directory=directory,
)

# Allow quick restart without waiting for TIME_WAIT to expire
socketserver.TCPServer.allow_reuse_address = True

with socketserver.TCPServer(("0.0.0.0", port), handler) as httpd:
print(f"Serving on http://0.0.0.0:{port}")
httpd.serve_forever()


if __name__ == "__main__":
run_server()
Empty file added tests/__init__.py
Empty file.
Loading