Project 10: HTTP Server

Build a minimal HTTP/1.1 server that serves static files and handles basic requests.

Quick Reference

Attribute Value
Difficulty Advanced
Time Estimate 2-3 weeks
Language C
Prerequisites Sockets, I/O, parsing
Key Topics TCP, HTTP, concurrency basics

1. Learning Objectives

By completing this project, you will:

  1. Build a TCP server that accepts connections.
  2. Parse HTTP request lines and headers.
  3. Serve files with correct status codes.
  4. Implement basic logging and error handling.

2. Theoretical Foundation

2.1 Core Concepts

  • TCP sockets: Accept and handle client connections.
  • HTTP protocol: Request line, headers, body.
  • Status codes: 200, 404, 500 indicate response state.

2.2 Why This Matters

HTTP servers are a classic systems programming project. It teaches networking, parsing, and I/O efficiency in one integrated system.

2.3 Historical Context / Background

HTTP/1.1 remains a dominant protocol for web services. Implementing it shows how a text-based protocol maps to sockets.

2.4 Common Misconceptions

  • “HTTP is just text”: It is text over a stream that can be partial.
  • “One read gets the whole request”: It often does not.

3. Project Specification

3.1 What You Will Build

A server that:

  • Listens on a port
  • Handles GET /path requests
  • Serves static files from a document root
  • Returns 404 on missing files

3.2 Functional Requirements

  1. Parse request line and headers.
  2. Map URL paths to filesystem paths safely.
  3. Send correct HTTP response headers.
  4. Serve file contents with proper length.

3.3 Non-Functional Requirements

  • Security: Prevent path traversal (..).
  • Reliability: Handle malformed requests gracefully.
  • Performance: Stream file output without loading whole file.

3.4 Example Usage / Output

$ ./httpd 8080 ./www
[listen] 0.0.0.0:8080
[request] GET /index.html
[response] 200 512 bytes

3.5 Real World Outcome

You can open a browser at http://localhost:8080/ and see your static HTML served by your C server. Requests and responses are visible in your logs.


4. Solution Architecture

4.1 High-Level Design

accept -> read request -> parse -> open file -> respond

4.2 Key Components

Component Responsibility Key Decisions
Listener Accept sockets socket/bind/listen
Parser Extract method/path Basic HTTP/1.1
File server Read and send file Use sendfile or read/write
Logger Log request/response Simple stderr logging

4.3 Data Structures

typedef struct {
    char method[8];
    char path[256];
    char version[16];
} HttpRequest;

4.4 Algorithm Overview

Key Algorithm: Request handling

  1. Read from socket until \r\n\r\n.
  2. Parse request line and headers.
  3. Map path to file; reject ...
  4. Send headers and file content.

Complexity Analysis:

  • Time: O(n) per request
  • Space: O(1) streaming

5. Implementation Guide

5.1 Development Environment Setup

cc -Wall -Wextra -O2 -g -o httpd httpd.c

5.2 Project Structure

httpd/
├── src/
│   └── httpd.c
├── tests/
│   └── test_httpd.sh
└── README.md

5.3 The Core Question You’re Answering

“How does an HTTP request become a file response over a TCP stream?”

5.4 Concepts You Must Understand First

Stop and research these before coding:

  1. Sockets
    • What is a listening socket vs client socket?
  2. HTTP framing
    • How do you know where headers end?
  3. Path safety
    • How do you prevent ../ traversal?

5.5 Questions to Guide Your Design

Before implementing, think through these:

  1. Will you handle keep-alive or close after response?
  2. How will you set MIME types?
  3. How will you handle large files?

5.6 Thinking Exercise

Partial Reads

If the request line arrives in two TCP packets, how does your parser handle it?

5.7 The Interview Questions They’ll Ask

Prepare to answer these:

  1. “How do you implement a TCP server?”
  2. “How do you parse HTTP requests safely?”
  3. “How do you prevent directory traversal?”

5.8 Hints in Layers

Hint 1: Serve only one file Start with a fixed response.

Hint 2: Parse request line Handle GET /path HTTP/1.1.

Hint 3: Stream file Use a buffer loop to send file content.

5.9 Books That Will Help

Topic Book Chapter
Sockets “UNIX Network Programming” Ch. 4-6
HTTP basics “HTTP: The Definitive Guide” Ch. 1-3

5.10 Implementation Phases

Phase 1: Foundation (4-6 days)

Goals:

  • Basic TCP server

Tasks:

  1. Accept a connection.
  2. Read and print request.

Checkpoint: Server receives requests.

Phase 2: Core Functionality (5-7 days)

Goals:

  • Parse and serve files

Tasks:

  1. Parse request line.
  2. Map path and send file.

Checkpoint: Browser loads static file.

Phase 3: Polish & Edge Cases (4-6 days)

Goals:

  • Errors and security

Tasks:

  1. Return 404/400.
  2. Prevent traversal and handle large files.

Checkpoint: Invalid requests return errors.

5.11 Key Implementation Decisions

Decision Options Recommendation Rationale
Concurrency Single-threaded vs threaded Single-threaded Simpler for learning
File send read/write vs sendfile read/write Portable baseline

6. Testing Strategy

6.1 Test Categories

Category Purpose Examples
Unit Tests Parser logic Request line parsing
Integration Tests HTTP responses curl requests
Security Tests Path traversal /../etc/passwd

6.2 Critical Test Cases

  1. GET existing file: 200 response.
  2. GET missing file: 404 response.
  3. Bad request: 400 response.

6.3 Test Data

www/index.html
www/style.css

7. Common Pitfalls & Debugging

7.1 Frequent Mistakes

Pitfall Symptom Solution
Partial reads Truncated headers Read until \r\n\r\n
Path traversal Security hole Normalize path
Missing Content-Length Browser hangs Include correct header

7.2 Debugging Strategies

  • Use curl -v to inspect responses.
  • Log request parsing results.

7.3 Performance Traps

Reading one byte at a time is slow. Use a buffer of 4 KB or more.


8. Extensions & Challenges

8.1 Beginner Extensions

  • Add directory index listing.
  • Add MIME type detection.

8.2 Intermediate Extensions

  • Support keep-alive connections.
  • Add simple thread pool.

8.3 Advanced Extensions

  • Implement HTTP/1.1 chunked responses.
  • Add TLS termination (OpenSSL).

9. Real-World Connections

9.1 Industry Applications

  • Web servers: nginx, Apache use the same basics.
  • Embedded: Minimal HTTP servers for devices.
  • lighttpd: Small-footprint server.

9.3 Interview Relevance

Networking and protocol parsing are common in systems interviews.


10. Resources

10.1 Essential Reading

  • “UNIX Network Programming” - Ch. 4-6
  • “HTTP: The Definitive Guide” - Ch. 1-3

10.2 Video Resources

  • Socket programming lectures

10.3 Tools & Documentation

  • man 2 socket, man 2 bind, man 2 listen
  • Unix Shell: Networking commands and exec behavior.
  • Database Engine: Use HTTP for simple APIs.

11. Self-Assessment Checklist

11.1 Understanding

  • I can explain socket lifecycle.
  • I can parse HTTP request lines.
  • I can handle partial reads.

11.2 Implementation

  • Server responds to GET requests.
  • Correct status codes are returned.
  • Path traversal is blocked.

11.3 Growth

  • I can add concurrency.
  • I can explain this project in an interview.

12. Submission / Completion Criteria

Minimum Viable Completion:

  • Serves one static file.

Full Completion:

  • Serves arbitrary files under document root.

Excellence (Going Above & Beyond):

  • Keep-alive and chunked responses.

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