Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions file.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,12 +339,16 @@ static char *uh_file_header(struct client *cl, int idx)
static void uh_file_response_ok_hdrs(struct client *cl, struct stat *s)
{
char buf[128];
struct extra_header *eh;

if (s) {
ustream_printf(cl->us, "ETag: %s\r\n", uh_file_mktag(s, buf, sizeof(buf)));
ustream_printf(cl->us, "Last-Modified: %s\r\n",
uh_file_unix2date(s->st_mtime, buf, sizeof(buf)));
}
list_for_each_entry(eh, &conf.extra_header, list) {
ustream_printf(cl->us, "%s\r\n", eh->header);
}
ustream_printf(cl->us, "Date: %s\r\n",
uh_file_unix2date(time(NULL), buf, sizeof(buf)));
}
Expand Down
19 changes: 18 additions & 1 deletion main.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ static int usage(const char *name)
" -d string URL decode given string\n"
" -r string Specify basic auth realm\n"
" -m string MD5 crypt given string\n"
" -z string Add additional response header (can use multiple times)\n"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to change the z to H with long opt --header. Similar to curl but also similarly to npm http-server, to thecoshman/http and miniserve

Copy link
Author

@wryun wryun Jul 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

H is, unfortunately, already used (see getopt). longopts are not supported.

"\n", name
);
return 1;
Expand All @@ -193,6 +194,7 @@ static void init_defaults_pre(void)
conf.cgi_path = "/sbin:/usr/sbin:/bin:/usr/bin";
INIT_LIST_HEAD(&conf.cgi_alias);
INIT_LIST_HEAD(&conf.lua_prefix);
INIT_LIST_HEAD(&conf.extra_header);
#if HAVE_UCODE
INIT_LIST_HEAD(&conf.ucode_prefix);
#endif
Expand Down Expand Up @@ -271,6 +273,7 @@ static void add_ucode_prefix(const char *prefix, const char *handler) {
int main(int argc, char **argv)
{
struct alias *alias;
struct extra_header *extra_header;
bool nofork = false;
char *port;
int opt, ch;
Expand All @@ -293,7 +296,7 @@ int main(int argc, char **argv)
init_defaults_pre();
signal(SIGPIPE, SIG_IGN);

while ((ch = getopt(argc, argv, "A:ab:C:c:Dd:E:e:fh:H:I:i:K:k:L:l:m:N:n:O:o:P:p:qRr:Ss:T:t:U:u:Xx:y:")) != -1) {
while ((ch = getopt(argc, argv, "A:ab:C:c:Dd:E:e:fh:H:I:i:K:k:L:l:m:N:n:O:o:P:p:qRr:Ss:T:t:U:u:Xx:y:z:")) != -1) {
switch(ch) {
#ifdef HAVE_TLS
case 'C':
Expand Down Expand Up @@ -408,6 +411,20 @@ int main(int argc, char **argv)
list_add(&alias->list, &conf.cgi_alias);
break;

case 'z':
extra_header = calloc(1, sizeof(*extra_header));
if (!extra_header) {
fprintf(stderr, "Error: failed to allocate extra_header\n");
exit(1);
}
if (strchr(optarg, ':') == NULL) {
fprintf(stderr, "Error: invalid extra header (-z) - missing colon\n");
exit(1);
Copy link

@stokito stokito Nov 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather not exit the whole webserver and lost access to Luci if the header is ivalid. But it looks like everywhere else the same behavior.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, but I think if you're changing the webserver settings you should have the expectation you may mess it up and have an alternative access mechanism (i.e. ssh).

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally yes, but here we in the embedded world. A user may lost an access to its router. In the same time if some header is not present and something was broken then it may be not so critical for a security.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As you pointed out, though, the general behaviour of bad options in uhttpd is that the server will not load, even if they're non-critical (e.g. missing 404 handler)... I guess I'm reluctant to change this unless someone else chimes in and says that it's the thing that's blocking a merge.

}
extra_header->header = optarg;
list_add(&extra_header->list, &conf.extra_header);
break;

case 'i':
optarg = strdup(optarg);
port = strchr(optarg, '=');
Expand Down
6 changes: 6 additions & 0 deletions uhttpd.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ struct lua_prefix {
void *ctx;
};

struct extra_header {
struct list_head list;
const char *header;
};

#ifdef HAVE_UCODE
struct ucode_prefix {
struct list_head list;
Expand Down Expand Up @@ -98,6 +103,7 @@ struct config {
int events_retry;
struct list_head cgi_alias;
struct list_head lua_prefix;
struct list_head extra_header;
#ifdef HAVE_UCODE
struct list_head ucode_prefix;
#endif
Expand Down