You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
205 lines
5.0 KiB
205 lines
5.0 KiB
#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); |
|
} |
|
|
|
|
|
|