Commit bc28a61ef8ce5783e82543e651b440d9dd8c8b90

Thomas de Grivel 2024-11-04T15:29:30

http sessions

diff --git a/http/http_request.c b/http/http_request.c
index cd705e6..51c0255 100644
--- a/http/http_request.c
+++ b/http/http_request.c
@@ -24,6 +24,7 @@ s_tag * http_request_buf_parse (s_tag *req, s_buf *buf)
   uw          content_length_uw = 0;
   s_str      *content_type = NULL;
   const s_str content_type_str = {{NULL}, 12, {"Content-Type"}};
+  const s_str cookie_str = {{NULL}, 6, {"Cookie"}};
   s_str *key;
   s_str line;
   s_tag method_key = {0};
@@ -93,8 +94,10 @@ s_tag * http_request_buf_parse (s_tag *req, s_buf *buf)
       tag_clean((*tail)->tag.data.tuple.tag + 1);
       tag_init_uw((*tail)->tag.data.tuple.tag + 1, content_length_uw);
     }
-    if (! compare_str_case_insensitive(&content_type_str, key))
+    else if (! compare_str_case_insensitive(&content_type_str, key))
       content_type = value;
+    else if (! compare_str_case_insensitive(&cookie_str, key))
+      http_request_cookie_add(&tmp_req, value);
     tail = &(*tail)->next.data.list;
   }
   if (content_length_uw) {
@@ -110,7 +113,7 @@ s_tag * http_request_buf_parse (s_tag *req, s_buf *buf)
         ! compare_str_case_insensitive(&urlencoded, content_type)) {
       if (! url_www_form_decode(body_str, &body))
         goto restore;
-      if (true) {
+      if (false) {
         err_write_1("http_request_buf_parse: body: ");
         err_inspect_tag(&body);
         err_write_1("\n");
@@ -269,6 +272,57 @@ sw http_request_buf_write (s_http_request *req, s_buf *buf)
   return result;
 }
 
+s_http_request * http_request_cookie_add (s_http_request *req,
+                                          s_str *cookies)
+{
+  sw eq_pos;
+  s_list *s;
+  const s_str  separator = {{NULL}, 2, {"; "}};
+  s_list *split;
+  s_list **tail;
+  s_tuple *tuple;
+  tail = list_tail(&req->cookies);
+  if (! str_split(cookies, &separator, &split))
+    return NULL;
+  s = split;
+  while (s) {
+    if (s->tag.type != TAG_STR) {
+      err_puts("http_request_cookie_add: not a Str");
+      assert(! "http_request_cookie_add: not a Str");
+      goto ko;
+    }
+    if ((eq_pos = str_position_1(&s->tag.data.str, "=")) < 0)
+      goto next;
+    if (! (*tail = list_new_tuple(2, NULL))) {
+      err_puts("http_request_cookie_add: list_new_tuple");
+      assert(! "http_request_cookie_add: list_new_tuple");
+      goto ko;
+    }
+    tuple = &(*tail)->tag.data.tuple;
+    tuple->tag[0].type = TAG_STR;
+    tuple->tag[1].type = TAG_STR;
+    if (! str_init_slice(&tuple->tag[0].data.str, &s->tag.data.str,
+                         0, eq_pos)) {
+      err_puts("http_request_cookie_add: str_init_slice 1");
+      assert(! "http_request_cookie_add: str_init_slice 1");
+      goto ko;
+    }
+    if (! str_init_slice(&tuple->tag[1].data.str, &s->tag.data.str,
+                         eq_pos + 1, -1)) {
+      err_puts("http_request_cookie_add: str_init_slice 2");
+      assert(! "http_request_cookie_add: str_init_slice 2");
+      goto ko;
+    }
+  next:
+    s = list_next(s);
+  }
+  list_delete_all(split);
+  return req;
+ ko:
+  list_delete_all(split);
+  return NULL;
+}
+
 s_tag * http_request_method_from_str (const s_str *str, s_tag *dest)
 {
   const s_list *allowed_methods;
diff --git a/http/http_request.h b/http/http_request.h
index 3e8f113..5e1d670 100644
--- a/http/http_request.h
+++ b/http/http_request.h
@@ -15,8 +15,12 @@
 
 #include "types.h"
 
-s_tag * http_request_buf_parse (s_tag *req, s_buf *buf);
-s_tag * http_request_buf_parse_method (s_buf *buf, s_tag *dest);
-s_tag * http_request_method_from_str (const s_str *str, s_tag *dest);
+s_tag *          http_request_buf_parse (s_tag *req, s_buf *buf);
+s_tag *          http_request_buf_parse_method (s_buf *buf,
+                                                s_tag *dest);
+s_http_request * http_request_cookie_add (s_http_request *req,
+                                          s_str *cookies);
+s_tag *          http_request_method_from_str (const s_str *str,
+                                               s_tag *dest);
 
 #endif /* HTTP_REQUEST_H */
diff --git a/http/types.h b/http/types.h
index ec9d93c..eb55b61 100644
--- a/http/types.h
+++ b/http/types.h
@@ -40,6 +40,8 @@ struct http_request {
   s_str url;
   s_str protocol;
   s_list *headers;
+  s_list *cookies;
+  s_map params;
 };
 
 struct http_response {
diff --git a/lib/kc3/0.1/http/request.kc3 b/lib/kc3/0.1/http/request.kc3
index e840be9..5955b3b 100644
--- a/lib/kc3/0.1/http/request.kc3
+++ b/lib/kc3/0.1/http/request.kc3
@@ -5,6 +5,7 @@ defmodule HTTP.Request do
              url: "/",
              protocol: "HTTP/1.1",
              headers: [],
+             cookies: [],
              params: %{}]
 
   dlopen(__DIR__ + "../http.so")
diff --git a/lib/kc3/0.1/http/response.kc3 b/lib/kc3/0.1/http/response.kc3
index 6e4c13f..b96b045 100644
--- a/lib/kc3/0.1/http/response.kc3
+++ b/lib/kc3/0.1/http/response.kc3
@@ -21,6 +21,11 @@ defmodule HTTP.Response do
   def buf_write = cfn Sw "http_response_buf_write" (HTTP.Response, Buf,
     Bool)
 
+  def set_cookie = fn (response, cookie) {
+    headers = [{"Set-Cookie", cookie} | response.headers]
+    Struct.put(response, :headers, headers)
+  }
+
   def set_header = cfn HTTP.Response "http_response_set_header"
     (HTTP.Response, Str, Str, Result)
 
diff --git a/lib/kc3/0.1/sym.facts b/lib/kc3/0.1/sym.facts
index 79c7ebf..e567255 100644
--- a/lib/kc3/0.1/sym.facts
+++ b/lib/kc3/0.1/sym.facts
@@ -7,3 +7,10 @@ add {Sym, :symbol, Sym.type_size}
 replace {Sym.type_size, :symbol_value, cfn Uw "sym_type_size" (Sym, Result)}
 add {Sym, :symbol, Sym.find}
 replace {Sym.find, :symbol_value, cfn Tag "sym_find_to_tag" (Str, Result)}
+add {Sym, :symbol, Sym.anon_serial}
+replace {Sym.anon_serial, :symbol_value, 0}
+add {Sym, :symbol, Sym.anon}
+replace {Sym.anon, :symbol_value, Sym.fn (prefix) {
+  def Sym.anon_serial = anon_serial + 1
+  "#{prefix}-#{anon_serial}"
+}}
diff --git a/libkc3/env.c b/libkc3/env.c
index d4d06a4..3e95b95 100644
--- a/libkc3/env.c
+++ b/libkc3/env.c
@@ -2218,7 +2218,7 @@ s_tag * env_facts_first_with (s_env *env, s_facts *facts,
   }
  ok:
   list_delete_all(arguments);
-  if (true) {
+  if (false) {
     err_write_1("env_facts_first_with: ");
     err_inspect_tag(&tmp);
     err_write_1("\n");