httpd: do not default to Content-type: application/octet-stream

Instead, simply don't send this header.

On Mon, Apr 2, 2018 at 8:17 PM, xisd <xisd-dev@riseup.net> wrote:
> I had some trouble using busybox httpd to serve a static website and I
> thought the issue might be of interest.
>
> My problem is related to something that seem quite common for static
> site generator :  the use of html files without the '.html' extension
> (it is called 'clean url'...)
>
> Most web server guess that these files are html and display them like
> any other .html files.
>
> From what I understood, the MIME type for files without extension in
> busybox htttp default settings is 'application/octet-stream', and
> because of that 'clean url' pages are not displayed.
>
> It is only trouble because I wanted to deploy my website on freshly
> installed linux without editing any configuration.
>
> The default MIME setting make sense to me as it is, I just thought that
> might be worth mentioning since the use of 'clean url' seem to be a
> common practice for static sites generators (the one I use is callled
> 'yellow' (https://github.com/datenstrom/yellow))
>
> Here is a link for the related issue on github :
> https://github.com/datenstrom/yellow/issues/317

function                                             old     new   delta
send_headers                                         702     718     +16
send_headers_and_exit                                 23      20      -3
handle_incoming_and_exit                            2794    2791      -3
send_file_and_exit                                   772     756     -16
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/3 up/down: 16/-22)             Total: -6 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2018-04-07 01:13:30 +02:00
parent 6b6a3d9339
commit 9fe8bd8d61

View File

@ -392,7 +392,10 @@ static const struct {
struct globals { struct globals {
int verbose; /* must be int (used by getopt32) */ int verbose; /* must be int (used by getopt32) */
smallint flg_deny_all; smallint flg_deny_all;
#if ENABLE_FEATURE_HTTPD_GZIP
/* client can handle gzip / we are going to send gzip */
smallint content_gzip;
#endif
unsigned rmt_ip; /* used for IP-based allow/deny rules */ unsigned rmt_ip; /* used for IP-based allow/deny rules */
time_t last_mod; time_t last_mod;
char *rmt_ip_str; /* for $REMOTE_ADDR and $REMOTE_PORT */ char *rmt_ip_str; /* for $REMOTE_ADDR and $REMOTE_PORT */
@ -440,14 +443,15 @@ struct globals {
#if ENABLE_FEATURE_HTTPD_PROXY #if ENABLE_FEATURE_HTTPD_PROXY
Htaccess_Proxy *proxy; Htaccess_Proxy *proxy;
#endif #endif
#if ENABLE_FEATURE_HTTPD_GZIP
/* client can handle gzip / we are going to send gzip */
smallint content_gzip;
#endif
}; };
#define G (*ptr_to_globals) #define G (*ptr_to_globals)
#define verbose (G.verbose ) #define verbose (G.verbose )
#define flg_deny_all (G.flg_deny_all ) #define flg_deny_all (G.flg_deny_all )
#if ENABLE_FEATURE_HTTPD_GZIP
# define content_gzip (G.content_gzip )
#else
# define content_gzip 0
#endif
#define rmt_ip (G.rmt_ip ) #define rmt_ip (G.rmt_ip )
#define bind_addr_or_port (G.bind_addr_or_port) #define bind_addr_or_port (G.bind_addr_or_port)
#define g_query (G.g_query ) #define g_query (G.g_query )
@ -481,11 +485,6 @@ enum {
#define hdr_cnt (G.hdr_cnt ) #define hdr_cnt (G.hdr_cnt )
#define http_error_page (G.http_error_page ) #define http_error_page (G.http_error_page )
#define proxy (G.proxy ) #define proxy (G.proxy )
#if ENABLE_FEATURE_HTTPD_GZIP
# define content_gzip (G.content_gzip )
#else
# define content_gzip 0
#endif
#define INIT_G() do { \ #define INIT_G() do { \
setup_common_bufsiz(); \ setup_common_bufsiz(); \
SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
@ -944,7 +943,7 @@ static char *encodeString(const char *string)
if (isalnum(ch)) if (isalnum(ch))
*p++ = ch; *p++ = ch;
else else
p += sprintf(p, "&#%d;", (unsigned char) ch); p += sprintf(p, "&#%u;", (unsigned char) ch);
} }
*p = '\0'; *p = '\0';
return out; return out;
@ -1040,7 +1039,7 @@ static void log_and_exit(void)
* second packet is delayed for any reason. * second packet is delayed for any reason.
* responseNum - the result code to send. * responseNum - the result code to send.
*/ */
static void send_headers(int responseNum) static void send_headers(unsigned responseNum)
{ {
static const char RFC1123FMT[] ALIGN1 = "%a, %d %b %Y %H:%M:%S GMT"; static const char RFC1123FMT[] ALIGN1 = "%a, %d %b %Y %H:%M:%S GMT";
/* Fixed size 29-byte string. Example: Sun, 06 Nov 1994 08:49:37 GMT */ /* Fixed size 29-byte string. Example: Sun, 06 Nov 1994 08:49:37 GMT */
@ -1052,9 +1051,9 @@ static void send_headers(int responseNum)
#if ENABLE_FEATURE_HTTPD_ERROR_PAGES #if ENABLE_FEATURE_HTTPD_ERROR_PAGES
const char *error_page = NULL; const char *error_page = NULL;
#endif #endif
unsigned len;
unsigned i; unsigned i;
time_t timer = time(NULL); time_t timer = time(NULL);
int len;
for (i = 0; i < ARRAY_SIZE(http_response_type); i++) { for (i = 0; i < ARRAY_SIZE(http_response_type); i++) {
if (http_response_type[i] == responseNum) { if (http_response_type[i] == responseNum) {
@ -1078,16 +1077,21 @@ static void send_headers(int responseNum)
strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime_r(&timer, &tm)); strftime(date_str, sizeof(date_str), RFC1123FMT, gmtime_r(&timer, &tm));
/* ^^^ using gmtime_r() instead of gmtime() to not use static data */ /* ^^^ using gmtime_r() instead of gmtime() to not use static data */
len = sprintf(iobuf, len = sprintf(iobuf,
"HTTP/1.0 %d %s\r\n" "HTTP/1.0 %u %s\r\n"
"Content-type: %s\r\n"
"Date: %s\r\n" "Date: %s\r\n"
"Connection: close\r\n", "Connection: close\r\n",
responseNum, responseString, responseNum, responseString,
/* if it's error message, then it's HTML */
(responseNum == HTTP_OK ? found_mime_type : "text/html"),
date_str date_str
); );
if (responseNum != HTTP_OK || found_mime_type) {
len += sprintf(iobuf + len,
"Content-type: %s\r\n",
/* if it's error message, then it's HTML */
(responseNum != HTTP_OK ? "text/html" : found_mime_type)
);
}
#if ENABLE_FEATURE_HTTPD_BASIC_AUTH #if ENABLE_FEATURE_HTTPD_BASIC_AUTH
if (responseNum == HTTP_UNAUTHORIZED) { if (responseNum == HTTP_UNAUTHORIZED) {
len += sprintf(iobuf + len, len += sprintf(iobuf + len,
@ -1147,9 +1151,9 @@ static void send_headers(int responseNum)
"Accept-Ranges: bytes\r\n" "Accept-Ranges: bytes\r\n"
#endif #endif
"Last-Modified: %s\r\n" "Last-Modified: %s\r\n"
"%s %"OFF_FMT"u\r\n", "%s-Length: %"OFF_FMT"u\r\n",
date_str, date_str,
content_gzip ? "Transfer-Length:" : "Content-Length:", content_gzip ? "Transfer" : "Content",
file_size file_size
); );
} }
@ -1161,8 +1165,8 @@ static void send_headers(int responseNum)
iobuf[len++] = '\n'; iobuf[len++] = '\n';
if (infoString) { if (infoString) {
len += sprintf(iobuf + len, len += sprintf(iobuf + len,
"<HTML><HEAD><TITLE>%d %s</TITLE></HEAD>\n" "<HTML><HEAD><TITLE>%u %s</TITLE></HEAD>\n"
"<BODY><H1>%d %s</H1>\n" "<BODY><H1>%u %s</H1>\n"
"%s\n" "%s\n"
"</BODY></HTML>\n", "</BODY></HTML>\n",
responseNum, responseString, responseNum, responseString,
@ -1300,9 +1304,9 @@ static NOINLINE void cgi_io_loop_and_exit(int fromCgi_rd, int toCgi_wr, int post
continue; continue;
} }
if (DEBUG && WIFEXITED(status)) if (DEBUG && WIFEXITED(status))
bb_error_msg("CGI exited, status=%d", WEXITSTATUS(status)); bb_error_msg("CGI exited, status=%u", WEXITSTATUS(status));
if (DEBUG && WIFSIGNALED(status)) if (DEBUG && WIFSIGNALED(status))
bb_error_msg("CGI killed, signal=%d", WTERMSIG(status)); bb_error_msg("CGI killed, signal=%u", WTERMSIG(status));
#endif #endif
break; break;
} }
@ -1533,7 +1537,7 @@ static void send_cgi_and_exit(
if (G.http_accept_language) if (G.http_accept_language)
setenv1("HTTP_ACCEPT_LANGUAGE", G.http_accept_language); setenv1("HTTP_ACCEPT_LANGUAGE", G.http_accept_language);
if (post_len) if (post_len)
putenv(xasprintf("CONTENT_LENGTH=%d", post_len)); putenv(xasprintf("CONTENT_LENGTH=%u", post_len));
if (cookie) if (cookie)
setenv1("HTTP_COOKIE", cookie); setenv1("HTTP_COOKIE", cookie);
if (content_type) if (content_type)
@ -1684,8 +1688,8 @@ static NOINLINE void send_file_and_exit(const char *url, int what)
* (happens if you abort downloads from local httpd): */ * (happens if you abort downloads from local httpd): */
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
/* If not found, default is "application/octet-stream" */ /* If not found, default is to not send "Content-type:" */
found_mime_type = "application/octet-stream"; /*found_mime_type = NULL; - already is */
suffix = strrchr(url, '.'); suffix = strrchr(url, '.');
if (suffix) { if (suffix) {
static const char suffixTable[] ALIGN1 = static const char suffixTable[] ALIGN1 =
@ -2543,11 +2547,9 @@ static void mini_httpd_nommu(int server_socket, int argc, char **argv)
*/ */
while (1) { while (1) {
int n; int n;
len_and_sockaddr fromAddr;
/* Wait for connections... */ /* Wait for connections... */
fromAddr.len = LSA_SIZEOF_SA; n = accept(server_socket, NULL, NULL);
n = accept(server_socket, &fromAddr.u.sa, &fromAddr.len);
if (n < 0) if (n < 0)
continue; continue;
@ -2734,7 +2736,7 @@ int httpd_main(int argc UNUSED_PARAM, char **argv)
xfunc_error_retval = 0; xfunc_error_retval = 0;
if (opt & OPT_INETD) if (opt & OPT_INETD)
mini_httpd_inetd(); mini_httpd_inetd(); /* never returns */
#if BB_MMU #if BB_MMU
if (!(opt & OPT_FOREGROUND)) if (!(opt & OPT_FOREGROUND))
bb_daemonize(0); /* don't change current directory */ bb_daemonize(0); /* don't change current directory */