Project 1: WSGI Application from Scratch (The Foundation)

Build a minimal WSGI app that parses HTTP requests, manages cookies, and composes middleware.


Quick Reference

Attribute Value
Difficulty Intermediate
Time Estimate 1 week
Language Python
Prerequisites Python basics, HTTP fundamentals
Key Topics WSGI, environ parsing, headers, cookies, middleware
Output Running WSGI app + demo routes

Learning Objectives

By completing this project, you will:

  1. Implement a WSGI callable that returns valid HTTP responses.
  2. Parse query strings and POST bodies from environ.
  3. Set and read cookies for session-like behavior.
  4. Compose middleware around a base app.
  5. Run your app using a WSGI server (gunicorn/uwsgi).
  6. Explain how Django’s request lifecycle starts at WSGI.

The Core Question You’re Answering

“What is the smallest possible Python web app that still behaves like a real server?”

If you can answer this, you can debug anything between Django and the browser.


Concepts You Must Understand First

Concept Why It Matters Where to Learn
WSGI interface Defines how servers call apps PEP 3333
HTTP request structure You must parse method/path/body HTTP basics
Headers and cookies State and auth rely on headers MDN cookies
Status lines Response format is strict RFC 7230
Middleware How Django stacks behavior Django docs

Key Concepts Deep Dive

  1. WSGI Callables
    • Must accept (environ, start_response) and return an iterable of bytes.
  2. Request Parsing
    • Query params: QUERY_STRING parsed with parse_qs.
    • POST body: read wsgi.input using CONTENT_LENGTH.
  3. Response Construction
    • Status string + list of header tuples.
    • Body must be bytes, not str.
  4. Cookies
    • Read from HTTP_COOKIE, set via Set-Cookie response header.

Theoretical Foundation

The WSGI Contract

Server (gunicorn) -> application(environ, start_response) -> response body

The server provides a request environment dictionary and a callback to send status/headers. Your job is to parse, route, and respond.


Project Specification

What You Will Build

A minimal WSGI app that handles routes /hello, /login, and /profile, supports query params, and uses cookies for session-like flow.

Functional Requirements

  1. Implement application(environ, start_response).
  2. Support GET and POST requests.
  3. Parse query strings and POST form data.
  4. Set a cookie on login and read it on profile.
  5. Add logging middleware.

Non-Functional Requirements

  • Correctness: Proper status and headers.
  • Clarity: Minimal but readable code.
  • Portability: Works on gunicorn.

Example Usage / Output

$ gunicorn app:application
$ curl "http://localhost:8000/hello?name=World"
Hello, World!

Real World Outcome

You can open /hello in a browser, log in with /login, and see a protected /profile page that reads a cookie. Logs show each request path and timing.


Solution Architecture

High-Level Design

Request -> Router -> Handler -> Response
        -> Middleware (logging)

Key Components

Component Responsibility Key Decisions
Router Match path to handler Dict mapping
Parser Extract params parse_qs
Session Cookie read/write Simple token
Middleware Logging Wrapper callable

Implementation Guide

Development Environment Setup

python -m venv web-env
source web-env/bin/activate
pip install gunicorn

Project Structure

project-root/
├── app.py
└── README.md

The Core Question You’re Answering

“How does a raw HTTP request become a response at the lowest level?”

Questions to Guide Your Design

  1. What headers are required for a valid response?
  2. How will you handle missing query params?
  3. What cookie format will you use?
  4. How will you implement a 404 response?

Thinking Exercise

Use curl -v and map each header to a key in environ.

Interview Questions

  1. What is WSGI and why does it exist?
  2. How do you parse POST bodies in WSGI?
  3. Why must WSGI responses be bytes?
  4. How does middleware work?
  5. How do cookies work in HTTP?

Hints in Layers

  • Hint 1: Print the environ keys to see what’s available.
  • Hint 2: Build one route first, then add routing.
  • Hint 3: Use parse_qs for query and body.
  • Hint 4: Wrap the app with a logging middleware.

Implementation Phases

Phase 1: Basic Routing (2 days)

  • Implement application and one route.

Checkpoint: /hello returns 200 OK.

Phase 2: Params and Cookies (2-3 days)

  • Parse query and POST data.
  • Implement cookie-based login.

Checkpoint: /profile works after login.

Phase 3: Middleware + Errors (2 days)

  • Add logging middleware.
  • Add 404/500 responses.

Checkpoint: Logs and error handling work.


Testing Strategy

Category Purpose Examples
Routing Correct handler /hello 200
Parsing Query/POST values name param
Cookies Read/write session cookie

Critical cases:

  • Missing params.
  • Empty POST body.
  • Unknown route returns 404.

Common Pitfalls and Debugging

Pitfall Symptom Solution
Returning str TypeError Encode to bytes
Missing Content-Length Client hangs Set header
Reading body twice Empty body Read once

Extensions and Challenges

  • Add JSON responses.
  • Add static file serving.
  • Add gzip middleware.

Resources

  • PEP 3333: https://peps.python.org/pep-3333/
  • Gunicorn: https://gunicorn.org/
  • HTTP basics: https://developer.mozilla.org/

Self-Assessment Checklist

  • I can explain the WSGI interface.
  • I can parse GET/POST data reliably.
  • I can build middleware around an app.

Submission / Completion Criteria

Minimum Viable Completion

  • WSGI app with basic routing and query parsing.

Full Completion

  • Cookies + middleware + error handling.

Excellence

  • Static file support and gzip compression.

This guide was generated from LEARN_DJANGO_WEB_FRAMEWORKS.md. For the complete learning path, see the parent directory LEARN_DJANGO_WEB_FRAMEWORKS/README.md.