0

When using Check50 on server.c, I get this result:

:) server.c exists 

:) server compiles 

:) HTTP/1.0 returns error code 505 

:( Method of 'abcGET' returns error code 405

    \ expected output, but not "HTTP/1.1 404 Not Found\r\nContent-Type:..." 

:( Method of 'GETabc' returns error code 405

    \ expected output, but not "HTTP/1.1 404 Not Found\r\nContent-Type:..."

:( request-target without starting '/' returns error code 501

    \ expected output, but not "HTTP/1.1 404 Not Found\r\nContent-Type:..."

:( request-target of abc/hello.php returns error code 501

    \ expected output, but not "HTTP/1.1 404 Not Found\r\nContent-Type:..."

:( Requesting cat.exe returns error code 501

    \ expected output, but not "HTTP/1.1 404 Not Found\r\nContent-Type:..."

:) Requesting non-existant file returns error code 404

:( Requesting request-target with " returns error code 400

    \ expected output, but not "HTTP/1.1 404 Not Found\r\nContent-Type:..."

:) Two spaces after GET returns error code

:) A space within the request target returns error code

:) Two spaces before HTTP/1.1 returns error code

This is my code for parse():

bool parse(const char* line, char* abs_path, char* query)
{
    char* method;
    char* version;
    for (int i = 0, n = strlen(line); i < n; i++)
    {
        for (int j = 0; j < n - 1; j++)
        {
            method = strstr(line, "GET");
            if (method == NULL)
            {
                error(405);
                return false;
            }

            version = strstr(line, "HTTP/1.1");
            if (version == NULL)
            {
                error(505);
                return false;
            }

            char* temp_path = strchr(line, '/');
            if (temp_path == NULL)
            {
                error(501);
                return false;
            }
            int index = 0;
            for (int length = strlen(temp_path); index < length; index++)
            {
                if (temp_path[index] == ' ')
                {
                    break;
                }
            }
            strncpy(abs_path, temp_path, index);
            abs_path[index - 1] = '\0';
        }
    }



    return true;
}

So what am I doing wrong? Any help would be appreciated.

0

As they say in the real estate biz, "Location, location, location".

Recall from the specification:

Per 3.1.1 of http://tools.ietf.org/html/rfc7230, a request-line is defined as

method SP request-target SP HTTP-version CRLF

wherein SP represents a single space ( ) and CRLF represents \r\n. None of method, request-target, and HTTP-version, meanwhile, may contain SP.

Let's see what happens when check50 tests for Method of 'abcGET'...

This block:

method = strstr(line, "GET");
          if (method == NULL)
            {
                error(405);
                return false;
            }

asks "Does line contain the string GET?" When it encounters abcGET the result is non-NULL. The missing piece is location. The method has to be the first "thing" in request-line. (AND must be followed by a space). This test :( Method of 'GETabc' returns error code 405 fails for the same reason.

Similarly, this test :( request-target of abc/hello.php returns error code 501 fails because of this code:

char* temp_path = strchr(line, '/');
        if (temp_path == NULL)
        {
            error(501);
            return false;
        }

Again, "Does line contain a '/'?" The answer is non-NULL, so the program continues. And remember, since a valid version is HTTP/1.1, that test is more likely than not always non-NULL, and probably explains this error :( request-target without starting '/' returns error code 501 too.

This test Requesting cat.exe returns error code 501 fails because abs_path is not terminated properly. But, you say, I have added the null terminator here abs_path[index - 1] = '\0';!!! Indeed you have. But where is "here"? It's off by one. In the case of /cat.exe, abs_path will be /cat.ex. You might to go through it on paper to see why. Now might be a good time to get cozy with debug50 or gdb. It usually takes a bit of practice, patience and perseverance but using a debugger is an invaluable skill for every programmer.

It is really important that you figure out on your own why this test :( Requesting request-target with " returns error code 400 fails.

Obviously this function is not done since query is never built. And I question what is the purpose/point of the i and j loops? They appear to add significant run time ( O(n^2) ), but no value.

ADDENDUM

Guide for using gdb (assuming a problem in the "method test" based on comment after code changes). You will need two terminal sessions. It is also helpful to have the source code open in a third tab, I find it easier to follow than using l in gdb. It is infinitely easier (especially in the beginning) to test server with a curl request instead of a browser request. Key point: if gdb is not doing anything, it's waiting for a request; if curl is not doing anything it's waiting for gdb.

  1. In terminal 1, start gdb ./server
  2. (gdb) break parse
  3. (gdb) run ./public
  4. In terminal 2, issue a curl request to hello.html curl -i http://localhost:8080/hello.html. It won't do anything, assume gdb is at the parse breakpoint.
  5. Back in terminal 1, time to next through parse and let the troubleshooting begin!

(NB from the comment: this run 80 abc/hello.php is equivalent to ./server 80 abc/hello.php. It should be obvious why that is incorrect.)

1
  • Comments are not for extended discussion; this conversation has been moved to chat.
    – kzidane
    Dec 11 '16 at 20:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .