]> git.seodisparate.com - c_simple_http/commitdiff
Impl. handling HTTP/1.1 requests
authorStephen Seo <seo.disparate@gmail.com>
Fri, 6 Sep 2024 02:53:28 +0000 (11:53 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Fri, 6 Sep 2024 02:56:00 +0000 (11:56 +0900)
TODO:
    Handle errors other than 404 Not Found.

example_config/example.config [new file with mode: 0644]
src/arg_parse.c
src/arg_parse.h
src/http.c
src/http.h
src/main.c

diff --git a/example_config/example.config b/example_config/example.config
new file mode 100644 (file)
index 0000000..06a6fcb
--- /dev/null
@@ -0,0 +1,6 @@
+PATH=/
+HTML='''Test HTML
+{{{Var}}}
+'''
+
+Var='''Test var value'''
index 20e224bb361c0564387fc4d5a6072692459c0026..0ca73cdeb293168bd14296e377d1ba9f522e2589 100644 (file)
@@ -24,6 +24,7 @@
 void print_usage(void) {
   puts("Usage:");
   puts("  -p <port> | --port <port>");
+  puts("  --config=<config_file>");
 }
 
 Args parse_args(int argc, char **argv) {
@@ -42,6 +43,8 @@ Args parse_args(int argc, char **argv) {
       }
       --argc;
       ++argv;
+    } else if (strncmp(argv[0], "--config=", 9) == 0 && strlen(argv[0]) > 9) {
+      args.config_file = argv[0] + 9;
     } else {
       puts("ERROR: Invalid args!\n");
       print_usage();
index a17e6d50156fa055605e3d991b583ba882bc9df4..6e762067d54933f82f2b7f3d9abda0faf2d1bfc7 100644 (file)
@@ -20,6 +20,8 @@
 typedef struct Args {
   unsigned short flags;
   unsigned short port;
+  // Does not need to be free'd, this should point to a string in argv.
+  const char *config_file;
 } Args;
 
 void print_usage(void);
index b6a20772efe6fe1eeaf9b9826d71e4a6aefd296a..a43648ab11c5f564bdb7d1a98a94db7fd7600410 100644 (file)
 #include <string.h>
 #include <stdio.h>
 
+// Third party includes.
+#include <SimpleArchiver/src/helpers.h>
+
 // Local includes
 #include "constants.h"
+#include "http_template.h"
 
 #define REQUEST_TYPE_BUFFER_SIZE 16
 #define REQUEST_PATH_BUFFER_SIZE 256
 char *c_simple_http_request_response(
     const char *request,
     unsigned int size,
-    const C_SIMPLE_HTTP_HTTPTemplates *templates) {
+    const C_SIMPLE_HTTP_HTTPTemplates *templates,
+    size_t *out_size) {
+  if (out_size) {
+    *out_size = 0;
+  }
   // parse first line.
   unsigned int idx = 0;
   char request_type[REQUEST_TYPE_BUFFER_SIZE] = {0};
@@ -102,8 +110,26 @@ char *c_simple_http_request_response(
   fprintf(stderr, "Parsing request: got http protocol \"%s\"\n", request_proto);
 #endif
 
-  // TODO
-  return NULL;
+  if (strcmp(request_type, "GET") != 0) {
+    fprintf(stderr, "ERROR Only GET requests are allowed!\n");
+    return NULL;
+  }
+
+  size_t generated_size = 0;
+  char *generated_buf = c_simple_http_path_to_generated(
+    request_path,
+    templates,
+    &generated_size);
+  if (!generated_buf || generated_size == 0) {
+    fprintf(stderr, "ERROR Unable to generate response html for path \"%s\"!\n",
+      request_path);
+    return NULL;
+  }
+
+  if (out_size) {
+    *out_size = generated_size;
+  }
+  return generated_buf;
 }
 
 // vim: ts=2 sts=2 sw=2
index e4264cd2c1a32e6d6d39f35ac81ee43e1701a499..e87ae0275d336c8e3b2285321c0927b2661b30e5 100644 (file)
@@ -17,6 +17,9 @@
 #ifndef SEODISPARATE_COM_C_SIMPLE_HTTP_HTTP_H_
 #define SEODISPARATE_COM_C_SIMPLE_HTTP_HTTP_H_
 
+// Standard library includes.
+#include <stddef.h>
+
 // Third party includes.
 #include <SimpleArchiver/src/data_structures/hash_map.h>
 
@@ -30,7 +33,8 @@ typedef C_SIMPLE_HTTP_ParsedConfig C_SIMPLE_HTTP_HTTPTemplates;
 char *c_simple_http_request_response(
   const char *request,
   unsigned int size,
-  const C_SIMPLE_HTTP_HTTPTemplates *templates
+  const C_SIMPLE_HTTP_HTTPTemplates *templates,
+  size_t *out_size
 );
 
 #endif
index ae0e1dc234dd58682a7df980a425a198c9710805..c0f83fd978b2cb2e2888727317cc3c7e085329a9 100644 (file)
@@ -27,6 +27,9 @@
 #include <time.h>
 #include <errno.h>
 
+// Third party includes.
+#include <SimpleArchiver/src/helpers.h>
+
 // Local includes.
 #include "arg_parse.h"
 #include "big_endian.h"
 int main(int argc, char **argv) {
   Args args = parse_args(argc, argv);
 
+  if (!args.config_file) {
+    fprintf(stderr, "ERROR Config file not specified!\n");
+    print_usage();
+    return 2;
+  }
+
   printf("%u\n", args.port);
+  printf("config file is: %s\n", args.config_file);
+
+  __attribute__((cleanup(c_simple_http_clean_up_parsed_config)))
+  C_SIMPLE_HTTP_ParsedConfig parsed_config = c_simple_http_parse_config(
+    args.config_file,
+    "PATH",
+    NULL
+  );
 
   __attribute__((cleanup(cleanup_tcp_socket))) int tcp_socket =
     create_tcp_socket(args.port);
@@ -95,12 +112,38 @@ int main(int argc, char **argv) {
         }
       }
       puts("");
-      // TODO Validate request and send response.
-      // TODO WIP
+
+      size_t response_size = 0;
       const char *response = c_simple_http_request_response(
-        (const char*)recv_buf, read_ret, NULL);
+        (const char*)recv_buf, read_ret, &parsed_config, &response_size);
       if (response) {
+        write(connection_fd, "HTTP/1.1 200 OK\n", 16);
+        write(connection_fd, "Allow: GET\n", 11);
+        write(connection_fd, "Content-Type: text/html\n", 24);
+        char content_length_buf[128];
+        size_t content_length_buf_size = 0;
+        memcpy(content_length_buf, "Content-Length: ", 16);
+        content_length_buf_size = 16;
+        int written = 0;
+        snprintf(
+          content_length_buf + content_length_buf_size,
+          127 - content_length_buf_size,
+          "%lu\n%n",
+          response_size,
+          &written);
+        content_length_buf_size += written;
+        write(connection_fd, content_length_buf, content_length_buf_size);
+        write(connection_fd, "\n", 1);
+        write(connection_fd, response, response_size);
+
         free((void*)response);
+      } else {
+        // TODO handle internal errors also.
+        write(connection_fd, "HTTP/1.1 404 Not Found\n", 23);
+        write(connection_fd, "Allow: GET\n", 11);
+        write(connection_fd, "Content-Type: text/html\n", 24);
+        write(connection_fd, "Content-Length: 14\n", 19);
+        write(connection_fd, "\n404 Not Found\n", 15);
       }
       close(connection_fd);
     } else {