This is a basic HTTP server implementation from scratch made for the CodeCrafters "Build Your Own HTTP Server" challenge.
- System.Net and System.Net.Sockets: Used for creating TCP listeners and handling network streams.
- System.Threading: Used threading and tasks to support multiple, concurrent requests.
- System.Text: Used for encoding and decoding text data.
- System.IO: Used for file operations.
- System.IO.Compression: Used for compressing data streams.
- HTTP Methods: Implemented basic handling for GET and POST requests.
- Headers: Learned how to parse and use HTTP headers.
- Status Codes: Learned some new HTTP status codes like 405 Method Not Allowed.
- Content Encoding: Implemented support for gzip content encoding.
- Asynchronous Programming: Used
async
andawait
for asynchronous IO operations. - LINQ: Used LINQ for string manipulation and collection operations.
- File Handling: Learned how to read from and write to files.
Follow these steps to run the project:
-
Clone the repository:
git clone https://github.com/OmarAshraf-02/HttpServer.git
-
Navigate to the project directory:
cd HttpServer
-
Build the project:
dotnet build
-
Run the server:
dotnet run
The server will start and listen on the specified port. You can send HTTP requests to test its functionality.
To make a GET request, you can use curl
:
curl -v http://localhost:4221/
This will return a 200 Success
response.
curl -v http://localhost:4221/abcdefg
This will return a 404 Not Found
response as it is not defined in the server.
curl -v http://localhost:4221/echo/foo
This will return a 200 Success
response, along with the Content-Type: text/plain
& Content-Length
with the length of your {str}
in the path. It will also append the {str}
to the response body.
curl -v --header "Accept-Encoding: gzip" http://localhost:4221/echo/foo
This will return a 200 Success
response. The raw {str}
will be gzip encoded by the server and then appended to the response body.
If you're using curl
and want to see the response body in the terminal, use the --output -
curl option (however this will be gibberish and may mess up your terminal).
Content-Length
will be set to the length of the gzip encoded data and the Content-Type: text/plain
.
If Accept-Encoding
is set to a comma-separated list of encoding methods, this will be parsed by the server to see if gzip
is one of the options, so a request such as this will also work:
curl -v --header "Accept-Encoding: encoding1, gzip, encoding2" http://localhost:4221/echo/foo
curl -v --header "User-Agent: foobar/1.2.3" http://localhost:4221/user-agent
For this request, the server parses the User-Agent
header and responds with a 200 Success
with Content-Type: text/plain
& Content-Length
set to the length of your User-Agent
header's value. This value will also be appended to the response body.
curl -i http://localhost:4221/files/foo.txt
This request will search for a file with the name filename
in the /data
directory in the project root (not src).
If a file with the same name is found, a 200 Success
response will be returned with Content-Type: application/octet-stream
& Content-Length
set to the size of the file in bytes. The file contents will also be appended to the response body.
If the file is not found, a 404 Not Found
response is returned.
foo.txt
is included in the /data
folder of the repository as an example for testing.
curl -v --data "12345" -H "Content-Type: application/octet-stream" http://localhost:4221/unsupported
Any unsupported post request will return a 404 Not Found
response.
curl -v --data "12345" -H "Content-Type: application/octet-stream" http://localhost:4221/files/foo
If a POST
request is sent to /files/{filename}
, a file with the name filename
will be created in the project's /data
directory. This file's contents will consist of the contents of the request body (In the above case = 12345). A 201 Created
response will then be returned by the server.