[PATCH] Add --header option to pass additional raw HTTP headers

Sergey Ponomarev stokito at gmail.com
Sun Jan 26 20:27:50 EST 2020


Signed-off-by: Sergey Ponomarev <stokito at gmail.com>
---
 uclient-fetch.c | 16 ++++++++++++++++
 uclient-http.c  | 28 ++++++++++++++++++++++++++++
 uclient.h       |  1 +
 3 files changed, 45 insertions(+)

diff --git a/uclient-fetch.c b/uclient-fetch.c
index 38c9c53..34cbfd5 100644
--- a/uclient-fetch.c
+++ b/uclient-fetch.c
@@ -43,6 +43,7 @@

 static const char *user_agent = "uclient-fetch";
 static const char *post_data;
+static const char **raw_headers = NULL;
 static struct ustream_ssl_ctx *ssl_ctx;
 static const struct ustream_ssl_ops *ssl_ops;
 static int quiet = false;
@@ -340,6 +341,7 @@ static int init_request(struct uclient *cl)

   uclient_http_reset_headers(cl);
   uclient_http_set_header(cl, "User-Agent", user_agent);
+  uclient_http_set_raw_headers(cl, raw_headers);
   if (cur_resume)
      check_resume_offset(cl);

@@ -458,6 +460,7 @@ static int usage(const char *progname)
      "  -P <dir>         Set directory for output files\n"
      "  --user=<user>        HTTP authentication username\n"
      "  --password=<password>     HTTP authentication password\n"
+     "  --header=<header>     Add HTTP header\n"
      "  --user-agent|-U <str>     Set HTTP user agent\n"
      "  --post-data=STRING    use the POST method; send STRING as the data\n"
      "  --spider|-s          Spider mode - only check file existence\n"
@@ -512,6 +515,7 @@ enum {
   L_CA_CERTIFICATE,
   L_USER,
   L_PASSWORD,
+  L_HEADER,
   L_USER_AGENT,
   L_POST_DATA,
   L_SPIDER,
@@ -527,6 +531,7 @@ static const struct option longopts[] = {
   [L_CA_CERTIFICATE] = { "ca-certificate", required_argument },
   [L_USER] = { "user", required_argument },
   [L_PASSWORD] = { "password", required_argument },
+  [L_HEADER] = { "header", required_argument },
   [L_USER_AGENT] = { "user-agent", required_argument },
   [L_POST_DATA] = { "post-data", required_argument },
   [L_SPIDER] = { "spider", no_argument },
@@ -546,6 +551,7 @@ int main(int argc, char **argv)
   const char *proxy_url;
   char *username = NULL;
   char *password = NULL;
+  int raw_headers_count = 0;
   struct uclient *cl;
   int longopt_idx = 0;
   bool has_cert = false;
@@ -580,6 +586,16 @@ int main(int argc, char **argv)
            password = strdup(optarg);
            memset(optarg, '*', strlen(optarg));
            break;
+        case L_HEADER:
+           if (!raw_headers) {
+              // Max possible count of headers is the count of args (argc) - 2
+              // because the first arg is program and last is a URL.
+              // But user may forget the URL and raw_headers is null
terminated so max raw_headers can be argc
+              raw_headers = calloc(argc, sizeof(char *));
+           }
+           raw_headers[raw_headers_count] = optarg;
+           raw_headers_count++;
+           break;
         case L_USER_AGENT:
            user_agent = optarg;
            break;
diff --git a/uclient-http.c b/uclient-http.c
index c1f7228..a70d445 100644
--- a/uclient-http.c
+++ b/uclient-http.c
@@ -96,6 +96,7 @@ struct uclient_http {

   uint32_t nc;

+  const char **raw_headers;
   struct blob_buf headers;
   struct blob_buf meta;
 };
@@ -589,6 +590,17 @@ uclient_http_add_auth_header(struct uclient_http *uh)
   return 0;
 }

+static void
+uclient_http_send_raw_headers(const struct uclient_http *uh) {
+  const char **raw_headers = uh->raw_headers;
+  const char *raw_header = *raw_headers;
+  while (raw_header != NULL) {
+     ustream_printf(uh->us, "%s\r\n", raw_header);
+     raw_headers++;
+     raw_header = *raw_headers;
+  }
+}
+
 static int
 uclient_http_send_headers(struct uclient_http *uh)
 {
@@ -626,6 +638,7 @@ uclient_http_send_headers(struct uclient_http *uh)
   if (err)
      return err;

+  uclient_http_send_raw_headers(uh);
   ustream_printf(uh->us, "\r\n");

   uh->state = HTTP_STATE_HEADERS_SENT;
@@ -1026,6 +1039,21 @@ uclient_http_set_header(struct uclient *cl,
const char *name, const char *value)
   return 0;
 }

+int
+uclient_http_set_raw_headers(struct uclient *cl, const char **raw_headers)
+{
+  struct uclient_http *uh = container_of(cl, struct uclient_http, uc);
+
+  if (cl->backend != &uclient_backend_http)
+     return -1;
+
+  if (uh->state > HTTP_STATE_INIT)
+     return -1;
+
+  uh->raw_headers = raw_headers;
+  return 0;
+}
+
 static int
 uclient_http_send_data(struct uclient *cl, const char *buf, unsigned int len)
 {
diff --git a/uclient.h b/uclient.h
index 4f37364..f1977bc 100644
--- a/uclient.h
+++ b/uclient.h
@@ -121,6 +121,7 @@ extern const struct uclient_backend uclient_backend_http;

 int uclient_http_reset_headers(struct uclient *cl);
 int uclient_http_set_header(struct uclient *cl, const char *name,
const char *value);
+int uclient_http_set_raw_headers(struct uclient *cl, const char **raw_headers);
 int uclient_http_set_request_type(struct uclient *cl, const char *type);
 int uclient_http_redirect(struct uclient *cl);

-- 
2.20.1




On Mon, 27 Jan 2020 at 03:46, Sergey Ponomarev <stokito at gmail.com> wrote:
>
> Hi,
>
> I making a package that internally will perform a HTTP call to OAuth service and I need to pass `Authorization: Barer token` as a header. The wget clone uclient-fetch doesn't have such functionality to pass an additional header while original wget have it. I can use curl but it uses too much space: uclient-fetch~ 28Kb while curl  ~280kb.
> I'm pretty sure that there is thousands of other reasons to pass a custom header like `Accept: application/json` etc.
> So here I made a small patch that adds such functionality to uclient-fetch. You can specify multiple headers so they all will be stored to raw_headers list.
> uclient-fetch --header="H1: VAL1" --header="H2: VAL2" -O - http://192.168.1.1/
> I tested with Wireshark and all works fine.
>
> Index: uclient-fetch.c
> <+>UTF-8
> ===================================================================
> --- uclient-fetch.c (revision fef6d3d311ac45c662c01e0ebd9cb0f6c8d7145c)
> +++ uclient-fetch.c (revision 8a9562d89891ec886192d7693e60065d0985fedd)
> @@ -43,6 +43,7 @@
>
>  static const char *user_agent = "uclient-fetch";
>  static const char *post_data;
> +static const char **raw_headers = NULL;
>  static struct ustream_ssl_ctx *ssl_ctx;
>  static const struct ustream_ssl_ops *ssl_ops;
>  static int quiet = false;
> @@ -340,6 +341,7 @@
>
>   uclient_http_reset_headers(cl);
>   uclient_http_set_header(cl, "User-Agent", user_agent);
> + uclient_http_set_raw_headers(cl, raw_headers);
>   if (cur_resume)
>   check_resume_offset(cl);
>
> @@ -458,6 +460,7 @@
>   " -P <dir> Set directory for output files\n"
>   " --user=<user> HTTP authentication username\n"
>   " --password=<password> HTTP authentication password\n"
> + " --header=<header> Add HTTP header\n"
>   " --user-agent|-U <str> Set HTTP user agent\n"
>   " --post-data=STRING use the POST method; send STRING as the data\n"
>   " --spider|-s Spider mode - only check file existence\n"
> @@ -512,6 +515,7 @@
>   L_CA_CERTIFICATE,
>   L_USER,
>   L_PASSWORD,
> + L_HEADER,
>   L_USER_AGENT,
>   L_POST_DATA,
>   L_SPIDER,
> @@ -527,6 +531,7 @@
>   [L_CA_CERTIFICATE] = { "ca-certificate", required_argument },
>   [L_USER] = { "user", required_argument },
>   [L_PASSWORD] = { "password", required_argument },
> + [L_HEADER] = { "header", required_argument },
>   [L_USER_AGENT] = { "user-agent", required_argument },
>   [L_POST_DATA] = { "post-data", required_argument },
>   [L_SPIDER] = { "spider", no_argument },
> @@ -546,6 +551,7 @@
>   const char *proxy_url;
>   char *username = NULL;
>   char *password = NULL;
> + int raw_headers_count = 0;
>   struct uclient *cl;
>   int longopt_idx = 0;
>   bool has_cert = false;
> @@ -579,6 +585,16 @@
>   break;
>   password = strdup(optarg);
>   memset(optarg, '*', strlen(optarg));
> + break;
> + case L_HEADER:
> + if (!raw_headers) {
> + // Max possible count of headers is the count of args (argc) - 2
> + // because the first arg is program and last is a URL.
> + // But user may forget the URL and raw_headers is null terminated so max raw_headers can be argc
> + raw_headers = calloc(argc, sizeof(char *));
> + }
> + raw_headers[raw_headers_count] = optarg;
> + raw_headers_count++;
>   break;
>   case L_USER_AGENT:
>   user_agent = optarg;
> Index: uclient-http.c
> <+>UTF-8
> ===================================================================
> --- uclient-http.c (revision fef6d3d311ac45c662c01e0ebd9cb0f6c8d7145c)
> +++ uclient-http.c (revision 8a9562d89891ec886192d7693e60065d0985fedd)
> @@ -96,6 +96,7 @@
>
>   uint32_t nc;
>
> + const char **raw_headers;
>   struct blob_buf headers;
>   struct blob_buf meta;
>  };
> @@ -589,6 +590,17 @@
>   return 0;
>  }
>
> +static void
> +uclient_http_send_raw_headers(const struct uclient_http *uh) {
> + const char **raw_headers = uh->raw_headers;
> + const char *raw_header = *raw_headers;
> + while (raw_header != NULL) {
> + ustream_printf(uh->us, "%s\r\n", raw_header);
> + raw_headers++;
> + raw_header = *raw_headers;
> + }
> +}
> +
>  static int
>  uclient_http_send_headers(struct uclient_http *uh)
>  {
> @@ -626,6 +638,7 @@
>   if (err)
>   return err;
>
> + uclient_http_send_raw_headers(uh);
>   ustream_printf(uh->us, "\r\n");
>
>   uh->state = HTTP_STATE_HEADERS_SENT;
> @@ -1025,6 +1038,21 @@
>   blobmsg_add_string(&uh->headers, name, value);
>   return 0;
>  }
> +
> +int
> +uclient_http_set_raw_headers(struct uclient *cl, const char **raw_headers)
> +{
> + struct uclient_http *uh = container_of(cl, struct uclient_http, uc);
> +
> + if (cl->backend != &uclient_backend_http)
> + return -1;
> +
> + if (uh->state > HTTP_STATE_INIT)
> + return -1;
> +
> + uh->raw_headers = raw_headers;
> + return 0;
> +}
>
>  static int
>  uclient_http_send_data(struct uclient *cl, const char *buf, unsigned int len)
> Index: uclient.h
> <+>UTF-8
> ===================================================================
> --- uclient.h (revision fef6d3d311ac45c662c01e0ebd9cb0f6c8d7145c)
> +++ uclient.h (revision 8a9562d89891ec886192d7693e60065d0985fedd)
> @@ -121,6 +121,7 @@
>
>  int uclient_http_reset_headers(struct uclient *cl);
>  int uclient_http_set_header(struct uclient *cl, const char *name, const char *value);
> +int uclient_http_set_raw_headers(struct uclient *cl, const char **raw_headers);
>  int uclient_http_set_request_type(struct uclient *cl, const char *type);
>  int uclient_http_redirect(struct uclient *cl);
>



-- 
Sergey Ponomarev, skype:stokito

_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list