Commit 85da7ff9b70f15db69001235d77d94a290038a55

Thomas de Grivel 2024-09-12T14:00:42

wip http_request_buf_parse_method

diff --git a/http/http_request.c b/http/http_request.c
index 53d645a..c8d7dfb 100644
--- a/http/http_request.c
+++ b/http/http_request.c
@@ -15,62 +15,59 @@
 #include "http.h"
 #include "url.h"
 
-const s_sym ** http_request_buf_parse_method (s_buf *buf,
-                                              const s_sym **dest)
+s_tag * http_request_buf_parse_method (s_buf *buf, s_tag *dest)
 {
-  s_tag allowed_methods;
-  s_list *m;
+  const s_list *allowed_methods;
+  s_tag allowed_methods_tag;
+  bool b;
   s_ident ident;
-  sw r;
   s_buf_save save;
   s_str str;
-  const s_sym *sym;
+  s_tag tmp = {0};
   assert(buf);
   assert(dest);
   ident_init(&ident, sym_1("HTTP.Request"), sym_1("allowed_methods"));
-  if (! ident_get(&ident, &allowed_methods)) {
+  if (! ident_get(&ident, &allowed_methods_tag)) {
     err_puts("http_request_buf_parse_method: missing"
              " HTTP.Request.allowed_methods");
     assert(!("http_request_buf_parse_method: missing"
              " HTTP.Request.allowed_methods"));
     return NULL;
   }
-  if (allowed_methods.type != TAG_LIST) {
+  if (allowed_methods_tag.type != TAG_LIST ||
+      ! allowed_methods_tag.data.list ||
+      allowed_methods_tag.data.list->tag.type != TAG_SYM) {
     err_puts("http_request_buf_parse_method: invalid"
              " HTTP.Request.allowed_methods");
     assert(!("http_request_buf_parse_method: invalid"
              " HTTP.Request.allowed_methods"));
     return NULL;
   }
+  allowed_methods = allowed_methods_tag.data.list;
   buf_save_init(buf, &save);
-  m = allowed_methods.data.list;
-  while (m) {
-    if (m->tag.type != TAG_SYM) {
-      err_puts("http_request_buf_parse_method: invalid"
-               " HTTP.Request.allowed_methods");
-      assert(!("http_request_buf_parse_method: invalid"
-               " HTTP.Request.allowed_methods"));
-      goto restore;
-    }
-    sym = m->tag.data.sym;
-    str_init_alloc(&str, sym->str.size + 1);
-    memcpy(str.free.pchar, sym->str.ptr.pchar, sym->str.size);
-    str.free.pchar[sym->str.size] = ' ';
-    str.free.pchar[sym->str.size + 1] = 0;
-    if ((r = buf_read_str(buf, &str)) < 0) {
-      err_puts("http_request_buf_parse_method: buf_read_str");
-      goto restore;
-    }
-    str_clean(&str);
-    if (r) {
-      *dest = sym;
-      buf_save_clean(buf, &save);
-      return dest;
-    }
-    m = list_next(m);
+  if (! buf_read_until_1_into_str(buf, " ", &str)) {
+    err_puts("http_request_buf_parse_method: buf_read_until_1_into_str");
+    goto restore;
+  }
+  if (! (tmp.data.sym = sym_find(&str))) {
+    tmp.type = TAG_STR;
+    tmp.data.str = str;
+    buf_save_clean(buf, &save);
+    *dest = tmp;
+    return dest;
+  }
+  str_clean(&str);
+  tmp.type = TAG_SYM;
+  if (! list_has(&allowed_methods, &tmp, &b)) {
+    err_puts("http_request_buf_parse_method: list_has");
+    goto restore;
+  }
+  if (! b) {
+    tmp.type = TAG_STR;
+    tmp.data.str = tmp.data.sym->str;
   }
-  *dest = &g_sym_Void;
   buf_save_clean(buf, &save);
+  *dest = tmp;
   return dest;
  restore:
   buf_save_restore_rpos(buf, &save);
@@ -90,10 +87,10 @@ s_tag * http_request_buf_parse (s_tag *req, s_buf *buf)
   assert(buf);
   buf_save_init(buf, &save);
   if (! http_request_buf_parse_method(buf, &tmp_req.method))
-    goto restore;
+    goto clean;
   if (true) {
     err_write_1("http_request_buf_parse: method: ");
-    err_inspect_sym(&tmp_req.method);
+    err_inspect_tag(&tmp_req.method);
     err_write_1("\n");
   }
   if (! buf_read_until_1_into_str(buf, " ", &url)) {
@@ -150,6 +147,7 @@ sw http_request_buf_write (s_http_request *req, s_buf *buf)
 {
   s_tag *key;
   s_list *list;
+  const s_str *method;
   sw r;
   sw result = 0;
   s_str str;
@@ -157,7 +155,19 @@ sw http_request_buf_write (s_http_request *req, s_buf *buf)
   s_tag *value;
   assert(req);
   assert(buf);
-  if (! req->method->str.size) {
+  switch (req->method.type) {
+  case TAG_SYM:
+    method = &req->method.data.sym->str;
+    break;
+  case TAG_STR:
+    method = &req->method.data.str;
+    break;
+  default:
+    err_puts("http_request_buf_write: invalid method");
+    assert(! "http_request_buf_write: invalid method");
+    return -1;
+  }
+  if (! method->size) {
     err_puts("http_request_buf_write: invalid method: \"\"");
     return -1;
   }    
@@ -173,12 +183,8 @@ sw http_request_buf_write (s_http_request *req, s_buf *buf)
     err_puts("http_request_buf_write: invalid headers: not an AList");
     return -1;
   }
-  if (! str_init_to_upper(&str, &req->method->str))
-    return -1;
-  if ((r = buf_write_str(buf, &str)) < 0) {
-    str_clean(&str);
+  if ((r = buf_write_str(buf, method)) < 0)
     return r;
-  }
   result += r;
   str_clean(&str);
   if ((r = buf_write_1(buf, " ")) <= 0)
diff --git a/http/http_request.h b/http/http_request.h
index a846d70..4c5b905 100644
--- a/http/http_request.h
+++ b/http/http_request.h
@@ -15,8 +15,9 @@
 
 #include "types.h"
 
-s_http_request * http_request_buf_parse (s_http_request *req, s_buf *buf);
-const s_sym ** http_request_buf_parse_method (s_buf *buf,
-                                              const s_sym **dest);
+s_http_request * http_request_buf_parse (s_http_request *req,
+                                         s_buf *buf);
+s_tag *          http_request_buf_parse_method (s_buf *buf,
+                                                s_tag *dest);
 
 #endif /* HTTP_REQUEST_H */
diff --git a/http/types.h b/http/types.h
index 390bf1b..c9812d1 100644
--- a/http/types.h
+++ b/http/types.h
@@ -35,7 +35,7 @@ struct socket_buf {
 };
 
 struct http_request {
-  const s_sym *method;
+  s_tag method;
   s_str url;
   s_str protocol;
   s_list *headers;
diff --git a/lib/kc3/0.1/http/request.kc3 b/lib/kc3/0.1/http/request.kc3
index e972dcc..af96c6a 100644
--- a/lib/kc3/0.1/http/request.kc3
+++ b/lib/kc3/0.1/http/request.kc3
@@ -1,6 +1,6 @@
 defmodule HTTP.Request do
 
-  defstruct [method: :get,
+  defstruct [method: ?,
              url: "/",
              protocol: "HTTP/1.1",
              headers: []]