[WORK IN PROGRESS]
This project is about creating an HTTP server. Nginx serves as a reference.
- Take a configuration file as argument, or use a default path.
- Return a proper HTTP response status codes
- Work with GET, POST and DELETE methods
- Have CGI and ability to upload files
- Be able to listen to multiple prots and and launch several servers at the same time
- Everything in C++98
- execve, du, dup2, pipe, fork
- strerror, gai_strerror, errno
- htons, htonl, ntohs, ntohl
- select, poll, epoll, kqueue
- socket, bind, connect, accept, listen
- getaddrinfo, freeaddrinfo, setsockopt, getsockname, getprotobyname
- recv, send
- fcntl, all FD macros (like FD_SET, FD_CLR, FD_ISSET)
- make - to compile the executable file
- execute it with ./webserv to launch it with a default config
- or ./webserv [path to a config] to lauch with a config of your choice
- a server block in the config should contain port, host name, path for error pages and locations
- Read config, save parameters from it, create and prepare listening sockets, launch main loop. Inside it save every request, parse it to get all the required parameters, create a proper response and send it back. The loop keeps running until timeout
- Config parser
- Main loop (with socket creator, accepter, handler and responder)
- Request parser
- Responder
- Website pages
- CGI
- Unit-tests
- We decided to create several classes for the config parser: one for server blocks, one for locations, general one (that contains all other classes)
- We adapted the IBM's implementation for our main loop
- Loop starts with SELECT(), then it checks whether a socket is in the FD_SET and checks its type. If it is a listening socket, the server tries to accept the incoming connections. Otherwise it performs I/O operations
- Before the main loop we create listening sockets and add them to the FD_SET
- We mapped every listening socket to the corresponding server block in order to track locations properly
- In SELECT() we used only one FD_SET for the sake of simplicity
- We split header and body, then save parameters from the starting line. All other header's parameters are mapped
- Then we do error checks (mainly method and target) and create a proper path to the targeted page
- We used Python to create unit tests
- 1st attempt: 100 %
config - contains config files inc - headers src - cpp files unit-tests - some basic Python tests website - content for the website
- Article on how to create a basic HTTP server in C. Contains some useful links, including ones to RFC
- RFC 7230, where you can find information about request and response format
- Video on how to build a basic HTTP server in C++
- Video about SELECT()
- Implementation of the main loop by IBM. Really good one, need just adapt it a bit for multiple ports and servers