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:
- Implement a WSGI callable that returns valid HTTP responses.
- Parse query strings and POST bodies from
environ. - Set and read cookies for session-like behavior.
- Compose middleware around a base app.
- Run your app using a WSGI server (gunicorn/uwsgi).
- 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
- WSGI Callables
- Must accept
(environ, start_response)and return an iterable of bytes.
- Must accept
- Request Parsing
- Query params:
QUERY_STRINGparsed withparse_qs. - POST body: read
wsgi.inputusingCONTENT_LENGTH.
- Query params:
- Response Construction
- Status string + list of header tuples.
- Body must be bytes, not str.
- Cookies
- Read from
HTTP_COOKIE, set viaSet-Cookieresponse header.
- Read from
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
- Implement
application(environ, start_response). - Support GET and POST requests.
- Parse query strings and POST form data.
- Set a cookie on login and read it on profile.
- 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
- What headers are required for a valid response?
- How will you handle missing query params?
- What cookie format will you use?
- How will you implement a 404 response?
Thinking Exercise
Use curl -v and map each header to a key in environ.
Interview Questions
- What is WSGI and why does it exist?
- How do you parse POST bodies in WSGI?
- Why must WSGI responses be bytes?
- How does middleware work?
- How do cookies work in HTTP?
Hints in Layers
- Hint 1: Print the
environkeys to see what’s available. - Hint 2: Build one route first, then add routing.
- Hint 3: Use
parse_qsfor query and body. - Hint 4: Wrap the app with a logging middleware.
Implementation Phases
Phase 1: Basic Routing (2 days)
- Implement
applicationand 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.