#include "callback_http.h" #include #include #include #include "../utils/strings.h" #include "http_headers.h" #include "request_method.h" #include "response_code.h" static const char* SEPS = " \n\r"; #define return_bad_request() { \ args->output = "HTTP/1.1 400 Bad Request"; \ args->output_size = 24; \ return; \ } static void append_header(enum HttpHeader header, const char* value, const char** parts_array, size_t *ind); void callback_http(callback_args* args) { if (args->extra == NULL) { printf("No HTTP callbacks were set!"); return; } http_callbacks *callbacks = args->extra; /* Parse input request */ client_message in_message = { .method = RM_UNKNOWN, .url = NULL, .version = NULL, .headers = { 0 }, }; /** Request method **/ char* word = strtok(args->input, SEPS); if (word == NULL) return_bad_request() for (enum RequestMethod rm = RM_GET; rm < RM_UNKNOWN; rm++) { if (streq(REQUEST_METHOD_NAME[rm], word)) { in_message.method = rm; break; } } if (in_message.method == RM_UNKNOWN) return_bad_request() /** URL **/ word = strtok(NULL, SEPS); if (word == NULL) return_bad_request() in_message.url = word; /** HTTP version **/ word = strtok(NULL, SEPS); if (word == NULL || !streq("HTTP/1.1", word)) return_bad_request() in_message.version = word; /** Headers **/ word = strtok(NULL, ":\n\r"); while(word != NULL) { enum HttpHeader he = 0; while (he < HE_LENGTH) { if (streq(HTTP_HEADER_NAME[he], word)) break; ++he; } word = strtok(NULL, "\n\r"); if (word == NULL) break; if (he < HE_LENGTH) { while (*word == ' ') ++word; in_message.headers[he] = word; } word = strtok(NULL, ":\n\r"); } /* Respond to request */ response_message out_message = { .response_code = RC_500_INTERNAL_SERVER_ERRROR, .headers = { 0 }, .body = NULL, .body_size = 0, .free_body = 0, }; if (in_message.method < RM_UNKNOWN) callbacks->all_callbacks[in_message.method](&in_message, &out_message); else printf("Unsupported method!"); const char* response[1024] = { 0 }; size_t rind = 0; response[rind++] = "HTTP/1.1 "; response[rind++] = RESPONSE_CODE_NAME[out_message.response_code]; response[rind++] = "\n"; for (enum HttpHeader he = 0; he < HE_LENGTH; he++) { if (out_message.headers[he] != NULL) append_header(he, out_message.headers[he], response, &rind); } response[rind++] = "\n"; if (out_message.body != NULL && out_message.body_size > 0) response[rind++] = out_message.body; args->output = concat_array(response, rind, &args->output_size); args->free_output = 1; if (out_message.free_body) free(out_message.body); } static void append_header(enum HttpHeader header, const char* value, const char** parts_array, size_t *ind) { parts_array[(*ind)++] = HTTP_HEADER_NAME[header]; parts_array[(*ind)++] = ": "; parts_array[(*ind)++] = value; parts_array[(*ind)++] = "\n"; }