]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
http: move headers collecting to writer
authorStefan Eissing <stefan@eissing.org>
Tue, 6 Feb 2024 12:55:07 +0000 (13:55 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 26 Feb 2024 08:44:15 +0000 (09:44 +0100)
- add a client writer that does "push" response
  headers written to the client if the headers api
  is enabled
- remove special handling in sendf.c
- needs to be installed very early on connection
  setup to catch CONNECT response headers

Closes #12880

lib/headers.c
lib/headers.h
lib/http.c
lib/sendf.c
lib/sendf.h
lib/url.c

index 8a3264ab566c2b5a835053347c108d54bb0eb768..0c53dec6840a6287c389e9621fb8f0f276c3649d 100644 (file)
@@ -27,6 +27,7 @@
 #include "urldata.h"
 #include "strdup.h"
 #include "strcase.h"
+#include "sendf.h"
 #include "headers.h"
 
 /* The last 3 #include files should be in this order */
@@ -337,14 +338,68 @@ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header,
 }
 
 /*
- * Curl_headers_init(). Init the headers subsystem.
+ * Curl_headers_reset(). Reset the headers subsystem.
  */
-static void headers_init(struct Curl_easy *data)
+static void headers_reset(struct Curl_easy *data)
 {
   Curl_llist_init(&data->state.httphdrs, NULL);
   data->state.prevhead = NULL;
 }
 
+struct hds_cw_collect_ctx {
+  struct Curl_cwriter super;
+};
+
+static CURLcode hds_cw_collect_write(struct Curl_easy *data,
+                                     struct Curl_cwriter *writer, int type,
+                                     const char *buf, size_t blen)
+{
+  if((type & CLIENTWRITE_HEADER) && !(type & CLIENTWRITE_STATUS)) {
+    unsigned char htype = (unsigned char)
+      (type & CLIENTWRITE_CONNECT ? CURLH_CONNECT :
+       (type & CLIENTWRITE_1XX ? CURLH_1XX :
+        (type & CLIENTWRITE_TRAILER ? CURLH_TRAILER :
+         CURLH_HEADER)));
+    CURLcode result = Curl_headers_push(data, buf, htype);
+    if(result)
+      return result;
+  }
+  return Curl_cwriter_write(data, writer->next, type, buf, blen);
+}
+
+static const struct Curl_cwtype hds_cw_collect = {
+  "hds-collect",
+  NULL,
+  Curl_cwriter_def_init,
+  hds_cw_collect_write,
+  Curl_cwriter_def_close,
+  sizeof(struct hds_cw_collect_ctx)
+};
+
+CURLcode Curl_headers_init(struct Curl_easy *data)
+{
+  struct Curl_cwriter *writer;
+  CURLcode result;
+
+  if(data->conn && (data->conn->handler->protocol & PROTO_FAMILY_HTTP)) {
+    /* avoid installing it twice */
+    if(Curl_cwriter_get_by_name(data, hds_cw_collect.name))
+      return CURLE_OK;
+
+    result = Curl_cwriter_create(&writer, data, &hds_cw_collect,
+                                 CURL_CW_PROTOCOL);
+    if(result)
+      return result;
+
+    result = Curl_cwriter_add(data, writer);
+    if(result) {
+      Curl_cwriter_free(data, writer);
+      return result;
+    }
+  }
+  return CURLE_OK;
+}
+
 /*
  * Curl_headers_cleanup(). Free all stored headers and associated memory.
  */
@@ -358,7 +413,7 @@ CURLcode Curl_headers_cleanup(struct Curl_easy *data)
     n = e->next;
     free(hs);
   }
-  headers_init(data);
+  headers_reset(data);
   return CURLE_OK;
 }
 
index a5229ea22f0a512f0b9dc2b78fa7ece56dc3a4f5..d9813388c51e7a264c4012f29200d0848f49e923 100644 (file)
@@ -36,6 +36,12 @@ struct Curl_header_store {
   char buffer[1]; /* this is the raw header blob */
 };
 
+/*
+ * Initialize header collecting for a transfer.
+ * Will add a client writer that catches CLIENTWRITE_HEADER writes.
+ */
+CURLcode Curl_headers_init(struct Curl_easy *data);
+
 /*
  * Curl_headers_push() gets passed a full header to store.
  */
@@ -48,6 +54,7 @@ CURLcode Curl_headers_push(struct Curl_easy *data, const char *header,
 CURLcode Curl_headers_cleanup(struct Curl_easy *data);
 
 #else
+#define Curl_headers_init(x) CURLE_OK
 #define Curl_headers_push(x,y,z) CURLE_OK
 #define Curl_headers_cleanup(x) Curl_nop_stmt
 #endif
index 915205524105dc070320d2972caf5c92ad55f2db..5b4814cf8b4620ab6fcad7ffd85a9f51d6322b87 100644 (file)
@@ -73,6 +73,7 @@
 #include "hostip.h"
 #include "dynhds.h"
 #include "http.h"
+#include "headers.h"
 #include "select.h"
 #include "parsedate.h" /* for the week day and month names */
 #include "strtoofft.h"
@@ -3131,6 +3132,13 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done)
     break;
   }
 
+  /* Add collecting of headers written to client. For a new connection,
+   * we might have done that already, but reuse
+   * or multiplex needs it here as well. */
+  result = Curl_headers_init(data);
+  if(result)
+    goto fail;
+
   http = data->req.p.http;
   DEBUGASSERT(http);
 
index f37cee5d935a4b3a52491bbe85cd821a89a19d7e..6c575083c3e3c8b4f2319da35e971ec24ef2dc24 100644 (file)
@@ -49,7 +49,6 @@
 #include "select.h"
 #include "strdup.h"
 #include "http2.h"
-#include "headers.h"
 #include "progress.h"
 #include "ws.h"
 
@@ -256,21 +255,6 @@ static CURLcode chop_write(struct Curl_easy *data,
     len -= chunklen;
   }
 
-#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_HEADERS_API)
-  /* HTTP header, but not status-line */
-  if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
-     (type & CLIENTWRITE_HEADER) && !(type & CLIENTWRITE_STATUS) ) {
-    unsigned char htype = (unsigned char)
-      (type & CLIENTWRITE_CONNECT ? CURLH_CONNECT :
-       (type & CLIENTWRITE_1XX ? CURLH_1XX :
-        (type & CLIENTWRITE_TRAILER ? CURLH_TRAILER :
-         CURLH_HEADER)));
-    CURLcode result = Curl_headers_push(data, optr, htype);
-    if(result)
-      return result;
-  }
-#endif
-
   if(writeheader) {
     size_t wrote;
 
@@ -674,6 +658,17 @@ CURLcode Curl_cwriter_add(struct Curl_easy *data,
   return CURLE_OK;
 }
 
+struct Curl_cwriter *Curl_cwriter_get_by_name(struct Curl_easy *data,
+                                              const char *name)
+{
+  struct Curl_cwriter *writer;
+  for(writer = data->req.writer_stack; writer; writer = writer->next) {
+    if(!strcmp(name, writer->cwt->name))
+      return writer;
+  }
+  return NULL;
+}
+
 void Curl_cwriter_remove_by_name(struct Curl_easy *data,
                                  const char *name)
 {
index 4d4f01e4f58e0a924ce7b3513496b48193780cfe..1a4a68d8ea0634393566bb9424d1d2432d813761 100644 (file)
@@ -151,6 +151,9 @@ CURLcode Curl_cwriter_add(struct Curl_easy *data,
 void Curl_cwriter_remove_by_name(struct Curl_easy *data,
                                  const char *name);
 
+struct Curl_cwriter *Curl_cwriter_get_by_name(struct Curl_easy *data,
+                                              const char *name);
+
 /**
  * Convenience method for calling `writer->do_write()` that
  * checks for NULL writer.
index d6036c533b33193ebc8de3358826f1ed5f402919..21bd66b45e05cadd09230ba1591745900a9524bc 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -3848,6 +3848,9 @@ CURLcode Curl_setup_conn(struct Curl_easy *data,
   if(!conn->bits.reuse)
     result = Curl_conn_setup(data, conn, FIRSTSOCKET, conn->dns_entry,
                              CURL_CF_SSL_DEFAULT);
+  if(!result)
+    result = Curl_headers_init(data);
+
   /* not sure we need this flag to be passed around any more */
   *protocol_done = FALSE;
   return result;