#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"); if ( contentLengthHeader == NULL ){ responseAddHeader( rsp, "content-length: 0" ); 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); }