/make-42-webserv-great-again

A guide on how to manually test your "42 Coding School" project "webserv" (October 2022) and a beta version of an automated tester.

Primary LanguageC++

make-42-webserv-great-again

A guide on how to manually test your "42 Coding School" project "webserv" (October 2022) and a beta version of an automated tester.

Table of contents


How to manually send a specific HTTP request

There are many tools that you can use to send specific HTTP requests to test how your server responds. To name some of them there are curl, netcat and postman which are all available on the schools iMacs.

Curl

Curl is a command-line utility for transferring data from or to a server.

The -X option lets you define the request method (by default it is GET)
The -H option lets you add, replace or remove request header fields (curl adds some by default)
The --data option lets you add a request body.
The --resolve option allows you to internally redirect the requests for a host to an IP address. You can use this to be able to send requests to hosts other than 127.0.0.1 or localhost.

Here are a few examples of how to use it:

curl -X POST -H "Content-Type: plain/text" --data "request body text" http://localhost:8080/new_file.txt

curl --resolve www.webserv.com:8080:127.0.0.1 http://www.webserv.com:8080/

curl --resolve webserv.com:80:127.0.0.1 http://webserv.com/index.html (port 80 is the default port for HTTP)

Netcat

Netcat is a computer networking utility for reading from and writing to network connections using TCP or UDP. You can use it to send a freely written request to your server. This is nice beacuse this way you could also send invalid requests. An easy way of using netcat is to echo your custom request and pipe it into netcat as follows:

echo "GET / HTTP/1.1\r\nHost: webserv\r\n\r\n" | nc localhost 8080

Postman

Postman is an API platform for building and using APIs. You can use it to send requests to your server. Download it to to your school iMac via the "Managed Software Center".

Click on the plus to create a new request.

grafik

Select the method, enter a url and add a request body and / or header fields (note that there are some hidden default header fileds, that can be removed if needed).

grafik

After the request got received, the status code is shown and you can check out its header fileds and body.

grafik




How to perform a stress test

Siege is a HTTP load test and benchmark utility and can be used to stress a web server. If you use it with the -b option it will send the request without delays in between and until you exit it (e.g. with ctrl+c). It will then show a summary of the test where you can see the availability. The evaluation sheet asks for an availibility > 99.5%.

For example the command:

siege -b http://localhost:8080/empty.html

could give you an output similar to this one:

image

How to install siege

You can install siege on the school iMacs by using brew, as described below.

Install brew

The following command installs brew and adds the path to its binary to .zshrc, so it can be used without the path. If you want to use it in bash, replace "zsh" with "bash".

rm -rf $HOME/.brew && git clone --depth=1 <https://github.com/Homebrew/brew> $HOME/.brew && echo 'export PATH=$HOME/.brew/bin:$PATH' >> $HOME/.zshrc && source $HOME/.zshrc && brew update

Install siege

To install siege you need brew. Use the command brew install siege. If you get "Error: Xcode alone is not sufficient on Catalina." install the xcode Command Line Tools with xcode-select --install. This will open the following installation window:

screenshot

Click on install -> aggree -> done and then use brew install siege again.


Automated tester

The automated tester is kind of a beta version (private tester made public) and lacks a lot of testing and errorhandling, but I guess it can be usefull anyway. Because some tests depend on the implementation of the server it is also possible that the behaviour of your server might be correct although the tester marks it as wrong or vice versa.

The tester will send different requests (test cases) to your server and compare the response it receives (for the custom tests it is the entire response, for the others it's only the response body) with the "expected outcome string". There are three stages of comparison. As soon as a comparison for a test case succeeds, no further comparisons for this test case will be made.
In the first stage the tester checks for an exact match between the response body and the expected result. On success the tester shows "OK". If it is not an exact match the expected result string gets interpreted as status code (if possible) and gets checked against the response's status code. On success the tester shows "OK status code: " followed by the status code. For the last stage of comparison the response body is checked for an occurrence of the "expected outcome string". If it is found the tester shows "OK found: " followed by the found string. This comparison is very unexact, therefore the "expected output string" should be as special as possible to lower the change of false positives. If none of the comparisons succeeds, the tester will show "KO" followed by the received response.

The output looks like this:
image
The blue text shows the file and line number of the test case. You can press the command key and left-click on it to jump there.

On each run the tester will create the following directory structure within make-42-webserv-great-again/server/ and delete it afterwards:

root/
├── dir/
│   ├── %file
│   ├── custom/
│   ├── index/
│   │   ├── custom/
│   │   │   └── custom.html
│   │   ├── index.html
│   │   └── no/
│   │       ├── autoindex/
│   │       ├── no_autoindex/
│   │       └── no_permission_dir/
│   ├── no_permission_dir/
│   │   ├── file
│   │   └── file.cgi
│   ├── one/
│   │   ├── custom.html
│   │   └── two/
│   │       └── index.html
│   ├── permission_dir/
│   │   ├── .cgi
│   │   ├── file
│   │   ├── file.cgi
│   │   └── no_permission_file
│   └── uploads/
│       ├── file.cgi
│       ├── no_permission_dir/
│       │   └── file
│       ├── no_permission_file
│       └── no_permission_file.cgi
├── index.html
├── server1/
│   ├── custom/
│   │   └── custom.html
│   ├── file
│   └── file.cgi
└── server2/
    ├── file
    └── file.cgi

Setup

Clone the "make-42-webserv-great-again" repository into the root directory of your "webserv" repository.

Create a configuration file with the following settings:

 Virtual Server 0

  server_name: webserv
  port: 80
  root: make-42-webserv-great-again/server/root/
  max_body_size: 100
  autoindex: false
  index_page: index.html
  cgi .cgi: should be executed using the executable "make-42-webserv-great-again/server/cgi_bin/cgi".

  route /route/
   allowed methods: GET
   routed to: make-42-webserv-great-again/server/root/dir/

  route /route/one/
   allowed methods: GET
   index_page: custom.html
   routed to: make-42-webserv-great-again/server/root/dir/one

  route /route/one/two/
   allowed methods: GET
   index_page: index.html
   routed to: make-42-webserv-great-again/server/root/dir/index/

  route /uploads/
   allowed methods: GET, POST, DELETE
   routed to: make-42-webserv-great-again/server/root/dir/uploads/

  route /index/
   allowed methods: GET
   routed to: make-42-webserv-great-again/server/root/dir/index/

  route /index/no/autoindex/
   allowed methods: GET
   autoindex: true
   routed to: make-42-webserv-great-again/server/root/dir/index/no/autoindex/

  route /index/no/no_autoindex/
   allowed methods: GET
   autoindex: false
   routed to: make-42-webserv-great-again/server/root/dir/index/no/no_autoindex/

  route /index/custom/
   allowed methods: GET
   index_page: custom.html
   routed to: make-42-webserv-great-again/server/root/dir/index/custom/

 Virtual Server 1

  server_name: server1
  port: 6000
  root: make-42-webserv-great-again/server/root/server1/
  error_page 404: make-42-webserv-great-again/server/root/server1/custom/custom.html
  cgi .cgi: should be executed using the executable "make-42-webserv-great-again/server/cgi_bin/no_permission_cgi".

 Virtual Server 2

  server_name: server2
  port: 8080, 8081
  root: make-42-webserv-great-again/server/root/server2/
  cgi .cgi: should be executed using the executable "doesntexist".

  route /
   allowed methods: none
   autoindex: false
  route /route/
   allowed methods: GET POST

Relation of subject expression to the used keywords:

"default error page" = error_page
"client body size" = max_body_size
"directory listing" = autoindex (true / false)
"default file to answer if the request is a directory" = index_page (the name of the file)



How to launch

Start your server with the configuration described in Setup and use make run in the command line from the root of the "make-42-webserv-great-again" repository.


How to customize

To add, remove or change test cases, edit the corresponding file within the root of the "make-42-webserv-great-again" repository, as described below. To add, remove or change the known host:port combinations for the tester, edit the file 0_hosts.cpp as follows: add_host("uri-host", "port");

Modify custom tests

For the custom tests a simple client is used to send a request. You can for example use it to send invalid requests or requests with certain (invalid) header fields. Edit the file 1_custom.cpp as follows: custom_test("HTTP request", "expected resonse or status code", FILE_LINE);

The default port for the custom requests is port 80. Make sure your server is listening on it, or change it by editing uint16_t g_port_for_custom_requests = 80;

Modify GET request tests

For the GET request tests the libcurl API is used to send a GET request to the url of your choice. Header fields get added automatically. Edit the file 2_get.cpp as follows: GET_test("url", "expected resonse body or status code", FILE_LINE);

Modify POST request tests

For the POST request tests the libcurl API is used to send a POST request with the body: "This is my POST body with length of 39.", to the url of your choice. Header fields get added automatically. Edit the file 3_post.cpp as follows: POST_test("url", "expected resonse body or status code", FILE_LINE);

Modify DELETE request tests

For the DELETE request tests the libcurl API is used to send a DELETE request to the url of your choice. Header fields get added automatically. Edit the file 4_delete.cpp as follows: DELETE_test("url", "expected resonse body or status code", FILE_LINE);