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.
130 lines
3.5 KiB
130 lines
3.5 KiB
#include "response.h" |
|
|
|
Response* newResponse(){ |
|
Response *response = malloc( sizeof( Response ) ); |
|
memset(response, 0, sizeof(Response)); |
|
response->headers = NULL; |
|
response->statusMessage = NULL; |
|
response->body = NULL; |
|
return response; |
|
} |
|
|
|
void responseBarebones(Response *rsp){ |
|
rsp->headers = malloc( sizeof( HeaderList ) ); |
|
rsp->headers->header = newHeader("Content-Length: 0"); |
|
rsp->headers->next = NULL; |
|
addHeader(rsp->headers, "Content-Type: text/plain"); |
|
rsp->statusCode = 200; |
|
rsp->statusMessage = strdup("OK"); |
|
rsp->version = 1.1; |
|
} |
|
|
|
void connectionEstablished(Response *rsp){ |
|
rsp->statusCode = 200; |
|
rsp->statusMessage = strdup("Connection Established"); |
|
rsp->version = 1.1; |
|
} |
|
|
|
char* responseToString( Response *rsp ){ |
|
// HTTP/x.x xxx OK \r\n |
|
int fullLength = 13 + strlen(rsp->statusMessage) + 2 + |
|
// Headers \r\n\r\n |
|
headerListCharLength(rsp->headers) + 4; |
|
|
|
if ( rsp->body != NULL ) fullLength += strlen(rsp->body) + 2; |
|
|
|
char retString[fullLength]; |
|
|
|
|
|
sprintf(retString, "HTTP/%.1f %3d %s\r\n%s\r\n", rsp->version, rsp->statusCode, |
|
rsp->statusMessage,headersToString(rsp->headers)); |
|
|
|
if ( rsp->body != NULL ) sprintf(retString + strlen(retString), "%s\r\n", (char *)rsp->body); |
|
|
|
return strdup(retString); |
|
} |
|
|
|
void responseSetBody(Response *rsp, char *string, bool updateContentLength){ |
|
rsp->body = strdup(string); |
|
|
|
|
|
if ( updateContentLength ){ |
|
Header *contentLengthHeader = getHeader(rsp->headers, "content-length"); |
|
char *value = malloc(sizeof(char) * 20); |
|
sprintf(value, "%lu", strlen(string) ); |
|
contentLengthHeader->value = strdup(value); |
|
} |
|
} |
|
|
|
void responseAddHeader(Response *rsp, char header[]){ |
|
if ( rsp->headers == NULL ){ |
|
rsp->headers = malloc(sizeof( HeaderList )); |
|
rsp->headers->header = newHeader( header ); |
|
rsp->headers->next = NULL; |
|
} else |
|
addHeader( rsp->headers, header ); |
|
|
|
} |
|
|
|
void responseFirstLine( Response *rsp, char line[] ){ |
|
// HTTP/1.1 200 OK |
|
float version = 0; |
|
int statusCode = 0; |
|
char statusMessage[256] = {'\0'}; |
|
|
|
sscanf( line, "HTTP/%f %i %255[^\n]", &version, &statusCode, statusMessage ); |
|
rsp->version = version; |
|
rsp->statusCode = statusCode; |
|
rsp->statusMessage = strdup(statusMessage); |
|
} |
|
|
|
Response* newResponseFromSocket(int socket){ |
|
Response *rsp = newResponse(); |
|
int valread; |
|
char line[1024] = {0}; |
|
Header *contentLength = NULL; |
|
unsigned int bodySize = 0, bodyRead = 0; |
|
|
|
valread = fdReadLine( socket, line, 1024); |
|
|
|
responseFirstLine(rsp, 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 ){ |
|
responseAddHeader( rsp, line ); |
|
valread = fdReadLine( socket , line, 1024); |
|
} |
|
//I believe at this point all the headers are done. |
|
contentLength = getHeader( rsp->headers, "content-length" ); |
|
|
|
if ( contentLength != NULL ){ |
|
bodySize = atoi( contentLength->value ); |
|
if (bodySize > 0){ |
|
//When the body is not binary data, it is useful to treat it as a |
|
//string. For this reason, I want the bite immediately after it to |
|
//be \0 |
|
rsp->body = malloc( bodySize + 1 ); |
|
memset( rsp->body + bodySize + 1, '\0', 1 ); |
|
while ( bodyRead < bodySize ){ |
|
valread=read( socket, rsp->body + bodyRead, bodySize - bodyRead ); |
|
if (valread < 0){ |
|
perror("Unable to read"); |
|
return NULL; |
|
} |
|
bodyRead += valread; |
|
} |
|
} |
|
} |
|
|
|
|
|
return rsp; |
|
} |
|
|
|
void freeResponse( Response *rsp ){ |
|
free(rsp->statusMessage); |
|
freeHeaderList( rsp->headers ); |
|
free(rsp->body); |
|
free(rsp); |
|
}
|
|
|