#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 */
}
/*
- * 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.
*/
n = e->next;
free(hs);
}
- headers_init(data);
+ headers_reset(data);
return CURLE_OK;
}
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.
*/
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
#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"
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);
#include "select.h"
#include "strdup.h"
#include "http2.h"
-#include "headers.h"
#include "progress.h"
#include "ws.h"
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;
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)
{
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.
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;