[PATCH 1/4] uclient-fetch: --header option to pass additional raw HTTP headers
Sergey Ponomarev
stokito at gmail.com
Mon May 9 14:59:20 PDT 2022
You can add a custom HTTP header(s) to request:
wget --header='Authorization: Bearer TOKEN' \
--header='If-Modified-Since: Wed, 9 May 2021 12:16:00 GMT' \
https://example.com/
Some headers like Authorization or User-Agent may be already set by --password or --user-agent.
We may override them but it's a protection from user itself.
To keep code concise the logic omitted.
Signed-off-by: Sergey Ponomarev <stokito at gmail.com>
---
tests/cram/test-san_uclient-fetch.t | 1 +
tests/cram/test_uclient-fetch.t | 1 +
uclient-fetch.c | 16 +++++++++++++++
uclient-http.c | 31 +++++++++++++++++++++++++++++
uclient.h | 1 +
5 files changed, 50 insertions(+)
diff --git a/tests/cram/test-san_uclient-fetch.t b/tests/cram/test-san_uclient-fetch.t
index 435659b..047749a 100644
--- a/tests/cram/test-san_uclient-fetch.t
+++ b/tests/cram/test-san_uclient-fetch.t
@@ -15,6 +15,7 @@ check uclient-fetch usage:
\t--user=<user>\t\t\tHTTP authentication username (esc)
\t--password=<password>\t\tHTTP authentication password (esc)
\t--user-agent | -U <str>\t\tSet HTTP user agent (esc)
+ \t--header='Header: value'\t\tAdd HTTP header. Multiple allowed (esc)
\t--post-data=STRING\t\tuse the POST method; send STRING as the data (esc)
\t--post-file=FILE\t\tuse the POST method; send FILE as the data (esc)
\t--spider | -s\t\t\tSpider mode - only check file existence (esc)
diff --git a/tests/cram/test_uclient-fetch.t b/tests/cram/test_uclient-fetch.t
index e22aa40..cb70271 100644
--- a/tests/cram/test_uclient-fetch.t
+++ b/tests/cram/test_uclient-fetch.t
@@ -15,6 +15,7 @@ check uclient-fetch usage:
\t--user=<user>\t\t\tHTTP authentication username (esc)
\t--password=<password>\t\tHTTP authentication password (esc)
\t--user-agent | -U <str>\t\tSet HTTP user agent (esc)
+ \t--header='Header: value'\t\tAdd HTTP header. Multiple allowed (esc)
\t--post-data=STRING\t\tuse the POST method; send STRING as the data (esc)
\t--post-file=FILE\t\tuse the POST method; send FILE as the data (esc)
\t--spider | -s\t\t\tSpider mode - only check file existence (esc)
diff --git a/uclient-fetch.c b/uclient-fetch.c
index 282092e..4efc917 100644
--- a/uclient-fetch.c
+++ b/uclient-fetch.c
@@ -44,6 +44,7 @@
static const char *user_agent = "uclient-fetch";
static const char *post_data;
static const char *post_file;
+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;
@@ -342,6 +343,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);
@@ -481,6 +483,7 @@ static int usage(const char *progname)
" --continue | -c Continue a partially-downloaded file\n"
" --user=<user> HTTP authentication username\n"
" --password=<password> HTTP authentication password\n"
+ " --header='Header: value' Add HTTP header. Multiple allowed\n"
" --user-agent | -U <str> Set HTTP user agent\n"
" --post-data=STRING use the POST method; send STRING as the data\n"
" --post-file=FILE use the POST method; send FILE as the data\n"
@@ -542,6 +545,7 @@ enum {
L_USER,
L_PASSWORD,
L_USER_AGENT,
+ L_HEADER,
L_POST_DATA,
L_POST_FILE,
L_SPIDER,
@@ -559,6 +563,7 @@ static const struct option longopts[] = {
[L_USER] = { "user", required_argument, NULL, 0 },
[L_PASSWORD] = { "password", required_argument, NULL, 0 },
[L_USER_AGENT] = { "user-agent", required_argument, NULL, 0 },
+ [L_HEADER] = { "header", required_argument, NULL, 0 },
[L_POST_DATA] = { "post-data", required_argument, NULL, 0 },
[L_POST_FILE] = { "post-file", required_argument, NULL, 0 },
[L_SPIDER] = { "spider", no_argument, NULL, 0 },
@@ -578,6 +583,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;
@@ -626,6 +632,16 @@ int main(int argc, char **argv)
case L_USER_AGENT:
user_agent = optarg;
break;
+ case L_HEADER:
+ if (!raw_headers) {
+ /* Max possible count of headers is the count of args (argc) - 2
+ Since the first arg is program and last is a URL.
+ But user may forget the URL and raw_headers is null terminated so allocate argc */
+ raw_headers = calloc(argc, sizeof(char *));
+ }
+ raw_headers[raw_headers_count] = optarg;
+ raw_headers_count++;
+ break;
case L_POST_DATA:
post_data = optarg;
break;
diff --git a/uclient-http.c b/uclient-http.c
index c2bba6b..3d59de8 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;
};
@@ -587,6 +588,20 @@ uclient_http_add_auth_header(struct uclient_http *uh)
return 0;
}
+static void
+uclient_http_send_raw_headers(const struct uclient_http *uh) {
+ if (!uh->raw_headers) {
+ return;
+ }
+ 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)
{
@@ -625,6 +640,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 +1042,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.34.1
More information about the openwrt-devel
mailing list