diff --git a/DockerfileDevEnv b/DockerfileDevEnv index f604d55..4f29f26 100644 --- a/DockerfileDevEnv +++ b/DockerfileDevEnv @@ -2,7 +2,7 @@ FROM debian:bullseye-slim RUN apt-get update RUN apt-get install -y curl RUN curl -fsSL https://deb.nodesource.com/setup_20.x -o nodesource_setup.sh && bash nodesource_setup.sh -RUN apt-get install -y make clang python3 php-cgi libpthread-stubs0-dev nodejs +RUN apt-get install -y make clang python3 php-cgi libpthread-stubs0-dev nodejs valgrind RUN mkdir -p /var/www/html diff --git a/Makefile b/Makefile index 15925d4..b53d3f4 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # By: agaley +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2023/12/15 15:51:13 by agaley #+# #+# # -# Updated: 2024/06/21 16:36:27 by agaley ### ########lyon.fr # +# Updated: 2024/06/25 00:40:40 by agaley ### ########lyon.fr # # # # **************************************************************************** # @@ -14,7 +14,7 @@ NAME = webserv CXX = c++ CXXFLAGS = -Wall -Wextra -Werror -MMD -std=c++98 -DEBUGFLAGS = -g3 -fsanitize=address +DEBUGFLAGS = -g3 SRC_DIR = src OBJ_DIR = obj @@ -30,9 +30,9 @@ export NGINX_PORT_1 ?= 8000 export NGINX_PORT_2 ?= 8001 SRC = $(SRC_DIR)/Server.cpp \ - $(SRC_DIR)/ConfigManager.cpp $(SRC_DIR)/ConfigParser.cpp \ + $(SRC_DIR)/Config.cpp $(SRC_DIR)/ConfigManager.cpp $(SRC_DIR)/ConfigParser.cpp \ $(SRC_DIR)/FileManager.cpp \ - $(SRC_DIR)/ConnectionHandler.cpp \ + $(SRC_DIR)/ConnectionHandler.cpp $(SRC_DIR)/CacheHandler.cpp \ $(SRC_DIR)/Worker.cpp \ $(SRC_DIR)/HTTPRequest.cpp $(SRC_DIR)/HTTPResponse.cpp $(SRC_DIR)/URI.cpp \ $(SRC_DIR)/CGIHandler.cpp $(SRC_DIR)/FileHandler.cpp \ @@ -59,7 +59,7 @@ $(OBJ_DIR)/%.o: %.cpp $(CXX) $(CXXFLAGS) -c $< -o $@ debug: $(DEBUG_OBJ) - $(CXX) $(CXXFLAGS) $(DEBUGFLAGS) $(DEBUG_OBJ) -o $(NAME) + $(CXX) $(CXXFLAGS) $(DEBUGFLAGS) $(DEBUG_OBJ) -lpthread -o $(NAME) $(DEBUG_OBJ_DIR)/%.o: %.cpp @mkdir -p $(DEBUG_OBJ_DIR) @@ -67,6 +67,9 @@ $(DEBUG_OBJ_DIR)/%.o: %.cpp run: daemon $(MAKE) wait-for-healthy + docker compose exec -it webserv make + docker compose exec -it webserv bash -c "kill 1" + sleep 1 @make logs daemon: @@ -78,13 +81,18 @@ watch: inotifywait -qre close_write /app/src; \ done - dev: export BUILD_TYPE=debug docker compose up --build -d webserv-dev docker compose exec -it webserv-dev make debug docker compose exec -it webserv-dev bash -c "./webserv" +valgrind: + export BUILD_TYPE=debug + docker compose up --build -d webserv-dev + docker compose exec -it webserv-dev make debug + docker compose exec -it webserv-dev bash -c "ulimit -n 1024 && valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes ./webserv" + logs: docker compose logs -f diff --git a/NXtest_conf.conf b/NXtest_conf.conf new file mode 100644 index 0000000..97a738b --- /dev/null +++ b/NXtest_conf.conf @@ -0,0 +1,34 @@ +server { + listen 8080; + server_name test.local; + + root /var/www/YoupiBanane; + index index.html; + # cgi on; + + location / { + # autoindex on; + limit_except GET { deny all; } + } + + location /put_test/ { + limit_except PUT { deny all; } + } + + # location ~ \.bla$ { + # limit_except POST { deny all; } + # include /etc/nginx/fastcgi_params; + # fastcgi_pass unix:/var/run/cgi_test.sock; + # } + + location /post_body { + limit_except POST { deny all; } + client_max_body_size 100; + } + + location /directory/ { + limit_except GET { deny all; } + autoindex on; + index youpi.bad_extension; + } +} diff --git a/benchmark b/benchmark new file mode 100644 index 0000000..b2d4305 --- /dev/null +++ b/benchmark @@ -0,0 +1,74 @@ +no loadbalancing: +Lifting the server siege... +Transactions: 106412 hits +Availability: 100.00 % +Elapsed time: 29.09 secs +Data transferred: 70.53 MB +Response time: 0.01 secs +Transaction rate: 3658.03 trans/sec +Throughput: 2.42 MB/sec +Concurrency: 24.81 +Successful transactions: 106413 +Failed transactions: 0 +Longest transaction: 0.03 +Shortest transaction: 0.00 + + +with loadbalancing (algo 1) +Lifting the server siege... +Transactions: 143922 hits +Availability: 100.00 % +Elapsed time: 29.32 secs +Data transferred: 95.39 MB +Response time: 0.01 secs +Transaction rate: 4908.66 trans/sec +Throughput: 3.25 MB/sec +Concurrency: 24.69 +Successful transactions: 143922 +Failed transactions: 0 +Longest transaction: 0.05 +Shortest transaction: 0.00 + +with loadbalancing (algo 2) +Lifting the server siege... +Transactions: 231742 hits +Availability: 100.00 % +Elapsed time: 29.67 secs +Data transferred: 153.60 MB +Response time: 0.00 secs +Transaction rate: 7810.65 trans/sec +Throughput: 5.18 MB/sec +Concurrency: 24.77 +Successful transactions: 231742 +Failed transactions: 0 +Longest transaction: 0.06 +Shortest transaction: 0.00 +-------------------------------------- +Lifting the server siege... +Transactions: 111982 hits +Availability: 100.00 % +Elapsed time: 17.79 secs +Data transferred: 74.22 MB +Response time: 0.00 secs +Transaction rate: 6294.66 trans/sec +Throughput: 4.17 MB/sec +Concurrency: 24.57 +Successful transactions: 111983 +Failed transactions: 0 +Longest transaction: 0.03 +Shortest transaction: 0.00 + +nginx: +Lifting the server siege... +Transactions: 458431 hits +Availability: 100.00 % +Elapsed time: 26.94 secs +Data transferred: 303.85 MB +Response time: 0.00 secs +Transaction rate: 17016.74 trans/sec +Throughput: 11.28 MB/sec +Concurrency: 22.63 +Successful transactions: 458437 +Failed transactions: 0 +Longest transaction: 0.09 +Shortest transaction: 0.00 diff --git a/check_workers.py b/check_workers.py new file mode 100644 index 0000000..b034ec8 --- /dev/null +++ b/check_workers.py @@ -0,0 +1,16 @@ +# Liste des IDs des workers qui ont démarré +started_workers = [ + 1209762, 1209771, 1209764, 1209770, 1209766, 1209769, 1209767, 1209765, + 1209772, 1209768, 1209763, 1209773, 1209774, 1209775, 1209776, 1209777, + 1209778, 1209779, 1209780, 1209781 +] + +# Liste des IDs des workers qui ont terminé +finished_workers = [ + 1209772, 1209771, 1209764, 1209777, 1209769, 1209767, 1209762, 1209765, + 1209766, 1209781, 1209773, 1209776, 1209779, 1209763, 1209774, 1209780, + 1209775, 1209778, 1209770 +] +not_finished_workers = set(started_workers) - set(finished_workers) + +print("Workers qui n'ont pas terminé:", not_finished_workers) diff --git a/default.conf b/default.conf index 7aa0752..23499ab 100644 --- a/default.conf +++ b/default.conf @@ -27,6 +27,7 @@ server { } location /cgi/ { + autoindex on; cgi on; limit_except GET POST { deny all; } } diff --git a/local.conf b/local.conf new file mode 100644 index 0000000..e9897ac --- /dev/null +++ b/local.conf @@ -0,0 +1,79 @@ +# NGINX Compatible conf (no cgi or upload) +worker_processes auto; + +server { + listen 8080; + server_name example.co example.fr; + + # Default error pages + # error_page 403 /errors/403.html; + # error_page 500 /errors/500.html; + error_page 404 /errors/404_main.html; + + # Client body size limit (in bytes) + client_max_body_size 1048576; # 1MB + + # root /var/www/html; # Root directory for the server + ; root /home/mchenava/webserv/site; + root /mnt/e/webserv/site; + autoindex on; + # index index.html; + + # Routes configuration + location / { + autoindex on; + index i-index.html; # Default file if request is a directory + limit_except GET POST { deny all; } # Allowed HTTP methods + client_max_body_size 123; + } + + location /dir/ { + error_page 404 /errors/404_api.html; + limit_except GET POST { deny all; } # Allowed HTTP methods + } + + location /site/ { + limit_except GET POST { deny all; } # Allowed HTTP methods + } + + # location /upload/ { + # limit_except POST { deny all; } # Allowed HTTP methods + # accept_upload on; + # } + + location /cgi/ { + cgi on; + limit_except GET POST { deny all; } # Allowed HTTP methods + } + + location /cgi/off/ { + cgi off; + limit_except GET POST { deny all; } # Allowed HTTP methods + } + + location /redirect/ { + return 301 http://anotherdomain.com; + return 200 blabla; # Should be ignored + limit_except GET { deny all; } # Allowed HTTP methods + } +} + +# Additional server instance (example of multiple server configurations) +server { + listen 8081; + server_name another.local; + + # Default error pages + error_page 404 /errors/404.html; + error_page 500 /errors/500.html; + + # Client body size limit (in bytes) + client_max_body_size 2048000; # 2MB + + location /files/ { + root /var/www/files; + index index.html; + limit_except GET POST { deny all; } + autoindex off; + } +} diff --git a/site/long.html b/site/long.html new file mode 100644 index 0000000..f14cee7 --- /dev/null +++ b/site/long.html @@ -0,0 +1,6448 @@ + + + + Welcome to example fr! + + + + +

Welcome to miniNgin!

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+

+ If you see this page, the miniNgin web server is successfully installed + and working. Further configuration is required. +

+ +

+ For online documentation and support please refer to + miniNgin. +

+ +

Thank you for using miniNgin.

+ +

End.

+ + diff --git a/src/CacheHandler.cpp b/src/CacheHandler.cpp new file mode 100644 index 0000000..ae15e39 --- /dev/null +++ b/src/CacheHandler.cpp @@ -0,0 +1,92 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* CacheHandler.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agaley +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/24 23:54:38 by agaley #+# #+# */ +/* Updated: 2024/06/25 03:14:43 by agaley ### ########lyon.fr */ +/* */ +/* ************************************************************************** */ + +#include "CacheHandler.hpp" + +const time_t CacheHandler::MAX_AGE = 3600; +CacheHandler* CacheHandler::_instance = NULL; + +CacheHandler& CacheHandler::getInstance() { + if (_instance == NULL) { + _instance = new CacheHandler(); + } + return *_instance; +} + +void CacheHandler::deleteInstance() { + if (_instance != NULL) { + delete _instance; + _instance = NULL; + } +} + +CacheHandler::CacheHandler() : _maxAge(MAX_AGE) { + pthread_mutex_init(&_mutex, NULL); +} + +CacheHandler::~CacheHandler() { + for (std::map >::iterator it = + _cache.begin(); + it != _cache.end(); ++it) { + delete it->second.first; + } + _cache.clear(); + pthread_mutex_destroy(&_mutex); +} + +HTTPResponse* CacheHandler::getResponse(const HTTPRequest& request) { + pthread_mutex_lock(&_mutex); + std::map >::const_iterator it = + _cache.find(_generateKey(request)); + if (it != _cache.end()) { + if (it->second.second + _maxAge > time(NULL)) { // Check cache freshness + HTTPResponse* response = new HTTPResponse(*(it->second.first)); + pthread_mutex_unlock(&_mutex); + return response; + } else { + delete it->second.first; // Response + _cache.erase(it->first); // + } + } + pthread_mutex_unlock(&_mutex); + return NULL; +} + +void CacheHandler::storeResponse(const HTTPRequest& request, + const HTTPResponse& response) { + std::string key = _generateKey(request); + pthread_mutex_lock(&_mutex); + if (_cache.find(key) == _cache.end()) + _cache[key] = std::make_pair(new HTTPResponse(response), time(NULL)); + pthread_mutex_unlock(&_mutex); +} + +std::string CacheHandler::_generateKey(const HTTPRequest& request) const { + std::ostringstream oss; + oss << _hash(request.getRawRequest()); + return oss.str(); +} + +unsigned long CacheHandler::_hash(const std::string& str) const { + // FNV-1a Hash Algorithm + const unsigned long FNV_prime = 16777619; + const unsigned long offset_basis = 2166136261U; + unsigned long hash = offset_basis; + const char* cstr = str.c_str(); + + while (*cstr) { + hash ^= static_cast(*cstr++); + hash *= FNV_prime; + } + + return hash; +} diff --git a/src/CacheHandler.hpp b/src/CacheHandler.hpp new file mode 100644 index 0000000..38c0367 --- /dev/null +++ b/src/CacheHandler.hpp @@ -0,0 +1,45 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* CacheHandler.hpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agaley +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/24 23:54:58 by agaley #+# #+# */ +/* Updated: 2024/06/25 03:12:49 by agaley ### ########lyon.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef CACHEHANDLER_HPP +#define CACHEHANDLER_HPP + +#include +#include + +#include "HTTPRequest.hpp" +#include "HTTPResponse.hpp" + +class CacheHandler { + public: + static const time_t MAX_AGE; + + static CacheHandler& getInstance(); + static void deleteInstance(); + + void storeResponse(const HTTPRequest& request, const HTTPResponse& response); + HTTPResponse* getResponse(const HTTPRequest& request); + + private: + CacheHandler(); + ~CacheHandler(); + + static CacheHandler* _instance; + std::map > _cache; + time_t _maxAge; + + std::string _generateKey(const HTTPRequest& request) const; + unsigned long _hash(const std::string& str) const; + mutable pthread_mutex_t _mutex; +}; + +#endif diff --git a/src/Common.cpp b/src/Common.cpp index 665707b..18089f1 100644 --- a/src/Common.cpp +++ b/src/Common.cpp @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* Common.cpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: agaley +#+ +:+ +#+ */ +/* By: mchenava +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/24 11:06:33 by mchenava #+# #+# */ -/* Updated: 2024/06/17 19:39:18 by agaley ### ########lyon.fr */ +/* Updated: 2024/06/24 13:18:45 by mchenava ### ########.fr */ /* */ /* ************************************************************************** */ @@ -34,7 +34,7 @@ int set_non_blocking(int sockfd) { } void signalHandler(int signum) { - Logger::getInstance().info("Signal received: " + Utils::to_string(signum)); + Logger::getInstance().info("Signal received: " + Utils::to_string(signum) + "getting server instance"); Server::getInstance().stop(signum); } @@ -48,3 +48,4 @@ std::string generateSessionId(void) { } return sessionId; } + diff --git a/src/Common.hpp b/src/Common.hpp index 76e49c1..e9a2a3f 100644 --- a/src/Common.hpp +++ b/src/Common.hpp @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* Common.hpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: agaley +#+ +:+ +#+ */ +/* By: mchenava < mchenava@student.42lyon.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/24 11:09:02 by mchenava #+# #+# */ -/* Updated: 2024/06/17 19:44:02 by agaley ### ########lyon.fr */ +/* Updated: 2024/06/21 11:56:02 by mchenava ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,9 +15,12 @@ #include #include +#include "Config.hpp" int set_non_blocking(int sockfd); void signalHandler(int signum); std::string generateSessionId(void); + + #endif diff --git a/src/Config.cpp b/src/Config.cpp new file mode 100644 index 0000000..602d12d --- /dev/null +++ b/src/Config.cpp @@ -0,0 +1,87 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* Config.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: agaley +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/06/24 18:58:00 by agaley #+# #+# */ +/* Updated: 2024/06/24 19:21:02 by agaley ### ########lyon.fr */ +/* */ +/* ************************************************************************** */ + +#include "Config.hpp" + +LocationConfig::LocationConfig() { + client_max_body_size = 1000; + upload = false; + cgi = false; + autoindex = false; +} + +LocationConfig::~LocationConfig() { + error_pages.clear(); + allowed_methods.clear(); +} + +ListenConfig::ListenConfig() { + port = 80; + default_server = false; + backlog = 2048; + rcvbuf = 2048; + sndbuf = 2048; + ipv6only = false; +} + +bool ListenConfig::operator<(const ListenConfig& other) const { + if (address < other.address) + return true; + if (address > other.address) + return false; + if (port < other.port) + return true; + if (port > other.port) + return false; + if (default_server < other.default_server) + return true; + if (default_server > other.default_server) + return false; + if (rcvbuf < other.rcvbuf) + return true; + if (rcvbuf > other.rcvbuf) + return false; + if (sndbuf < other.sndbuf) + return true; + if (sndbuf > other.sndbuf) + return false; + return ipv6only < other.ipv6only; +} + +bool ListenConfig::operator==(const ListenConfig& other) const { + return address == other.address && port == other.port && + default_server == other.default_server && backlog == other.backlog && + rcvbuf == other.rcvbuf && sndbuf == other.sndbuf && + ipv6only == other.ipv6only; +} + +ServerConfig::ServerConfig() { + client_max_body_size = 1000; + upload = false; + cgi = false; + autoindex = false; +} + +ServerConfig::~ServerConfig() { + error_pages.clear(); + locations.clear(); +} + +Config::Config() { + worker_processes = sysconf(_SC_NPROCESSORS_CONF); + worker_connections = 2048; +} + +Config::~Config() { + unique_listen_configs.clear(); + servers.clear(); +} diff --git a/src/Config.hpp b/src/Config.hpp index ee81094..3b0327b 100644 --- a/src/Config.hpp +++ b/src/Config.hpp @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* Config.hpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: mchenava +#+ +:+ +#+ */ +/* By: agaley +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/09 16:53:47 by mchenava #+# #+# */ -/* Updated: 2024/06/20 14:24:33 by mchenava ### ########.fr */ +/* Updated: 2024/06/24 19:22:16 by agaley ### ########lyon.fr */ /* */ /* ************************************************************************** */ @@ -33,16 +33,12 @@ typedef struct LocationConfig { std::map error_pages; // Specific to location - std::set allowed_methods; - int returnCode; - std::string returnUrl; - - LocationConfig() { - client_max_body_size = 1000; - upload = false; - cgi = false; - autoindex = false; - } + std::set allowed_methods; + int returnCode; + std::string returnUrl; + + LocationConfig(); + ~LocationConfig(); } LocationConfig; typedef struct ListenConfig { @@ -54,43 +50,10 @@ typedef struct ListenConfig { int sndbuf; bool ipv6only; - bool operator<(const ListenConfig& other) const { - if (address < other.address) - return true; - if (address > other.address) - return false; - if (port < other.port) - return true; - if (port > other.port) - return false; - if (default_server < other.default_server) - return true; - if (default_server > other.default_server) - return false; - if (rcvbuf < other.rcvbuf) - return true; - if (rcvbuf > other.rcvbuf) - return false; - if (sndbuf < other.sndbuf) - return true; - if (sndbuf > other.sndbuf) - return false; - return ipv6only < other.ipv6only; - } - bool operator==(const ListenConfig& other) const { - return address == other.address && port == other.port && - default_server == other.default_server && backlog == other.backlog && - rcvbuf == other.rcvbuf && sndbuf == other.sndbuf && - ipv6only == other.ipv6only; - } - ListenConfig() { - port = 80; - default_server = false; - backlog = 2048; - rcvbuf = 2048; - sndbuf = 2048; - ipv6only = false; - } + bool operator<(const ListenConfig& other) const; + bool operator==(const ListenConfig& other) const; + + ListenConfig(); } ListenConfig; typedef struct ServerConfig { @@ -109,12 +72,8 @@ typedef struct ServerConfig { std::map locations; - ServerConfig() { - client_max_body_size = 1000; - upload = false; - cgi = false; - autoindex = false; - } + ServerConfig(); + ~ServerConfig(); } ServerConfig; typedef struct Config { @@ -124,11 +83,9 @@ typedef struct Config { std::set unique_listen_configs; std::string log_file; std::vector servers; - Config() { - worker_processes = - sysconf(_SC_NPROCESSORS_CONF); // Initialisation dans le constructeur - worker_connections = 2048; // Valeur fixe initialisée ici - } + + Config(); + ~Config(); } Config; #endif diff --git a/src/ConfigManager.cpp b/src/ConfigManager.cpp index 9da75a8..b427736 100644 --- a/src/ConfigManager.cpp +++ b/src/ConfigManager.cpp @@ -11,6 +11,7 @@ /* ************************************************************************** */ #include "ConfigManager.hpp" +#include "Config.hpp" #include "ConfigParser.hpp" #include "Logger.hpp" @@ -29,6 +30,13 @@ ConfigManager& ConfigManager::getInstance() { return *_instance; } +void ConfigManager::deleteInstance() { + if (_instance != NULL) { + delete _instance; + _instance = NULL; + } +} + Config& ConfigManager::getConfig() const { return _instance->_config; } @@ -47,22 +55,24 @@ void ConfigManager::loadConfig(const std::string& filepath) { void ConfigManager::printConfig() { const Config& config = getInstance()._config; + std::cout << "Unique Listen Configs:" << std::endl; + for (std::set::const_iterator it = + config.unique_listen_configs.begin(); + it != config.unique_listen_configs.end(); ++it) { + const ListenConfig& listen = *it; + std::cout << "\tAddress: " << listen.address << " Port: " << listen.port + << " Default Server: " << (listen.default_server ? "Yes" : "No") + << " Backlog: " << listen.backlog << " Rcvbuf: " << listen.rcvbuf + << " Sndbuf: " << listen.sndbuf + << " IPv6 Only: " << (listen.ipv6only ? "Yes" : "No") + << std::endl; + } for (std::vector::const_iterator it = config.servers.begin(); it != config.servers.end(); ++it) { const ServerConfig& server = *it; - std::cout << "Unique Listen Configs:" << std::endl; - for (std::set::const_iterator it = - config.unique_listen_configs.begin(); - it != config.unique_listen_configs.end(); ++it) { - const ListenConfig& listen = *it; - std::cout << "\tAddress: " << listen.address << " Port: " << listen.port - << " Default Server: " << (listen.default_server ? "Yes" : "No") - << " Backlog: " << listen.backlog - << " Rcvbuf: " << listen.rcvbuf << " Sndbuf: " << listen.sndbuf - << " IPv6 Only: " << (listen.ipv6only ? "Yes" : "No") - << std::endl; - } - std::cout << "Server Names: "; + std::cout << std::endl + << "===================" << std::endl + << "Server Names: "; for (std::vector::const_iterator nameIt = server.server_names.begin(); nameIt != server.server_names.end(); ++nameIt) { @@ -86,7 +96,7 @@ void ConfigManager::_printLocationsConfig( locations.begin(); it != locations.end(); ++it) { const LocationConfig& locationConfig = it->second; - std::cout << "====Route: " << it->first << std::endl; + std::cout << std::endl << it->first << " --------------------" << std::endl; std::cout << "\tDirectory: " << locationConfig.root << std::endl; std::cout << "\tIndex File: " << locationConfig.index << std::endl; std::cout << "\tRoot Directory: " << locationConfig.root << std::endl; @@ -106,7 +116,8 @@ void ConfigManager::_printLocationsConfig( std::cout << *methodIt << " "; } std::cout << std::endl; - std::cout << "======Error Pages:" << std::endl; + if (!locationConfig.error_pages.empty()) + std::cout << " Error Pages:" << std::endl; for (std::map::const_iterator errorIt = locationConfig.error_pages.begin(); errorIt != locationConfig.error_pages.end(); ++errorIt) { diff --git a/src/ConfigManager.hpp b/src/ConfigManager.hpp index 6421f55..cec5fe3 100644 --- a/src/ConfigManager.hpp +++ b/src/ConfigManager.hpp @@ -6,14 +6,13 @@ /* By: agaley +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/30 16:11:17 by agaley #+# #+# */ -/* Updated: 2024/05/29 18:30:10 by agaley ### ########lyon.fr */ +/* Updated: 2024/06/24 22:54:21 by agaley ### ########lyon.fr */ /* */ /* ************************************************************************** */ #ifndef CONFIGMANAGER_H #define CONFIGMANAGER_H -#include "Config.hpp" #include "Logger.hpp" class ConfigManager { @@ -29,6 +28,7 @@ class ConfigManager { ConfigManager(); public: + static void deleteInstance(); ~ConfigManager(); static ConfigManager& getInstance(); const std::string getFilePath() const; diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp index 4037391..e05f6de 100644 --- a/src/ConfigParser.cpp +++ b/src/ConfigParser.cpp @@ -26,8 +26,8 @@ Config ConfigParser::parseConfigFile(const std::string& filepath) { _configFilepath = filepath; std::ifstream configFile(filepath.c_str()); if (!configFile.is_open()) { - throw std::runtime_error("Failed to open config file: " + filepath); _log.emerg("Failed to open config file: " + filepath); + throw Exception("Failed to open config file: " + filepath); } Config config; @@ -39,19 +39,15 @@ Config ConfigParser::parseConfigFile(const std::string& filepath) { iss >> key >> value; value = _cleanValue(value, '#'); - if (key.empty() || key[0] == '#') { - _log.info("Skip empty or comment line :" + line); + if (key.empty() || key[0] == '#') continue; - } - _log.info("========== Parsing line : key = " + key + " line = " + line); if (key == "server") { if (value == "{") { ServerConfig serverConfig; _parseServerConfig(configFile, serverConfig, config); config.servers.push_back(serverConfig); - _log.info("++++++++++++++ new server config add to config"); } else { - throw std::runtime_error("Malformed server block"); + throw Exception("Malformed server block"); } } else if (key == "log_file") { config.log_file = _parseValue(value); @@ -76,30 +72,25 @@ void ConfigParser::_parseServerConfig(std::ifstream& configFile, std::string line; std::string key; while (key != "}" && getline(configFile, line)) { - _log.info("############### parseServerConfig line = [" + line + "]"); std::istringstream lineStream(line); std::string value; std::string afterValue; lineStream >> key >> value >> afterValue; if (key.empty() || key[0] == '#' || key == "}") { - _log.info("server block Skip empty or comment line :" + line); continue; } afterValue = _cleanValue(afterValue, '#'); - _log.info("========= Parsing server block line: key = [" + key + - "] line = [" + line + "]"); if (key == "location") { LocationConfig locationConfig; locationConfig.location = _parseValue(lineStream.str()); if (afterValue == "{") { _parseLocationConfig(configFile, locationConfig, serverConfig); serverConfig.locations[value] = locationConfig; - _log.info(">>>>>>>>>>>>>>>>>>>>> new route config add to server"); } else { std::cerr << "Parsing error !" << std::endl; - throw std::runtime_error("Malformed route block"); + throw Exception("Malformed route block"); } } else { if (key == "listen") { @@ -135,8 +126,6 @@ void ConfigParser::_parseServerConfig(std::ifstream& configFile, int errorCode; std::string errorPage; errorCode = Utils::stoi(value); - _log.info("Server block find error_page: errorCode = " + - Utils::to_string(errorCode) + " errorPage = " + afterValue); errorPage = _cleanValue(afterValue, ';'); serverConfig.error_pages[errorCode] = errorPage; } else { @@ -221,12 +210,8 @@ void ConfigParser::_parseLocationConfig(std::ifstream& configFile, while (key != "}" && getline(configFile, line)) { std::istringstream lineStream(line); lineStream >> key >> value >> afterValue; - if (key.empty() || key[0] == '#' || key == "}") { - _log.info("route block Skip empty or comment line :" + line); + if (key.empty() || key[0] == '#' || key == "}") continue; - } - _log.info(" ====== Parsing route block line: key = " + key + - " line = " + line); if (key == "root") { locationConfig.root = _parseValue(lineStream.str()); } else if (key == "index") { @@ -269,8 +254,6 @@ void ConfigParser::_parseLocationConfig(std::ifstream& configFile, int errorCode; std::string errorPage; errorCode = Utils::stoi(value); - _log.info("Server block find error_page: errorCode = " + - Utils::to_string(errorCode) + " errorPage = " + afterValue); errorPage = _cleanValue(afterValue, ';'); locationConfig.error_pages[errorCode] = errorPage; } else { @@ -283,8 +266,7 @@ void ConfigParser::_parseLocationConfig(std::ifstream& configFile, for (size_t i = 0; i < sizeof(HTTPRequest::supportedMethods) / sizeof(HTTPRequest::supportedMethods[0]); ++i) { - locationConfig.allowed_methods.insert( - HTTPRequest::supportedMethods[i]); + locationConfig.allowed_methods.insert(HTTPRequest::supportedMethods[i]); } } } @@ -323,9 +305,7 @@ std::string ConfigParser::_parseValue(std::string toParse) { std::string value; std::string afterValue; - _log.info("Parsing value form :" + toParse); toParseStream >> key >> value >> afterValue; - _log.info("parsed Value :" + value + " afterValue :" + afterValue); value = _cleanValue(value, '#'); afterValue = _cleanValue(afterValue, '#'); if (key == "route" && afterValue != "{") @@ -335,14 +315,11 @@ std::string ConfigParser::_parseValue(std::string toParse) { _log.warning("Badly terminated server line in server block: " + toParse + " afterValue = " + afterValue); else { - _log.info("key = " + key + " value = " + value + - " afterValue = " + afterValue); size_t semicolonPos = value.find(';'); if (semicolonPos != value.length()) { value = value.substr(0, semicolonPos); } else _log.warning("Badly terminated line in server block: " + toParse); } - _log.info("Parsed value : " + value); return value; } diff --git a/src/ConfigParser.hpp b/src/ConfigParser.hpp index 87479d7..f7b8fd8 100644 --- a/src/ConfigParser.hpp +++ b/src/ConfigParser.hpp @@ -6,7 +6,7 @@ /* By: agaley +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/30 16:11:17 by agaley #+# #+# */ -/* Updated: 2024/06/14 01:05:11 by agaley ### ########lyon.fr */ +/* Updated: 2024/06/24 22:11:19 by agaley ### ########lyon.fr */ /* */ /* ************************************************************************** */ @@ -17,9 +17,9 @@ #include #include #include -#include #include "Config.hpp" +#include "Exception.hpp" #include "HTTPRequest.hpp" #include "Logger.hpp" #include "Utils.hpp" diff --git a/src/ConnectionHandler.cpp b/src/ConnectionHandler.cpp index 4837539..799f198 100644 --- a/src/ConnectionHandler.cpp +++ b/src/ConnectionHandler.cpp @@ -3,60 +3,66 @@ /* ::: :::::::: */ /* ConnectionHandler.cpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: mchenava +#+ +:+ +#+ */ +/* By: mchenava < mchenava@student.42lyon.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/30 16:11:21 by agaley #+# #+# */ -/* Updated: 2024/06/20 14:46:46 by mchenava ### ########.fr */ +/* Updated: 2024/06/25 12:55:28 by mchenava ### ########.fr */ /* */ /* ************************************************************************** */ -#include "ConnectionHandler.hpp" -#include "Common.hpp" #include #include #include #include + +#include "Common.hpp" +#include "ConnectionHandler.hpp" #include "Utils.hpp" ConnectionHandler::ConnectionHandler( - int clientSocket, - int epollSocket, - // ListenConfig& listenConfig, + int clientSocket, + int epollSocket, std::vector& virtualServers) : _log(Logger::getInstance()), - // _listenConfig(listenConfig), _connectionStatus(READING), _clientSocket(clientSocket), _epollSocket(epollSocket), _buffer(new char[BUFFER_SIZE]), _readn(0), - _vservPool(virtualServers) -{ + _vservPool(virtualServers), + _request(NULL), + _response(NULL), + _cacheHandler(CacheHandler::getInstance()) { memset(_buffer, 0, BUFFER_SIZE); - _log.info("CONNECTION_HANDLER: New connection handler created"); - _log.info("CONNECTION_HANDLER: serverPool size : " + - Utils::to_string(_vservPool.size())); - for (std::vector::iterator it = _vservPool.begin(); - it != _vservPool.end(); ++it) { - _log.info("CONNECTION_HANDLER: serverPool name : " + - (*it)->getServerName()); - } } ConnectionHandler::~ConnectionHandler() { + for (std::vector::iterator it = _vservPool.begin(); + it != _vservPool.end(); ++it) { + delete *it; + } delete[] _buffer; + if (_request) { + delete _request; + _request = NULL; + } + if (_response) { + delete _response; + _response = NULL; + } } void ConnectionHandler::_receiveRequest() { - bool headersEnd = false; - ssize_t bytes; + bool headersEnd = false; + ssize_t bytes; std::string headers; - size_t contentLength = 0; - bool contentLengthFound = false; - size_t headersEndPos = 0; - int trys = 0; + size_t contentLength = 0; + bool contentLengthFound = false; + size_t headersEndPos = 0; + int trys = 0; - while (!headersEnd && (bytes = recv(_clientSocket, _buffer + _readn, BUFFER_SIZE - _readn, 0)) > 0) { + while (!headersEnd && (bytes = recv(_clientSocket, _buffer + _readn, + BUFFER_SIZE - _readn, 0)) > 0) { if (bytes <= 0) { if (trys > 3) { _log.error(std::string("CONNECTION_HANDLER: recv: ") + strerror(errno)); @@ -76,7 +82,7 @@ void ConnectionHandler::_receiveRequest() { headersEnd = true; size_t clPos = headers.find("Content-Length:"); if (clPos != std::string::npos) { - size_t clEnd = headers.find("\r\n", clPos); + size_t clEnd = headers.find("\r\n", clPos); std::string clValue = headers.substr(clPos + 15, clEnd - (clPos + 15)); contentLength = Utils::stoi(clValue); contentLengthFound = true; @@ -90,26 +96,28 @@ void ConnectionHandler::_receiveRequest() { } } - if (contentLengthFound && _readn - headersEndPos - 4 != contentLength) { - _log.error("CONNECTION_HANDLER: Content-Length mismatch"); - _connectionStatus = CLOSED; - return; + _log.error("CONNECTION_HANDLER: Content-Length mismatch"); + _connectionStatus = CLOSED; + return; } - - _log.info("CONNECTION_HANDLER: Request received: " + std::string(_buffer, _readn)); _processRequest(); _readn = 0; } void ConnectionHandler::_sendResponse() { + std::string method = _request->getMethod(); + std::string protocol = _request->getProtocol(); + std::string uri = _request->getURI(); + std::string status = Utils::to_string(_response->getStatusCode()); + std::string contentLength = + _response->getHeaders().find("Content-Length")->second; if (_response->sendResponse(_clientSocket) == -1) throw WriteException("CONNECTION_HANDLER: Failed to send response"); _connectionStatus = CLOSED; } VirtualServer* ConnectionHandler::_selectVirtualServer(std::string host) { - _log.info(std::string("CONNECTION_HANDLER: Host extracted: ") + host); if (!host.empty()) { for (std::vector::iterator it = _vservPool.begin(); it != _vservPool.end(); ++it) { @@ -164,11 +172,21 @@ std::string ConnectionHandler::_extractHost(const std::string& requestHeader) { } void ConnectionHandler::_processRequest() { + if (_request) { + delete _request; + _request = NULL; + } _request = new HTTPRequest(_buffer); - std::string sessionId = _request->getSessionId(); - if (sessionId.empty()) { - sessionId = generateSessionId(); - _request->setSessionId(sessionId); + + if (_request->getHeader("Cache-Control") != "no-cache") { + HTTPResponse* cachedResponse = _cacheHandler.getResponse(*_request); + if (cachedResponse) { + _log.info("CONNECTION_HANDLER: Cache hit"); + _response = cachedResponse; + _response->setCookie("sessionid", _request->getSessionId()); + _connectionStatus = SENDING; + return; + } } VirtualServer* vserv = _selectVirtualServer(_request->getHost()); @@ -181,50 +199,59 @@ void ConnectionHandler::_processRequest() { if ((_response = vserv->checkRequest(*_request)) != NULL) { _log.error("CONNECTION_HANDLER: Request failed"); - _response->setCookie("sessionid", sessionId); _connectionStatus = SENDING; return; } - _log.info("CONNECTION_HANDLER: Request valid"); _response = vserv->handleRequest(*_request); - _response->setCookie("sessionid", sessionId); + _response->addHeader( + "Cache-Control", + "public, max-age=" + Utils::to_string(CacheHandler::MAX_AGE)); + _cacheHandler.storeResponse(*_request, *_response); + + _response->setCookie("sessionid", _request->getSessionId()); + _connectionStatus = SENDING; } -int ConnectionHandler::getConnectionStatus() const { +int ConnectionHandler::getConnectionStatus() { return _connectionStatus; } -void ConnectionHandler::processConnection() { - struct epoll_event event; - event.data.fd = _clientSocket; - event.data.ptr = this; +void ConnectionHandler::_processData() { if (_connectionStatus == READING) { try { - _log.info(std::string("CONNECTION_HANDLER: receive req: ")); _receiveRequest(); } catch (const Exception& e) { _log.error(std::string("CONNECTION_HANDLER: Exception caught: ") + e.what()); return; } - event.events = EPOLLIN | EPOLLET | EPOLLONESHOT; - if (epoll_ctl(_epollSocket, EPOLL_CTL_MOD, _clientSocket, &event) == -1) { - _log.error(std::string("CONNECTION_HANDLER: epoll_ctl: ") + - strerror(errno)); - return; - } } if (_connectionStatus == SENDING) { try { _sendResponse(); } catch (const Exception& e) { - _log.error( - std::string("CONNECTION_HANDLER: Exception caught while sending: ") + - e.what()); + _log.error(std::string("CONNECTION_HANDLER: Exception caught: ") + + e.what()); + return; + } + } +} + +void ConnectionHandler::processConnection() { + struct epoll_event event; + event.data.fd = _clientSocket; + event.data.ptr = this; + _processData(); + if (_connectionStatus == READING) { + event.events = EPOLLIN | EPOLLET | EPOLLONESHOT; + if (epoll_ctl(_epollSocket, EPOLL_CTL_MOD, _clientSocket, &event) == -1) { + _log.error(std::string("CONNECTION_HANDLER: epoll_ctl: ") + + strerror(errno)); return; } + } else if (_connectionStatus == SENDING) { event.events = EPOLLOUT | EPOLLET | EPOLLONESHOT; if (epoll_ctl(_epollSocket, EPOLL_CTL_MOD, _clientSocket, &event) == -1) { _log.error(std::string("CONNECTION_HANDLER: epoll_ctl: ") + @@ -233,6 +260,20 @@ void ConnectionHandler::processConnection() { } } if (_connectionStatus == CLOSED) { + std::string host = _request->getHost(); + std::string method = _request->getMethod(); + std::string uri = _request->getURI(); + std::string protocol = _request->getProtocol(); + std::string status = Utils::to_string(_response->getStatusCode()); + std::string contentLength = + _response->getHeaders().find("Content-Length")->second; + _log.info("CONNECTION_HANDLER: Connection closed, client socket: " + + Utils::to_string(_clientSocket)); + _log.info("Request : " + host + " - " + method + " " + uri + " " + + protocol); + _log.info("Response : " + status + " " + contentLength); + epoll_ctl(_epollSocket, EPOLL_CTL_DEL, _clientSocket, NULL); close(_clientSocket); + delete this; } } diff --git a/src/ConnectionHandler.hpp b/src/ConnectionHandler.hpp index 0873e55..9244a88 100644 --- a/src/ConnectionHandler.hpp +++ b/src/ConnectionHandler.hpp @@ -3,19 +3,22 @@ /* ::: :::::::: */ /* ConnectionHandler.hpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: mchenava +#+ +:+ +#+ */ +/* By: agaley +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/30 16:11:25 by agaley #+# #+# */ -/* Updated: 2024/06/20 14:46:33 by mchenava ### ########.fr */ +/* Updated: 2024/06/25 01:51:47 by agaley ### ########lyon.fr */ /* */ /* ************************************************************************** */ #ifndef CONNECTION_HANDLER_H #define CONNECTION_HANDLER_H +#include #include #include #include + +#include "CacheHandler.hpp" #include "Config.hpp" #include "HTTPRequest.hpp" #include "HTTPResponse.hpp" @@ -36,7 +39,7 @@ class ConnectionHandler { // HTTPProtocol* selectHTTPProtocolVersion(const std::string& requestString); void processConnection(); - int getConnectionStatus() const; + int getConnectionStatus(); class ConnectionException : public Exception { public: @@ -70,6 +73,8 @@ class ConnectionHandler { std::vector _vservPool; HTTPRequest* _request; HTTPResponse* _response; + CacheHandler& _cacheHandler; + // pthread_mutex_t _mutex; void _receiveRequest(); void _processRequest(); @@ -77,6 +82,7 @@ class ConnectionHandler { VirtualServer* _findDefaultServer(); std::string _extractHost(const std::string& requestHeader); void _sendResponse(); + void _processData(); }; #endif diff --git a/src/HTTPMethods.cpp b/src/HTTPMethods.cpp index 65f6554..dadf89d 100644 --- a/src/HTTPMethods.cpp +++ b/src/HTTPMethods.cpp @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* HTTPMethods.cpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: mchenava < mchenava@student.42lyon.fr> +#+ +:+ +#+ */ +/* By: mchenava +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/11 11:59:07 by mchenava #+# #+# */ -/* Updated: 2024/06/18 23:47:06 by mchenava ### ########.fr */ +/* Updated: 2024/06/24 14:22:56 by mchenava ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,7 +17,9 @@ HTTPMethods::HTTPMethods(VirtualServer& server): _log(Logger::getInstance()) {} -HTTPMethods::~HTTPMethods() {} +HTTPMethods::~HTTPMethods() { + +} std::string HTTPMethods::_getPath(const std::string& uri, LocationConfig& location) { @@ -66,8 +68,8 @@ std::string HTTPMethods::_generateDirectoryListing(const std::string& path) { } HTTPResponse* HTTPMethods::_autoindex(const std::string& path, - LocationConfig& location) { - std::string indexPath = path + "/" + location.index; + LocationConfig& location) { + std::string indexPath = path + location.index; if (FileManager::doesFileExists(indexPath)) { HTTPResponse* response = new HTTPResponse(HTTPResponse::OK); response->addHeader("Content-Type", "text/html"); @@ -91,7 +93,6 @@ HTTPResponse* HTTPMethods::_autoindex(const std::string& path, HTTPResponse* HTTPMethods::_handleGetRequest(HTTPRequest& request) { std::string uri = request.getURI(); - _log.info("HTTPMethods::_handleGetRequest : URI : " + uri); LocationConfig location = _server.getLocationConfig(uri); std::string path = _getPath(uri, location); struct stat statbuf; @@ -124,7 +125,6 @@ HTTPResponse* HTTPMethods::_handlePostRequest(HTTPRequest& request) { std::string path = _getPath(request.getURI(), location); std::string contentType; contentType = request.getHeader("Content-Type"); - _log.info("HTTPMethods::_handlePostRequest : Content-Type: " + contentType); if (contentType == "") { contentType = HTTPResponse::getContentType(path); } @@ -181,8 +181,6 @@ HTTPResponse* HTTPMethods::handleRequest(HTTPRequest& request) { std::string uri = request.getURI(); LocationConfig location = _server.getLocationConfig(uri); request.setConfig(&location); - _log.info("HTTPMethods::handleRequest : Protocol : " + protocol + - " Method : " + method + " URI : " + uri); if (protocol != "HTTP/1.1") { _log.error("HTTPMethods::handleRequest : Protocol not supported"); diff --git a/src/HTTPRequest.cpp b/src/HTTPRequest.cpp index 0f76c69..bd0fb29 100644 --- a/src/HTTPRequest.cpp +++ b/src/HTTPRequest.cpp @@ -3,14 +3,15 @@ /* ::: :::::::: */ /* HTTPRequest.cpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: mchenava < mchenava@student.42lyon.fr> +#+ +:+ +#+ */ +/* By: agaley +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/30 16:10:58 by agaley #+# #+# */ -/* Updated: 2024/06/18 17:25:37 by mchenava ### ########.fr */ +/* Updated: 2024/06/25 03:18:55 by agaley ### ########lyon.fr */ /* */ /* ************************************************************************** */ #include "HTTPRequest.hpp" +#include "Common.hpp" #include "Utils.hpp" const std::string HTTPRequest::supportedMethods[4] = {"GET", "HEAD", "DELETE", @@ -38,15 +39,19 @@ void HTTPRequest::parseRequest() { _uri = URI::decode(rawUri); _uriComponents = URI::parse(rawUri); - std::cout << "URI: " << _uri << std::endl; - std::cout << "Method: " << _method << std::endl; - std::cout << "Protocol: " << _protocol << std::endl; - std::cout << "URI Components:" << std::endl; - std::cout << " Extension: " << _uriComponents.extension << std::endl; - std::cout << " Script Name: " << _uriComponents.scriptName << std::endl; - std::cout << " Path Info: " << _uriComponents.pathInfo << std::endl; - std::cout << " Query String: " << _uriComponents.queryString << std::endl; + _parseHeaders(requestStream); + if (_method == "POST" || _method == "PUT") { + std::stringstream bodyStream; + bodyStream << requestStream.rdbuf(); + setBody(bodyStream.str()); + } + + _parseSession(); +} + +void HTTPRequest::_parseHeaders(std::istringstream& requestStream) { + std::string line; while (std::getline(requestStream, line) && !line.empty()) { if (line == "\r" || line.empty()) break; @@ -59,12 +64,22 @@ void HTTPRequest::parseRequest() { addHeader(key, value); } } +} - if (_method == "POST" || _method == "PUT") { - std::stringstream bodyStream; - bodyStream << requestStream.rdbuf(); - setBody(bodyStream.str()); +void HTTPRequest::_parseSession() { + std::string sessionId; + std::string cookieHeader = getHeader("Cookie"); + std::size_t pos = cookieHeader.find("sessionid="); + if (pos != std::string::npos) { + std::size_t endPos = cookieHeader.find(";", pos); + if (endPos == std::string::npos) + sessionId = cookieHeader.substr(pos + 10); + else + sessionId = cookieHeader.substr(pos + 10, endPos - pos - 10); } + if (sessionId.empty()) + sessionId = generateSessionId(); + setSessionId(sessionId); } void HTTPRequest::setSessionId(const std::string& sessionId) { diff --git a/src/HTTPRequest.hpp b/src/HTTPRequest.hpp index 1cd70c5..64cf9d7 100644 --- a/src/HTTPRequest.hpp +++ b/src/HTTPRequest.hpp @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* HTTPRequest.hpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: mchenava +#+ +:+ +#+ */ +/* By: agaley +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/30 16:12:02 by agaley #+# #+# */ -/* Updated: 2024/06/14 13:42:10 by mchenava ### ########.fr */ +/* Updated: 2024/06/25 03:18:01 by agaley ### ########lyon.fr */ /* */ /* ************************************************************************** */ @@ -54,8 +54,8 @@ class HTTPRequest { void setBody(const std::string& body); private: - std::string _sessionId; - std::string _rawRequest; + std::string _sessionId; + std::string _rawRequest; // size_t _readn; std::string _method; std::string _uri; @@ -64,6 +64,9 @@ class HTTPRequest { std::string _body; std::string _protocol; LocationConfig* _config; + + void _parseHeaders(std::istringstream& requestStream); + void _parseSession(); }; #endif diff --git a/src/HTTPResponse.cpp b/src/HTTPResponse.cpp index dc1a0ac..f561b3a 100644 --- a/src/HTTPResponse.cpp +++ b/src/HTTPResponse.cpp @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* HTTPResponse.cpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: mchenava +#+ +:+ +#+ */ +/* By: agaley +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/30 16:12:07 by agaley #+# #+# */ -/* Updated: 2024/06/20 12:36:59 by mchenava ### ########.fr */ +/* Updated: 2024/06/24 16:15:46 by agaley ### ########lyon.fr */ /* */ /* ************************************************************************** */ @@ -269,7 +269,8 @@ void HTTPResponse::buildResponse() { } std::string HTTPResponse::defaultErrorPage(int status) { - for (int i = 0; i < NUM_STATUS_CODE_MESSAGES; i++) { + for (unsigned long i = 0; + i < sizeof(_defaultErrorPages) / sizeof(_defaultErrorPages[0]); i++) { if (_defaultErrorPages[i].first == status) { return std::string(_defaultErrorPages[i].second); } @@ -277,18 +278,17 @@ std::string HTTPResponse::defaultErrorPage(int status) { return std::string(""); } -ssize_t HTTPResponse::_sendAll(int socket, const char *buffer, size_t length) { - size_t totalSent = 0; // combien de bytes nous avons envoyé +ssize_t HTTPResponse::_sendAll(int socket, const char* buffer, size_t length) { + size_t totalSent = 0; // combien de bytes nous avons envoyé ssize_t bytesSent; - int trys = 0; + int trys = 0; - _log.info("length to send: " + Utils::to_string(length)); while (totalSent < length) { bytesSent = send(socket, buffer + totalSent, length - totalSent, 0); - _log.info("bytesSent: " + Utils::to_string(bytesSent)); if (bytesSent == -1) { if (trys > 3) { - throw Exception("(send) Error sending response" + std::string(strerror(errno))); + throw Exception("(send) Error sending response" + + std::string(strerror(errno))); } trys++; usleep(1000); @@ -298,28 +298,28 @@ ssize_t HTTPResponse::_sendAll(int socket, const char *buffer, size_t length) { totalSent += bytesSent; } - return totalSent; // Retourne le nombre total de bytes envoyés + return totalSent; // Retourne le nombre total de bytes envoyés } ssize_t HTTPResponse::_sendAllFile(int clientSocket, FILE* file) { - fseek(file, 0, SEEK_END); - off_t file_length = static_cast(ftell(file)); - fseek(file, 0, SEEK_SET); - - off_t offset = 0; - ssize_t bytesSent; - - while (offset < file_length) { - bytesSent = sendfile(clientSocket, fileno(file), &offset, file_length - offset); - if (bytesSent == -1) { - throw Exception("(sendfile) Error sending response"); - } + fseek(file, 0, SEEK_END); + off_t file_length = static_cast(ftell(file)); + fseek(file, 0, SEEK_SET); + + off_t offset = 0; + ssize_t bytesSent; + + while (offset < file_length) { + bytesSent = + sendfile(clientSocket, fileno(file), &offset, file_length - offset); + if (bytesSent == -1) { + throw Exception("(sendfile) Error sending response"); } - return offset; // Retourne le nombre total de bytes envoyés + } + return offset; // Retourne le nombre total de bytes envoyés } -int HTTPResponse::sendResponse(int clientSocket) -{ +int HTTPResponse::sendResponse(int clientSocket) { buildResponse(); _sendAll(clientSocket, _responseBuffer.c_str(), _responseBuffer.size()); diff --git a/src/Logger.cpp b/src/Logger.cpp index f41cd8b..d8bca60 100644 --- a/src/Logger.cpp +++ b/src/Logger.cpp @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* Logger.cpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: mchenava < mchenava@student.42lyon.fr> +#+ +:+ +#+ */ +/* By: agaley +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/24 13:32:08 by mchenava #+# #+# */ -/* Updated: 2024/06/11 15:23:29 by mchenava ### ########.fr */ +/* Updated: 2024/06/24 22:42:58 by agaley ### ########lyon.fr */ /* */ /* ************************************************************************** */ @@ -28,6 +28,13 @@ Logger& Logger::getInstance() { return *_instance; } +void Logger::deleteInstance() { + if (_instance != NULL) { + delete _instance; + _instance = NULL; + } +} + Logger::~Logger() { if (_progLogFile->is_open()) { _progLogFile->close(); diff --git a/src/Logger.hpp b/src/Logger.hpp index 4a5716d..fa24b76 100644 --- a/src/Logger.hpp +++ b/src/Logger.hpp @@ -6,7 +6,7 @@ /* By: agaley +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/24 13:21:59 by mchenava #+# #+# */ -/* Updated: 2024/06/04 01:25:25 by agaley ### ########lyon.fr */ +/* Updated: 2024/06/24 22:44:12 by agaley ### ########lyon.fr */ /* */ /* ************************************************************************** */ @@ -34,6 +34,7 @@ class Logger { void error(const std::string& message) const; void emerg(const std::string& message) const; + static void deleteInstance(); ~Logger(); private: diff --git a/src/Server.cpp b/src/Server.cpp index f60aff3..077630b 100644 --- a/src/Server.cpp +++ b/src/Server.cpp @@ -11,91 +11,152 @@ /* ************************************************************************** */ #include "Server.hpp" +#include #include "Common.hpp" #include "ConfigManager.hpp" #include "Utils.hpp" Server* Server::_instance = NULL; +int Server::_callCount = 1; Server::Server() : _config(ConfigManager::getInstance().getConfig()), _log(Logger::getInstance()), - _workerIndex(0), - _activeWorkers(0) { - - _setupWorkers(); + _activeWorkers(0), + _event_count(0), + _events() { + _log.info("====================SERVER: Setup server " + + Utils::to_string(_callCount)); + _setupEpoll(); _setupServerSockets(); + _setupWorkers(); pthread_mutex_init(&_mutex, NULL); - pthread_cond_init(&_cond, NULL); + pthread_mutex_init(&_eventsMutex, NULL); + _callCount++; + _running = false; + _instance = this; } Server::~Server() { for (size_t i = 0; i < _workers.size(); i++) { - _workers[i]->stop(); delete _workers[i]; } _workers.clear(); - pthread_cond_destroy(&_cond); pthread_mutex_destroy(&_mutex); + pthread_mutex_destroy(&_eventsMutex); + CacheHandler::deleteInstance(); + ConfigManager::deleteInstance(); Server::_instance = NULL; } Server& Server::getInstance() { - if (Server::_instance == NULL) { - Server::_instance = new Server(); + if (_instance == NULL) { + Logger::getInstance().info("SERVER: Creating server instance"); + _instance = new Server(); } - return *Server::_instance; + return *_instance; } void Server::workerFinished() { pthread_mutex_lock(&_mutex); _activeWorkers--; + _log.info("SERVER: Worker finished (" + Utils::to_string(_activeWorkers) + + ")"); if (_activeWorkers == 0) { - pthread_cond_signal(&_cond); + _running = false; + _log.info("SERVER: All workers finished"); } pthread_mutex_unlock(&_mutex); } void Server::start() { + _running = true; for (size_t i = 0; i < _workers.size(); i++) { _workers[i]->start(); pthread_mutex_lock(&_mutex); _activeWorkers++; pthread_mutex_unlock(&_mutex); } - pthread_mutex_lock(&_mutex); - while (_activeWorkers > 0) { - pthread_cond_wait(&_cond, &_mutex); + _log.info("SERVER: All workers started (" + Utils::to_string(_activeWorkers) + + ")"); + struct epoll_event events[MAX_EVENTS]; + while (_running) { + _log.info("SERVER: Waiting for events..."); + int nfds = epoll_wait(_epollSocket, events, MAX_EVENTS, -1); + if (nfds < 0) { + _log.error("SERVER: Failed to wait for events"); + usleep(1000); + continue; + } + for (int i = 0; i < nfds && _running; i++) { + _addEvent(events[i]); + _log.info("SERVER: Added event to queue"); + } } - pthread_mutex_unlock(&_mutex); + _log.info("SERVER: events queue size: " + Utils::to_string(_events.size())); +} + +void Server::_addEvent(struct epoll_event event) { + pthread_mutex_lock(&_eventsMutex); + _events.push(event); + pthread_mutex_unlock(&_eventsMutex); +} + +struct epoll_event Server::getEvent() { + pthread_mutex_lock(&_eventsMutex); + if (_events.empty()) { + struct epoll_event event = {}; + event.data.fd = -1; + pthread_mutex_unlock(&_eventsMutex); + return event; + } + struct epoll_event event = _events.front(); + _events.pop(); + pthread_mutex_unlock(&_eventsMutex); + _log.info("SERVER: Event popped"); + return event; } void Server::stop(int signum) { if (signum == SIGINT || signum == SIGTERM || signum == SIGKILL) { - Server::_instance->_log.info("Server stopped from signal " + Utils::to_string(signum)); - delete Server::_instance; - Server::_instance = NULL; - throw std::runtime_error("Server stopped"); + Server::_instance->_log.info("Server stopped from signal " + + Utils::to_string(signum)); + for (size_t i = 0; i < _workers.size(); i++) { + _log.info("SERVER: stopping worker " + Utils::to_string(i) + " (" + + Utils::to_string(_workers[i]->_threadId) + ")"); + _workers[i]->stop(); + } + _log.info("SERVER: workers stopped"); + _running = false; } } void Server::_setupWorkers() { for (int i = 0; i < _config.worker_processes; i++) { - _workers.push_back(new Worker()); + _workers.push_back(new Worker(*this, _epollSocket, _listenSockets)); + } +} + +void Server::_setupEpoll() { + _epollSocket = epoll_create1(0); + if (_epollSocket == -1) { + _log.error("Failed to create epoll socket"); + throw std::runtime_error("Failed to create epoll socket"); } } void Server::_setupServerSockets() { const std::set& uniqueConfigs = _config.unique_listen_configs; + _log.info("SERVER: Setup server sockets"); for (std::set::const_iterator it = uniqueConfigs.begin(); it != uniqueConfigs.end(); ++it) { const ListenConfig& listenConfig = *it; int sock = socket(AF_INET6, SOCK_STREAM, 0); if (sock < 0) { _log.error("(" + listenConfig.address + ":" + - Utils::to_string(listenConfig.port) + - ") Failed to create socket"); + Utils::to_string(listenConfig.port) + + ") Failed to create socket"); continue; } @@ -179,8 +240,19 @@ void Server::_setupServerSockets() { close(sock); continue; } - _listenSockets[listenConfig] = sock; - _workers[_workerIndex]->assignConnection(sock, listenConfig); - _workerIndex = (_workerIndex + 1) % _config.worker_processes; + + struct epoll_event event; + memset(&event, 0, sizeof(event)); + event.data.fd = sock; + event.events = EPOLLIN | EPOLLET; + if (epoll_ctl(_epollSocket, EPOLL_CTL_ADD, sock, &event) == -1) { + close(sock); + _log.error(std::string("SERVER (assign conn): Failed \"epoll_ctl\": ") + + strerror(errno) + " (" + Utils::to_string(sock) + ")"); + continue; + } + _log.info("SERVER (assign conn): Add socket to epoll : " + + Utils::to_string(sock)); + _listenSockets[sock] = listenConfig; } } diff --git a/src/Server.hpp b/src/Server.hpp index 872338d..616c16d 100644 --- a/src/Server.hpp +++ b/src/Server.hpp @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* Server.hpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: mchenava +#+ +:+ +#+ */ +/* By: agaley +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/28 15:34:01 by agaley #+# #+# */ -/* Updated: 2024/06/20 15:31:20 by mchenava ### ########.fr */ +/* Updated: 2024/06/24 23:04:40 by agaley ### ########lyon.fr */ /* */ /* ************************************************************************** */ @@ -19,34 +19,48 @@ #include #include #include +#include +#include "Common.hpp" #include "Config.hpp" #include "Logger.hpp" #include "Worker.hpp" +#define SHUTDOWN_DELAY 200000 + class Worker; class Server { private: - static Server* _instance; - Config& _config; - Logger& _log; - std::vector _workers; - int _workerIndex; - std::map _listenSockets; - pthread_mutex_t _mutex; - pthread_cond_t _cond; - int _activeWorkers; - - void _setupServerSockets(); - void _setupWorkers(); - static void _signalHandler(int signum); + static int _callCount; + static Server* _instance; + Config& _config; + Logger& _log; + std::vector _workers; + std::map _listenSockets; + pthread_mutex_t _mutex; + pthread_cond_t _cond; + int _epollSocket; + int _activeWorkers; + int _event_count; + pthread_mutex_t _eventsMutex; + bool _running; + std::queue _events; + std::map > _virtualServers; + void _setupServerSockets(); + void _setupWorkers(); + void _setupEpoll(); + void _addEvent(struct epoll_event event); + std::vector _setupAssociateVirtualServers( + const ListenConfig& listenConfig); public: Server(); - static Server& getInstance(); - void workerFinished(); + static Server& getInstance(); + std::vector getVirtualServer(int fd); + void workerFinished(); + struct epoll_event getEvent(); ~Server(); void start(); diff --git a/src/Utils.cpp b/src/Utils.cpp index d7b49bc..76c5c1f 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -3,16 +3,15 @@ /* ::: :::::::: */ /* Utils.cpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: mchenava +#+ +:+ +#+ */ +/* By: agaley +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/30 16:13:32 by agaley #+# #+# */ -/* Updated: 2024/06/20 12:17:58 by mchenava ### ########.fr */ +/* Updated: 2024/06/25 02:25:50 by agaley ### ########lyon.fr */ /* */ /* ************************************************************************** */ #include "Utils.hpp" - template T Utils::stoi(const std::string& str) { std::istringstream iss(str); @@ -86,7 +85,7 @@ template std::string Utils::to_string(const int& num); template std::string Utils::to_string(const unsigned int& num); template std::string Utils::to_string(const float& num); template std::string Utils::to_string(const double& num); -template std::string Utils::to_string(const ssize_t& num); +template std::string Utils::to_string(const long& num); void Utils::freeCharVector(std::vector& vec) { for (size_t i = 0; i < vec.size(); i++) diff --git a/src/VirtualServer.cpp b/src/VirtualServer.cpp index a55e3f0..c5f6f59 100644 --- a/src/VirtualServer.cpp +++ b/src/VirtualServer.cpp @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* VirtualServer.cpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: mchenava < mchenava@student.42lyon.fr> +#+ +:+ +#+ */ +/* By: agaley +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/24 15:10:25 by mchenava #+# #+# */ -/* Updated: 2024/06/18 17:32:18 by mchenava ### ########.fr */ +/* Updated: 2024/06/24 16:21:51 by agaley ### ########lyon.fr */ /* */ /* ************************************************************************** */ @@ -74,16 +74,13 @@ LocationConfig& VirtualServer::getLocationConfig(const std::string& uri) { } HTTPResponse* VirtualServer::checkRequest(HTTPRequest& request) { - std::string protocol = request.getProtocol(); - std::string method = request.getMethod(); - std::string uri = request.getURI(); - std::string body = request.getBody(); - int contentLength = request.getContentLength(); + std::string protocol = request.getProtocol(); + std::string method = request.getMethod(); + std::string uri = request.getURI(); + std::string body = request.getBody(); + int contentLength = request.getContentLength(); LocationConfig location = getLocationConfig(uri); - _log.info("Checking request: Protocol: " + protocol + ", Method: " + method + - ", URI: " + uri + ", Content Length: " + Utils::to_string(contentLength)); - if (protocol != "HTTP/1.1") { _log.error("Unsupported protocol"); return new HTTPResponse(HTTPResponse::BAD_REQUEST, location.error_pages); @@ -94,18 +91,38 @@ HTTPResponse* VirtualServer::checkRequest(HTTPRequest& request) { return new HTTPResponse(HTTPResponse::NOT_FOUND, location.error_pages); } - if (std::find(location.allowed_methods.begin(), location.allowed_methods.end(), method) == location.allowed_methods.end()) { + if (std::find(location.allowed_methods.begin(), + location.allowed_methods.end(), + method) == location.allowed_methods.end()) { _log.error("Method not allowed for this location"); - return new HTTPResponse(HTTPResponse::METHOD_NOT_ALLOWED, location.error_pages); + return new HTTPResponse(HTTPResponse::METHOD_NOT_ALLOWED, + location.error_pages); } - if (!body.empty() && contentLength == -1) { - _log.error("Content length not provided"); - return new HTTPResponse(HTTPResponse::LENGTH_REQUIRED, location.error_pages); - } - if (contentLength != -1 && ((size_t)contentLength > location.client_max_body_size || (size_t)contentLength != body.length())) { - _log.error("Content length too big or mismatch"); - return new HTTPResponse(HTTPResponse::REQUEST_ENTITY_TOO_LARGE, location.error_pages); + if (method != "GET" && method != "HEAD") { + if (!body.empty() && contentLength == -1) { + _log.error("Content length not provided"); + return new HTTPResponse(HTTPResponse::LENGTH_REQUIRED, + location.error_pages); + } + + if (contentLength < 0) { + _log.error("Negative content length"); + return new HTTPResponse(HTTPResponse::BAD_REQUEST, location.error_pages); + } + + if (contentLength != -1) { + if (static_cast(contentLength) > location.client_max_body_size) { + _log.error("Content length too big"); + return new HTTPResponse(HTTPResponse::REQUEST_ENTITY_TOO_LARGE, + location.error_pages); + } + if (static_cast(contentLength) != body.length()) { + _log.error("Content length mismatch"); + return new HTTPResponse(HTTPResponse::BAD_REQUEST, + location.error_pages); + } + } } if (location.returnCode >= 300 && location.returnCode < 400) { @@ -139,8 +156,8 @@ std::string VirtualServer::getRoot() const { } void VirtualServer::storeSessionData(const std::string& sessionId, - const std::string& key, - const std::string& value) { + const std::string& key, + const std::string& value) { _sessionStore[sessionId][key] = value; } diff --git a/src/Worker.cpp b/src/Worker.cpp index 51cfbb0..d20f643 100644 --- a/src/Worker.cpp +++ b/src/Worker.cpp @@ -13,29 +13,34 @@ #include "Worker.hpp" #include "Common.hpp" #include "ConfigManager.hpp" -#include "Server.hpp" -Worker::Worker() - : _config(ConfigManager::getInstance().getConfig()), +Worker::Worker(Server& server, + int epollSocket, + std::map& listenSockets) + : _server(server), + _thread(0), + _config(ConfigManager::getInstance().getConfig()), _log(Logger::getInstance()), - _maxConnections(_config.worker_connections), - _currentConnections(0), + _epollSocket(epollSocket), + _listenSockets(listenSockets), + _load(0), _shouldStop(false) { _log.info("Worker constructor called"); } -Worker::~Worker() { - // _stop(); +Worker::~Worker() {} - // pthread_mutex_destroy(&_stopMutex); -} +void Worker::start() { + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); -void Worker::start() { - if (pthread_create(&_thread, NULL, _workerRoutine, this) != 0) { + if (pthread_create(&_thread, &attr, _workerRoutine, this) != 0) { _log.error("WORKER : Failed to create thread proc"); } - pthread_detach(_thread); + + pthread_attr_destroy(&attr); } void Worker::stop() { @@ -51,8 +56,6 @@ std::vector Worker::_setupAssociateVirtualServer( for (std::vector::iterator lit = it->listen.begin(); lit != it->listen.end(); ++lit) { if (*lit == listenConfig) { - _log.info("WORKER: Associate VirtualServer to a conn: " + - it->server_names[0] + "\n"); virtualServers.push_back(new VirtualServer(*it)); break; } @@ -61,100 +64,74 @@ std::vector Worker::_setupAssociateVirtualServer( return virtualServers; } -void Worker::assignConnection(int clientSocket, - const ListenConfig& listenConfig) { - struct epoll_event event; - event.data.fd = clientSocket; - event.events = EPOLLIN | EPOLLET; - - if (_currentConnections >= _maxConnections) { - _log.error("WORKER: Max connections reached"); - close(clientSocket); - } else { - if (epoll_ctl(_epollSocket, EPOLL_CTL_ADD, clientSocket, &event) == -1) { - close(clientSocket); - _log.error(std::string("WORKER (assign conn): Failed \"epoll_ctl\": ") + - strerror(errno) + " (" + Utils::to_string(clientSocket) + ")"); - return; - } - _listenSockets.push_back(clientSocket); - _listenConfigs[clientSocket] = listenConfig; - _virtualServers[clientSocket] = _setupAssociateVirtualServer(listenConfig); - _currentConnections++; - } +int Worker::getLoad() { + return _load; } void Worker::_runEventLoop() { - struct epoll_event events[MAX_EVENTS]; - int nfds; while (!_shouldStop) { - nfds = epoll_wait(_epollSocket, events, MAX_EVENTS, -1); - if (nfds <= 0) { - _log.error("Erreur lors de l'attente des événements epoll"); + struct epoll_event event = _server.getEvent(); + if (event.data.fd == -1) { + usleep(1000); continue; } - - for (int n = 0; n < nfds; ++n) { - if (std::find(_listenSockets.begin(), _listenSockets.end(), - events[n].data.fd) != _listenSockets.end()) - _acceptNewConnection(events[n].data.fd); - else - _handleIncomingConnection(events[n]); - } + if (_listenSockets.find(event.data.fd) != _listenSockets.end() && + event.events & EPOLLIN) + _acceptNewConnection(event.data.fd); + else + _handleIncomingConnection(event); } + _log.info("WORKER (" + Utils::to_string(_threadId) + "): End of event loop"); } void Worker::_acceptNewConnection(int fd) { struct sockaddr_storage address; - socklen_t addrlen = sizeof(address); - int new_socket; - struct epoll_event event; - int trys = 0; + socklen_t addrlen = sizeof(address); + int new_socket; + struct epoll_event event; - _log.info("WORKER: \"accept\""); - while (true) { + while (!_shouldStop) { new_socket = accept(fd, (struct sockaddr*)&address, &addrlen); - if (new_socket < 0) { - if (trys > 3) { - _log.error("WORKER: Failed \"accept\""); - break; - } - trys++; - usleep(1000); - continue; + if (new_socket <= 0) { + _log.info("WORKER (" + Utils::to_string(_thread) + + "): Failed \"accept\" for fd =" + Utils::to_string(fd) + ": " + + strerror(errno)); + break; } - trys = 0; if (set_non_blocking(new_socket) == -1) { - _log.error("WORKER: Failed \"set_non_blocking\""); + _log.error("WORKER (" + Utils::to_string(_thread) + + "): Failed \"set_non_blocking\""); continue; } event.events = EPOLLIN | EPOLLET | EPOLLONESHOT; - ConnectionHandler* handler = new ConnectionHandler( - new_socket, _epollSocket, /*_listenConfigs[fd],*/ _virtualServers[fd]); - _handlers[new_socket] = handler; + ListenConfig listenConfig = _listenSockets[fd]; + std::vector virtualServers = + _setupAssociateVirtualServer(listenConfig); + ConnectionHandler* handler = + new ConnectionHandler(new_socket, _epollSocket, virtualServers); event.data.ptr = handler; if (epoll_ctl(_epollSocket, EPOLL_CTL_ADD, new_socket, &event) < 0) { - _log.error("WORKER (new conn): Failed \"epoll_ctl\""); + _log.error("WORKER (" + Utils::to_string(_thread) + + "): Failed \"epoll_ctl\""); continue; } } } -void Worker::_handleIncomingConnection(struct epoll_event& event) { - _log.info("WORKER: Handling incoming connection"); - ConnectionHandler* handler = (ConnectionHandler*)event.data.ptr; - int connectionStatus = handler->getConnectionStatus(); - if (connectionStatus == CLOSED) { - _log.info("WORKER: Connection closed"); - delete handler; - return; - } +void Worker::_handleIncomingConnection(struct epoll_event event) { + ConnectionHandler* handler = static_cast(event.data.ptr); handler->processConnection(); + epoll_ctl(_epollSocket, EPOLL_CTL_DEL, event.data.fd, &event); } void* Worker::_workerRoutine(void* ref) { Worker* worker = static_cast(ref); + worker->_threadId = gettid(); + worker->_log.info("WORKER (" + Utils::to_string(worker->_threadId) + + "): Started"); worker->_runEventLoop(); - Server::getInstance().workerFinished(); + worker->_log.info("WORKER (" + Utils::to_string(worker->_threadId) + + "): Finished"); + worker->_server.workerFinished(); return NULL; } diff --git a/src/Worker.hpp b/src/Worker.hpp index 1717b23..e17e597 100644 --- a/src/Worker.hpp +++ b/src/Worker.hpp @@ -6,7 +6,7 @@ /* By: mchenava < mchenava@student.42lyon.fr> +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/22 12:06:51 by mchenava #+# #+# */ -/* Updated: 2024/06/11 15:53:12 by mchenava ### ########.fr */ +/* Updated: 2024/06/25 12:39:00 by mchenava ### ########.fr */ /* */ /* ************************************************************************** */ @@ -21,46 +21,52 @@ #include #include #include +#include #include "ConnectionHandler.hpp" #include "Logger.hpp" #include "Utils.hpp" +#include "Common.hpp" #include "VirtualServer.hpp" +#include "Server.hpp" + #define MAX_EVENTS 10 #define WORKER_TIME_TO_STOP 2 class ConnectionHandler; +class Server; class Worker { private: + Server& _server; pthread_t _thread; Config& _config; Logger& _log; std::map _handlers; - std::map _listenConfigs; std::map > _virtualServers; int _epollSocket; - std::vector _listenSockets; - int _maxConnections; - int _currentConnections; + std::map _listenSockets; + // int _maxConnections; + int _load; bool _shouldStop; + // pthread_mutex_t _queueMutex; static void* _workerRoutine(void* ref); - void _setupEpoll(); std::vector _setupAssociateVirtualServer( const ListenConfig& listenConfig); void _acceptNewConnection(int fd); void _runEventLoop(); - void _handleIncomingConnection(struct epoll_event& event); + void _handleIncomingConnection(struct epoll_event event); public: - Worker(); + int _threadId; + Worker(Server& server, int epollSocket, std::map& listenSockets); ~Worker(); - void assignConnection(int clientSocket, const ListenConfig& listenConfig); void stop(); void start(); + int getLoad(); }; #endif diff --git a/src/main.cpp b/src/main.cpp index c4a0e54..da2f102 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,18 +3,19 @@ /* ::: :::::::: */ /* main.cpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: mchenava +#+ +:+ +#+ */ +/* By: agaley +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/04/28 15:02:12 by agaley #+# #+# */ -/* Updated: 2024/06/20 11:53:58 by mchenava ### ########.fr */ +/* Updated: 2024/06/25 01:13:41 by agaley ### ########lyon.fr */ /* */ /* ************************************************************************** */ #include + +#include "Common.hpp" #include "Config.hpp" #include "ConfigManager.hpp" #include "Server.hpp" -#include "Common.hpp" int main(int argc, char* argv[]) { if (argc != 2 || argv[1] == NULL) @@ -29,7 +30,6 @@ int main(int argc, char* argv[]) { sigaction(SIGTERM, &sigHandler, NULL); sigaction(SIGKILL, &sigHandler, NULL); - //coucouc Config config; try { ConfigManager::loadConfig(argc == 1 ? ConfigManager::DEFAULT_FILE_NAME @@ -46,6 +46,7 @@ int main(int argc, char* argv[]) { Logger::getInstance().info("Starting WebServ"); server.start(); Logger::getInstance().info("Shutdown WebServ"); - delete &Logger::getInstance(); + usleep(SHUTDOWN_DELAY); // Wait for Logger to finish output logs + Logger::deleteInstance(); return EXIT_SUCCESS; }