HTTP-C is a lightweight, modular HTTP/1.1 server implemented in C. It's designed to demonstrate fundamental concepts of socket programming, HTTP request parsing, response generation, and basic server architecture in a Unix-like environment.
- Features
- Project Structure
- Core Components
- Prerequisites
- Building the Server
- Running the Server
- Usage Examples (curl)
- Browser Output Examples
- Makefile Details
- License
- HTTP/1.1 GET Request Handling: Primarily processes
GETrequests. - Response Codes Supported:
200 OK: For successful requests to the root path (/) and the dynamic echo endpoint (/echo/<message>).400 Bad Request: Sent if the incoming HTTP request is malformed or cannot be parsed.404 Not Found: Returned forGETrequests to routes not explicitly handled by the server (i.e., anything other than/or/echo/).405 Method Not Allowed: Sent for any HTTP method other thanGET. Includes anAllow: GETheader.500 Internal Server Error: Generated if a server-side error occurs, such as memory allocation failure during response construction.
- Echo Endpoint (
/echo/<message>): Dynamically generates a200 OKresponse, echoing back the<message>provided in the path. This demonstrates basic dynamic content generation. - Graceful Shutdown: Implements a
SIGINT(Ctrl+C) signal handler for clean server termination, ensuring resources are properly released. - Structured Request Parsing: Parses incoming HTTP request lines into a structured format (method, route, HTTP version, and arguments).
- Modular Design: Code is organized into logical modules (headers and source files) for improved readability, maintainability, and separation of concerns.
- Out-of-Source Builds: Compiled object files and the final executable are placed in a separate
build/directory, keeping the source tree clean.
The project is organized into distinct directories for source code, include files, and build artifacts:
http-c/
├── src/ # Contains all C source (.c) files
│ ├── main.c
│ ├── http_types.c
│ ├── http_parser.c
│ ├── http_response.c
│ ├── server.c
│ └── signal_handler.c
├── include/ # Contains all custom header (.h) files
│ ├── config.h
│ ├── http_types.h
│ ├── http_parser.h
│ ├── http_response.h
│ ├── server.h
│ └── signal_handler.h
├── build/ # Generated directory for compiled object files and the final executable
├── Makefile # Build instructions for the project
├── assets/ # (Optional) For images and other assets
│ └── browser_root_output.png
│ └── browser_echo_output.png
└── README.md # This file: Project documentation
src/main.c: The main application entry point. Orchestrates the server setup, main event loop (accepting connections), and initiates graceful shutdown.include/config.h: Defines global configuration constants (e.g.,PORT,BUFFER_SIZE).http_types.c/include/http_types.h: DefinesClientRequestandServerResponsestructures for representing HTTP data, along with helper functions to free their allocated memory.http_parser.c/include/http_parser.h: Encapsulates the logic for parsing raw HTTP client request lines into theClientRequeststructure.http_response.c/include/http_response.h: Handles initialization of standard server responses (e.g., 200 OK, 404 Not Found) and constructs dynamic responses, such as for the/echo/endpoint.server.c/include/server.h: Contains the core networking logic:setup_server_socket(): Initializes and binds the listening socket.handle_accept()(if implemented as per last suggestion, otherwiseaccept()is inmain.c): Manages accepting new client connections.handle_client(): Processes an individual client's request after connection.
signal_handler.c/include/signal_handler.h: Manages POSIX signal handling (specificallySIGINTfor graceful shutdown) and the globalkeep_runningflag.
To build and run this server, you will need:
- A C compiler supporting C11 (e.g.,
gcc). - The
makeutility. - A POSIX-compliant environment (Linux, macOS, or a Unix-like environment on Windows).
- For Windows users: It is highly recommended to use Windows Subsystem for Linux (WSL) or a similar environment like MSYS2 with a MinGW-w64 toolchain. The server uses POSIX-specific networking APIs and headers (e.g.,
<netinet/in.h>,<sys/socket.h>,<unistd.h>) not natively available in standard Windows development environments.
- For Windows users: It is highly recommended to use Windows Subsystem for Linux (WSL) or a similar environment like MSYS2 with a MinGW-w64 toolchain. The server uses POSIX-specific networking APIs and headers (e.g.,
-
Clone or download the project files.
-
Navigate to the root project directory (
http-c/) containing theMakefile. -
Run
make:make
This command will:
- Create a
build/directory if it doesn't exist. - Compile all source files from the
src/directory into object files (.o) within thebuild/directory. - Link these object files to create the final executable
http_server, also placed in thebuild/directory.
- Create a
-
For a debug build (with debugging symbols and a
DEBUGmacro defined):make debug
After a successful build, the executable will be located in the build/ directory.
-
From the root project directory (
http-c/), run:./build/http_server
Alternatively, you can use the
make runtarget:make run
This will build the server (if necessary) and then execute it.
-
The server will start listening on port
42069(as defined ininclude/config.h). You will see log messages in your terminal:Logs from the program will appear here. Waiting for a client to connect on port 42069... Press Ctrl+C to stop the server. -
To stop the server, press
Ctrl+Cin the terminal where it's running. This will trigger theSIGINTsignal handler for a graceful shutdown.
You can interact with the server using a web browser or a command-line tool like curl.
-
Accessing the Root Path (
/):curl -v http://localhost:42069/
Server Log:
200 OK Response Sent (root).curlOutput:HTTP/1.1 200 OK -
Using the Echo Endpoint (
/echo/<message>):curl -v http://localhost:42069/echo/hello_from_C
Server Log:
Echo Response Sent.curlOutput (including headers):HTTP/1.1 200 OK Content-Type: text/plain Content-Length: 14 hello_from_C
-
Accessing a Non-Existent Path:
curl -v http://localhost:42069/thisdoesnotexist
Server Log:
404 Not Found Response Sent.curlOutput:HTTP/1.1 404 Not Found -
Using an Unsupported HTTP Method (e.g., POST):
curl -vX POST http://localhost:42069/
Server Log:
405 Method Not Allowed sent.curlOutput (including headers):HTTP/1.1 405 Method Not Allowed Allow: GET
Here's how the server responses might look in a web browser. (Note: Browsers may render plain text differently. These screenshots are illustrative.)
-
Root Path (
http://localhost:42069/): The browser will typically display the raw status line if no HTML content is provided.HTTP/1.1 200 OK -
Echo Endpoint (
http://localhost:42069/echo/HTTP-C_Says_Hello_!!!): The browser will display the echoed text.HTTP-C_Says_Hello_!!!
An Image of the output body with text "HTTP-CSays_Hello!!!".
The Makefile automates the build process and is configured for the project's structure:
CFLAGS: Includes essential compiler flags:-Wall -Wextra -pedantic -std=c11: For strict warnings and C11 standard compliance.-D_POSIX_C_SOURCE=200809L: To enable POSIX.1-2008 features.-Iinclude: Instructs the compiler to search for header files in theinclude/directory.
SRC_DIR,INC_DIR,BUILD_DIR: Variables defining the source, include, and build directories.SRC = $(wildcard $(SRC_DIR)/*.c): Automatically finds all.cfiles in thesrc/directory.OBJ = $(patsubst $(SRC_DIR)/%.c,$(BUILD_DIR)/%.o,$(SRC)): Generates object file paths, placing them in thebuild/directory (e.g.,src/main.ccompiles tobuild/main.o).- Targets:
all: Default target; builds thehttp_serverexecutable inbuild/.$(BUILD_DIR)/$(TARGET): Rule for linking object files into the final executable.$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c: Pattern rule for compiling.cfiles fromsrc/into.ofiles inbuild/. Ensures thebuild/directory exists.clean: Removes the entirebuild/directory, cleaning all compiled artifacts.debug: Builds the project with debugging flags (-g -DDEBUG).run: Builds (if necessary) and runs the server.
This project is open source and available under the MIT License. You are free to use, modify, and distribute it.
