http.c (2676B)
1 #include "http.h" 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 7 struct http_request * 8 parse_http_request(char *request) { 9 struct http_request *result = malloc(sizeof(struct http_request)); 10 11 if (result == NULL) { 12 return NULL; 13 } 14 15 char *method_string = strtok(request, " "), 16 *path_string = strtok(NULL, " "); 17 18 if (method_string != NULL) { 19 if (strcmp(method_string, "GET") == 0) { 20 result->method = GET; 21 } else if (strcmp(method_string, "HEAD") == 0) { 22 result->method = HEAD; 23 } else { 24 result->method = UNSUPPORTED; 25 } 26 } 27 28 if (path_string != NULL) { 29 strncpy(result->path, 30 path_string, 31 HTTP_REQUEST_PATH_MAX_LENGTH - 1); 32 result->path[HTTP_REQUEST_PATH_MAX_LENGTH - 1] = '\0'; 33 } 34 35 return result; 36 } 37 38 unsigned int 39 get_length_of_integer(unsigned int integer) { 40 unsigned int result = 0; 41 42 while (integer > 1) { 43 integer /= 10; 44 result++; 45 } 46 47 return result; 48 } 49 50 char * 51 compose_http_response_head(struct http_response response) { 52 size_t size; 53 unsigned int status_code = status_map[response.status].code; 54 const char *template = "HTTP/1.1 %u %s\r\n" 55 "Content-Type: %s; charset=UTF-8\r\n" 56 "Content-Length: %u\r\n", 57 *status_message = status_map[response.status].message, 58 *content_type = response.content_type, 59 *body = response.body; 60 char *buffer; 61 62 /* 63 * This is actually a bit inelegant: it adds the length of 'template' 64 * with the length of each component of http_response; it will result 65 * in something bigger than the actual size of the response due to 66 * the template patterns in %, but that is just a few bytes and nobody 67 * really minds it. 68 */ 69 size = strlen(template) 70 + get_length_of_integer(status_code) 71 + strlen(status_message) 72 + strlen(content_type) 73 + get_length_of_integer(strlen(body)); 74 75 buffer = malloc(size); 76 77 snprintf(buffer, size, template, 78 status_code, 79 status_message, 80 content_type, 81 strlen(body)); 82 83 buffer[size] = '\0'; 84 85 return buffer; 86 } 87 88 char * 89 compose_http_response_full(struct http_response response) { 90 size_t size; 91 const char *template = "%s" 92 "\r\n" 93 "%s\n", 94 *head = compose_http_response_head(response), 95 *body = response.body; 96 char *buffer; 97 98 /* 99 * Read the comment inside the compose_http_response_head function in 100 * this same file. 101 */ 102 size = strlen(template) 103 + strlen(head) 104 + strlen(body); 105 106 buffer = malloc(size); 107 108 snprintf(buffer, size, template, 109 head, 110 body); 111 112 buffer[size] = '\0'; 113 114 return buffer; 115 }