Skip to main content
2 of 2
replaced http://cs50.stackexchange.com/ with https://cs50.stackexchange.com/

Pset6 Server.c: 404 Error only when submitting query on hello.html, everything else works

Every time I input a query on the HTML form, I get a 404 Error even though the query appears in the URL, and printf seem to indicate that my Parse function is correctly extracting the right substring. My terminal output is as follows:

gege019@ide50:~/workspace/pset6 $ ./server public
Using /home/ubuntu/workspace/pset6/public for server's root
Listening on port 8080
GET / HTTP/1.1
Abs_path = /
HTTP/1.1 200 OK
GET /hello.html HTTP/1.1
Abs_path = /hello.html
path is /home/ubuntu/workspace/pset6/public/hello.html
type is text/html
Data: <!DOCTYPE html>

<html>
    <head>
        <title>hello</title>
    </head>
    <body>
        <form action="hello.php" method="get">
            <input autocomplete="off" autofocus name="name" placeholder="Name" type="text"/>
            <input type="submit" value="Say Hello"/>
        </form>
    </body>
</html>

Length: 316
HTTP/1.1 200 OK
GET /hello.php?name=gege019 HTTP/1.1
Query = name=gege019
Abs_path = /hello.php?name=gege019
HTTP/1.1 404 Not Found

Regardless, GDB seems to indicate the error is stemming from my parse function (below) but I'll paste my code for all the functions we had to work on just in case you guys have other ideas. I also looked at this previous question but couldn't determine if we're experiencing the same issue. I would sincerely appreciate any help and guidance on this you can provide. I've spent the past 2 months on this pset and would really like to be able to move on, but would feel terrible submitting it in it's current incomplete form. Thank you so much!!

Parse:

bool parse(const char* line, char* abs_path, char* query)
{
     // TODO
    //eg: GET /hello.php?name=test HTTP/1.1 

    //accept only GET as method
    if (strncmp("GET ", line, 4) != 0)
    {
        error(405);
        return false;
    }

    //check that only 2 spaces in request-line 
    char* space = strchr(line,' ');

    if (space == NULL)
    {
        error(400);
        return false; 
    }

    int i = 0;
    while (space != NULL)
    {
    
        //check for '/' after first space i.e. request-target starts with /
         if (i == 0)
         {
     
            if (strncmp(" /", space, 2) != 0)
            {
                error(501);
                return false;
            }
        
            //check for '"' in request-target and after 2nd space
            if (strchr(space, '"') != NULL && (strchr(space+1,' ') != NULL && strchr(strchr(space+1,' '), '"') != NULL ))
            {
                error(400);
                return false;
            }
        
            //assuming '?name=variable' can only come after ".php"
           //"GET /hello.php?q=test HTTP/1.1\r\n"
           int n = strlen(space+1) - strlen(strchr(space+1,' '));
           char numq[n + 1];
           // numq = "/hello.php?q=test"
           strncpy(numq, space+1, n);
           numq[n] = '\0';

           if (strchr(numq, '?') != NULL)
           {
              // only ".php" can have query
              if (strstr(numq, ".php") == NULL)
              {
                  error(400);
                  return false;
              }
          
              //verify that '?'comes right after ".php"
             char* numq3 = strstr(numq, ".php" );
             // '.php?name=variable'
         
             if (strncmp(".php?", numq3, 5) !=0)
             {
                  error(400);
                  return false;
             }
         
             //store query "name=variable" in char* query
            strcpy(query, (strchr(numq, '?' ) + 1));
            printf("Query = %s\n",query);
         
           }   
        
            //if ".php" file type but no query, then set query to " "
            else if (strstr(numq, ".php") != NULL)
              {
                  //set query to " " ie '\0'
                  strcpy(query, (strstr(numq, ".php" ) + 1));
                  printf("Query = %s\n",query);
              }
         }
   
        if (i == 1) 
        {
             //check for 'HTTP' after 2nd space
            if (strncmp(" HTTP", space, 5) != 0)
            {
            error(400);
            return false;
            }
        
            //check for CRLF
            if (strstr(space,"\r\n\0") == NULL)
            {
               error(400);
                return false;
            }

            //store abs path in abs_path
            int p = strlen(strchr(line,' ') + 1) - strlen(space);
            strncpy(abs_path, strchr(line,' ') + 1, p);
            abs_path[p] = '\0';
            printf("Abs_path = %s\n", abs_path);
        
        }
    
        i++;
        space = strchr(space+1, ' ');
    }


    //check for at most 2 spaces
    if (i != 2)
    {
        error(400);
        return false; 
    }

    return true;
}

Lookup:

const char* lookup(const char* path)
{
    // TODO
    //find the last 'dot'
    char* dot = strrchr(path,'.');

    if (path != NULL)
    {
        if (strcasecmp(dot,".css") == 0)
        {
            return "text/css";
        }
    
         if (strcasecmp(dot,".html") == 0)
        {
            return "text/html";
        }
         if (strcasecmp(dot,".gif") == 0)
        {
            return "image/gif";
        }
         if (strcasecmp(dot,".ico") == 0)
        {
            return "image/x-icon";
        }
         if (strcasecmp(dot,".jpg") == 0)
        {
            return "image/jpeg";
        }
         if (strcasecmp(dot,".js") == 0)
        {
            return "text/javascript";
        }
         if (strcasecmp(dot,".php") == 0)
        {
            return "text/x-php";
        }
         if (strcasecmp(dot,".png") == 0)
        {
            return "image/png";
        }
    
    }
    return NULL;
}

Load:

bool load(FILE* file, BYTE** content, size_t* length)
{

    if (*content == NULL)
    {
        return false;
    }
    char* buffer = malloc(sizeof(char));
    if(buffer == NULL) 
    {
        return false; 
    }

    int counter = 0;
    int c = fgetc(file);

    while(c != EOF)
    {
    
        buffer[counter] = (char) c;
        counter++;
        buffer = (char*) realloc(buffer, counter+1);
        c = fgetc(file);

    *content = buffer; // stores the address of the first of those bytes
    *length = counter;     // stores the number of bytes
    printf("Data: %s\n", *content);     // debugging - this works
    printf("Length: %zu\n", *length);   // debugging - this works
    return true;
}

Indexes

char* indexes(const char* path)
{
     //malloc space to contain directory path + index file name + null terminator
    char* buffer = malloc(sizeof(char) * (strlen(path) + strlen("/index.html") + 1));
    strcpy(buffer, path);
    strcat(buffer,"/index.php");

    FILE* fp = (fopen(buffer, "r"));
    if (fp != NULL)
    {
        return buffer;
    }
    strcpy(buffer, path);
    strcat(buffer,"/index.html");

    if (fp != NULL)
    {
        return buffer;
    }
    free(buffer);
    return NULL;

}