diff --git a/.gitignore b/.gitignore
index ed337c9..73c26f4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -39,3 +39,5 @@ cmake-build-debug
# cmake stuff
CMakeLists.txt
+request
+webserv
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..5195c87
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,12 @@
+SRC = main.cpp src/response.cpp
+CMP = clang++ -std=c++98
+FLAGS = -Wall -Wextra -Werror -g3
+NAME = a.out
+all : $(NAME)
+
+$(NAME):
+ $(CMP) $(FLAGS) $(SRC) -o a.out
+
+clean:
+ rm a.out
+re: clean all
\ No newline at end of file
diff --git a/README.md b/README.md
index 87eeac7..d369726 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,86 @@
# webserv
#### Serer Block Configurations
+ - A virtual server is defined by a server directive.
- A server block is a subset of servers’s configuration that defines a virtual server used to handle requests of a defined type.
- - A location block lives within a server block and is used to define how Nginx should handle requests for different resources and URIs for the parent server.
+ -
+ ```
+ server {
+ # Server configuration
+ }
+ ```
+ - It is possible to add multiple server directives into the http context to define multiple virtual servers.
+ ```
+ server {
+ # Server configuration
+ }
+
+ server {
+ # Other Server configuration
+ }
+ ```
+
+ - The server configuration block usually includes a listen directive to specify the IP address and port on which the server listens for requests.
+ ```
+ server {
+ # Server configuration
+ listen 127.0.0.1:8080
+
+ # Or
+ host 127.0.0.1
+ port 8080
+ }
+ ```
+ - If a port is omitted, the standard port is used. Likewise, if an address is omitted, the server listens on all addresses.
+ - If the listen directive is not included at all, the “standard” port is 80/tcp and the “default” port is 8000/tcp, depending on superuser privileges.
+ - If there are several servers that match the IP address and port of the request, the server tests the request’s Host header field against the server_name directives in the server blocks.
+ - If the Host header field does not match a server name, should routes the request to the default server for the port on which the request arrived. The default server is the first one listed in the config file, unless you include the default_server parameter to the listen directive to explicitly designate a server as the default.
+
+ ### Serving Static Content
+
+ An important web server task is serving out files (such as images or static HTML pages). You will implement an example where, depending on the request, files will be served from different local directories: /data/www (which may contain HTML files) and /data/images (containing images). This will require editing of the configuration file and setting up of a server block inside the http block with two location blocks.
+
+ First, create the /data/www directory and put an index.html file with any text content into it and create the /data/images directory and place some images in it.
+
+ Next, open the configuration file. The default configuration file already includes several examples of the server block, mostly commented out. For now comment out all such blocks and start a new server block:
+```
+http {
+ server {
+ }
+}
+```
+Generally, the configuration file may include several server blocks distinguished by ports on which they listen to and by server names. Once nginx decides which server processes a request, it tests the URI specified in the request’s header against the parameters of the location directives defined inside the server block.
+
+Add the following location block to the server block:
+```
+location / {
+ root /data/www;
+}
+```
+This location block specifies the “/” prefix compared with the URI from the request. For matching requests, the URI will be added to the path specified in the root directive, that is, to /data/www, to form the path to the requested file on the local file system. If there are several matching location blocks nginx selects the one with the longest prefix. The location block above provides the shortest prefix, of length one, and so only if all other location blocks fail to provide a match, this block will be used.
+
+Next, add the second location block:
+```
+location /images/ {
+ root /data;
+}
+```
+It will be a match for requests starting with /images/ (location / also matches such requests, but has shorter prefix).
+
+The resulting configuration of the server block should look like this:
+```
+server {
+ location / {
+ root /data/www;
+ }
+
+ location /images/ {
+ root /data;
+ }
+}
+```
+
+This is already a working configuration of a server that listens on the standard port 80 and is accessible on the local machine at http://localhost/. In response to requests with URIs starting with /images/, the server will send files from the /data/images directory. For example, in response to the http://localhost/images/example.png request nginx will send the /data/images/example.png file. If such file does not exist, nginx will send a response indicating the 404 error. Requests with URIs not starting with /images/ will be mapped onto the /data/www directory. For example, in response to the http://localhost/some/example.html request nginx will send the /data/www/some/example.html file.
+
#### How Nginx Decides Which Server Block Will Handle a Request
-
diff --git a/cmake-build-debug/Testing/Temporary/LastTest.log b/cmake-build-debug/Testing/Temporary/LastTest.log
index 17a281c..fcd970b 100644
--- a/cmake-build-debug/Testing/Temporary/LastTest.log
+++ b/cmake-build-debug/Testing/Temporary/LastTest.log
@@ -1,3 +1,3 @@
-Start testing: Nov 15 14:55 +01
+Start testing: Nov 15 16:48 +01
----------------------------------------------------------
-End testing: Nov 15 14:55 +01
+End testing: Nov 15 16:48 +01
diff --git a/error_pages/403.html b/error_pages/403.html
new file mode 100644
index 0000000..c860cb4
--- /dev/null
+++ b/error_pages/403.html
@@ -0,0 +1,15 @@
+
+
+
+ 403 Forbidden
+
+
+
+
+ 403 Forbidden
+
+
+ nginx/1.21.4
+
+
+
\ No newline at end of file
diff --git a/error_pages/404.html b/error_pages/404.html
new file mode 100644
index 0000000..0d9dec6
--- /dev/null
+++ b/error_pages/404.html
@@ -0,0 +1,15 @@
+
+
+
+ 404 Not Found
+
+
+
+
+ 404 Not Found
+
+
+ nginx/1.21.4
+
+
+
\ No newline at end of file
diff --git a/error_pages/405.html b/error_pages/405.html
new file mode 100644
index 0000000..7d04c1d
--- /dev/null
+++ b/error_pages/405.html
@@ -0,0 +1,15 @@
+
+
+
+ 405 Not Allowed
+
+
+
+
+ 405 Not Allowed
+
+
+ nginx/1.21.4
+
+
+
\ No newline at end of file
diff --git a/error_pages/502.html b/error_pages/502.html
new file mode 100644
index 0000000..3b829f9
--- /dev/null
+++ b/error_pages/502.html
@@ -0,0 +1,15 @@
+
+
+
+ 502 Bad Gateway
+
+
+
+
+ 502 Bad Gateway
+
+
+ nginx/1.21.4
+
+
+
\ No newline at end of file
diff --git a/file.html b/file.html
new file mode 100755
index 0000000..e69de29
diff --git a/file.json b/file.json
new file mode 100644
index 0000000..978d70e
--- /dev/null
+++ b/file.json
@@ -0,0 +1 @@
+{"name":"John", "age":30, "car":null}
\ No newline at end of file
diff --git a/fork.cpp b/fork.cpp
new file mode 100644
index 0000000..a762f3c
--- /dev/null
+++ b/fork.cpp
@@ -0,0 +1,129 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+std::vector cgi_meta_var(void)
+{
+ std::vector meta_var;
+ std::string str;
+ /*
+ * SRC = Request (we will get this info from the request headers)
+ * The server MUST set this meta-variable if and only if the request is accompanied by a message body entity.
+ * The CONTENT_LENGTH value must reflect the length of the message-body
+ */
+ str = std::string("CONTENT_LENGHT") + '\n';
+ meta_var.push_back(str.c_str());
+ // _cgi_meta_var += "CONTENT_LENGHT=" + '\n';
+ /*
+ * SRC = Request (we will get this info from the request headers)
+ * The server MUST set this meta-variable if an HTTP Content-Type field is present in the client request header.
+ */
+ str = std::string("CONTENT_TYPE=") + '\n';
+ meta_var.push_back(str.c_str());
+ /*
+ * SRC = Static (hard code it)
+ * It MUST be set to the dialect of CGI being used by the server to communicate with the script. Example: CGI/1.1
+ */
+ str = "GATEWAY_INTERFACE=CGI/1.1\n";
+ meta_var.push_back(str.c_str());
+ /*
+ * SRC = Request (we will get this info from the request headers)
+ * Extra "path" information. It's possible to pass extra info to your script in the URL,
+ * after the filename of the CGI script. For example, calling the
+ * URL http://www.myhost.com/mypath/myscript.cgi/path/info/here will set PATH_INFO to "/path/info/here".
+ * Commonly used for path-like data, but you can use it for anything.
+ */
+ str = std::string("PATH_INFO=") + '\n';
+ meta_var.push_back(str.c_str());
+ /*
+ * SRC = Request/Conf (we will get this info from the request headers but we should parse it as a local uri)
+ * the PATH_TRANSLATED variable is derived by taking the PATH_INFO value, parsing it as a local URI in its own right,
+ * and performing any virtual-to-physical translation appropriate to map it onto the server's document repository structure
+ */
+ str = std::string("PATH_TRANSLATED=") + '\n';
+ meta_var.push_back(str.c_str());
+ /*
+ * SRC = Request
+ * When information is sent using a method of GET, this variable contains the information in a query that follows the "?".
+ * The string is coded in the standard URL format of changing spaces to "+" and encoding special characters with "%xx" hexadecimal encoding.
+ * The CGI program must decode this information.
+ */
+ str = std::string("QUERY_STRING=") + '\n';
+ meta_var.push_back(str.c_str());
+ /*
+ * SRC = Request
+ * Contains the method (as specified with the METHOD attribute in an HTML form) that is
+ * used to send the request. Example: GET
+ */
+ str = std::string("REQUEST_METHOD=GET") + '\n';
+ meta_var.push_back(str.c_str());
+ /*
+ * SRC = Request
+ * The path part of the URL that points to the script being executed.
+ * It should include the leading slash. Example: /cgi-bin/hello.pgm
+ */
+ str = std::string("SCRIPT_NAME=") + '\n';
+ meta_var.push_back(str.c_str());
+ /*
+ * SRC = Conf
+ * Contains the server host name or IP address of the server. Example: 10.9.8.7
+ */
+ str = std::string("SERVER_NAME=") + '\n';
+ meta_var.push_back(str.c_str());
+ /*
+ * Contains the port number to which the client request was sent.
+ */
+ str = std::string("SERVER_PORT=") + '\n';
+ meta_var.push_back(str.c_str());
+ str = "SERVER_PROTOCOL=HTTP/1.1\n";
+ meta_var.push_back(str.c_str());
+ str = "SERVER_SOFTWARE=Webserv\n";
+ meta_var.push_back(str.c_str());
+ meta_var.push_back(NULL);
+ return meta_var;
+}
+
+int main(void)
+{
+ int fd = open("index.php", O_RDONLY);
+ pid_t pid;
+ int pfd[2];
+
+ pipe(pfd);
+ if(!(pid = fork()))
+ {
+ std::vector meta_var = cgi_meta_var();
+ std::vector args;
+ std::string path;
+
+ args.push_back("/Users/mamoussa/Desktop/brew/bin/php-cgi");
+ args.push_back(NULL);
+ path = "/Users/mamoussa/Desktop/brew/bin/php-cgi";
+ close(pfd[0]);
+ dup2(fd, 0);
+ dup2(pfd[1], 1);
+ if (execve(path.c_str(), const_cast(&(*args.begin()))
+ , const_cast(&(*meta_var.begin()))) < 0)
+ {
+ meta_var.~vector();
+ args.~vector();
+ std::cout << strerror(errno) << std::endl;
+ exit(1);
+ }
+ }
+ wait(&pid);
+ close(pfd[1]);
+ std::string ans;
+ char buff[1024];
+ int ret = 1;
+
+ while ((ret = read(pfd[0], buff, 1024)))
+ ans += buff;
+ std::cout << ans << std::endl;
+ return 0;
+}
\ No newline at end of file
diff --git a/hello.html b/hello.html
new file mode 100755
index 0000000..bfd56b7
--- /dev/null
+++ b/hello.html
@@ -0,0 +1,6 @@
+
+
+
+ hello
+
+
\ No newline at end of file
diff --git a/includes/location.hpp b/includes/location.hpp
new file mode 100644
index 0000000..5fc473c
--- /dev/null
+++ b/includes/location.hpp
@@ -0,0 +1,21 @@
+#pragma once
+#include
+#include
+
+class Location
+{
+ public:
+ Location(){}
+ Location(std::string const& path, std::vector const& index, std::vector const& allowed):
+ _path(path), _index(index), _allowed_methods(allowed){}
+ std::string const& getPath(void) const { return _path; }
+ std::vector getIndex(void) const { return _index; }
+ std::vector getAllowedMethods(void) const { return _allowed_methods; }
+ std::string & getAutoIndex(void) { return _autoIndex;}
+ private:
+ std::string _path;
+ std::vector _index;
+ std::vector _allowed_methods;
+ std::string _autoIndex;
+ std::string _cgi_path;
+};
\ No newline at end of file
diff --git a/includes/request.hpp b/includes/request.hpp
index 0aab20d..3161d0b 100644
--- a/includes/request.hpp
+++ b/includes/request.hpp
@@ -10,13 +10,13 @@
#include
#include
+typedef enum transfer_type {
+ CHUNKED,
+ COMPLETED,
+} transfer_type;
class Request {
private:
- typedef enum transfer_type
- {
- CHUNKED, COMPLETED
- } transfer_type;
std::map > _RequestMap;
std::stringstream _req;
diff --git a/includes/response.hpp b/includes/response.hpp
new file mode 100644
index 0000000..f14a781
--- /dev/null
+++ b/includes/response.hpp
@@ -0,0 +1,51 @@
+#pragma once
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+# include