#include "request.h" Request* newRequest(){ Request *request = malloc(sizeof(Request)); memset(request, 0, sizeof(Request)); request->method = NULL; request->protocol = NULL; request->host = NULL; request->path = NULL; request->headers = NULL; request->queryString = NULL; request->body = NULL; return request; } void requestFirstLine( Request *req, char line[] ){ char method[20] = {'\0'}; //Get, post, etc. // This may contain the method, the path, the domain and so on char *url = malloc(sizeof(char) *2048); memset(url, '\0', sizeof(char) * 2048); char *currentPos = url; float version = 0; char host[254] = {'\0'}; int port = -1; // 0 is a valid port number, -1 isn't //https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers char path[2000] = {'\0'}; sscanf( line, "%20s %2048s HTTP/%f", method, url, &version ); req->method = strdup(method); req->version = version; //We've pulled out the easy bits. Now to go through the url and pull out what we need int protEnd = strpos(url, "://" ); if ( protEnd > -1 ){ req->protocol = strndup( url, protEnd ); currentPos += protEnd + 3; } else { req->protocol = strdup(""); } sscanf( currentPos, "%253[^:/]", host ); if ( strlen( host ) > 0 ){ currentPos = currentPos + strlen(host); req->host = strdup(host); } else { req->host = strdup(""); } if ( currentPos[0] == ':' ){ currentPos++; sscanf( currentPos, "%i", &port ); req->port = port; currentPos += (int)floor( log10( port ) ) + 1; } else { req->port = -1; } sscanf( currentPos, "%2000[^? ]", path ); if ( strlen( path ) > 0 ){ currentPos += strlen(path); req->path = strdup(path); } else { req->path = strdup(""); } if ( strlen( currentPos ) > 0 ){ req->queryString = strdup( currentPos ); } else { req->queryString = strdup(""); } //We try and work out port and protocol if we don't have them if ( req->port == -1){ if ( strcmp( "https", req->protocol ) == 0 ) req->port = 443; else req->port = 80; } if ( strlen(req->protocol) == 0 ){ free(req->protocol); if ( req->port == 443 ) req->protocol = strdup("https"); else req->protocol = strdup("http"); } free(url); } Request* newRequestFromSocket(int socket){ Request *req = newRequest(); int valread; char line[1024] = {0}; // The first line will give us some important information valread = fdReadLine( socket, line, 1024); requestFirstLine(req, line); //a length of 2 will indicate an empty line which will split the headers //from the body (if there is a body) valread = fdReadLine( socket, line, 1024); while ( valread > 2 ){ requestAddHeader( req, line ); //I believe at this point all the headers are done. valread = fdReadLine( socket , line, 1024); } //TODO: make requests work with a body //contentLength = getHeader( req->headers, "content-length" ); //if ( contentLength != NULL ){ // printf( "Content length is %i\n", atoi(contentLength->value) ); //} return req; } Request* newRequestFromString(char *string){ // We don't want to modify the original string char *str = strdup(string); Request *req = newRequest(); int valread; //Find the new line char *occurance = strchr( str, '\n' ); occurance[0] = '\0'; requestFirstLine(req, str); str = occurance + 1; occurance = strchr( str, '\n' ); occurance[0] = '\0'; while ( strlen(str) > 1 ){ requestAddHeader( req, str ); str = occurance + 1; occurance = strchr( str, '\n' ); occurance[0] = '\0'; } //TODO: make requests work with a body //contentLength = getHeader( req->headers, "content-length" ); //if ( contentLength != NULL ){ // printf( "Content length is %i\n", atoi(contentLength->value) ); //} return req; } char* requestToString( Request *req){ unsigned int fullLength = strlen(req->method) + 1 + sizeof( req->path ) + //11 = [space]http/1.1\r\n sizeof( req->queryString ) + 11 + headerListCharLength( req->headers ); if ( strcmp( req->method, "CONNECT" ) == 0 ) fullLength += sizeof(req->host); char retString[fullLength]; memset( retString, '\0', fullLength ); if ( strcmp( req->method, "CONNECT" ) == 0 ) sprintf(retString, "%s %s HTTP/%.1f\r\n%s\r\n", req->method, req->host, req->version, headersToString(req->headers)); else sprintf(retString, "%s %s%s HTTP/%.1f\r\n%s\r\n", req->method, req->path, req->queryString, req->version, headersToString(req->headers)); // rsp->statusMessage,headersToString(rsp->headers),rsp->body); return strdup(retString); //return strdup(retString); } void requestAddHeader( Request *req, char header[] ){ if ( req->headers == NULL ){ req->headers = malloc(sizeof( HeaderList )); req->headers->header = newHeader( header ); req->headers->next = NULL; } else addHeader( req->headers, header ); } void freeRequest( Request *req ){ if ( req == NULL ) return; free(req->method); free(req->protocol); free(req->host); free(req->path); freeHeaderList( req->headers ); free(req->queryString); free(req->body); free(req); }