Skip to content

Commit c4f8352

Browse files
committed
Try serving index.html when a directory is requested and directory listing is disabled
1 parent 16b7d74 commit c4f8352

1 file changed

Lines changed: 91 additions & 62 deletions

File tree

serve.c

Lines changed: 91 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ void respond(Request request, ResponseBuilder *b)
576576
return;
577577
}
578578

579-
if (serve_file_or_dir(b, LIT("/"), LIT("docroot/"), request.path, NULLSTR, false))
579+
if (serve_file_or_dir(b, LIT(""), LIT("docroot"), request.path, NULLSTR, false))
580580
return;
581581

582582
status_line(b, 404);
@@ -1885,10 +1885,50 @@ string mimetype_from_filename(string name)
18851885
return NULLSTR;
18861886
}
18871887

1888+
void serve_file(string path, size_t size, string mime, ResponseBuilder *b)
1889+
{
1890+
int fd;
1891+
do
1892+
fd = open(path.data, O_RDONLY);
1893+
while (fd < 0 && errno == EINTR);
1894+
1895+
if (fd < 0) {
1896+
status_line(b, 500);
1897+
close(fd);
1898+
return;
1899+
}
1900+
1901+
status_line(b, 200);
1902+
1903+
if (mime.size == 0) mime = mimetype_from_filename(path);
1904+
if (mime.size > 0) add_header_f(b, "Content-Type: %.*s", (int) mime.size, mime.data);
1905+
1906+
string dst = append_content_start(b, size);
1907+
if (dst.size == 0) {
1908+
status_line(b, 500);
1909+
close(fd);
1910+
return;
1911+
}
1912+
assert(dst.size >= size);
1913+
1914+
size_t copied = 0;
1915+
while (copied < size) {
1916+
int num = read(fd, dst.data + copied, size - copied);
1917+
if (num <= 0) {
1918+
if (num < 0)
1919+
log_format("Failed reading from '%.*s'\n", (int) path.size, path.data);
1920+
break;
1921+
}
1922+
copied += num;
1923+
}
1924+
1925+
append_content_end(b, copied);
1926+
close(fd);
1927+
}
1928+
18881929
bool serve_file_or_dir(ResponseBuilder *b, string prefix, string docroot,
18891930
string reqpath, string mime, bool enable_dir_listing)
18901931
{
1891-
18921932
// Sanitize the request path
18931933
char pathmem[1<<10];
18941934
string path;
@@ -1927,77 +1967,66 @@ bool serve_file_or_dir(ResponseBuilder *b, string prefix, string docroot,
19271967
return true;
19281968
}
19291969

1930-
if (S_ISREG(buf.st_mode)) {
1970+
if (S_ISDIR(buf.st_mode)) {
19311971

1932-
int fd;
1933-
do
1934-
fd = open(path.data, O_RDONLY);
1935-
while (fd < 0 && errno == EINTR);
1972+
if (enable_dir_listing) {
19361973

1937-
if (fd < 0) {
1938-
status_line(b, 500);
1939-
close(fd);
1940-
return true;
1941-
}
1974+
DIR *d = opendir(path.data);
1975+
if (d == NULL) {
1976+
status_line(b, 500);
1977+
return true;
1978+
}
19421979

1943-
status_line(b, 200);
1980+
status_line(b, 200);
1981+
append_content_s(b, LIT(
1982+
"<html>\n"
1983+
" <head>\n"
1984+
" </head>\n"
1985+
" <body>\n"
1986+
" <ul>\n"
1987+
" <li><a href=\"\">(parent)</a></li>")); // TODO: Add links
1988+
1989+
struct dirent *dir;
1990+
while ((dir = readdir(d))) {
1991+
if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."))
1992+
continue;
1993+
append_content_f(b, "<li><a href=\"\">%s</a></li>\n", dir->d_name); // TODO: Add links
1994+
}
19441995

1945-
if (mime.size == 0) mime = mimetype_from_filename(path);
1946-
if (mime.size > 0) add_header_f(b, "Content-Type: %.*s", (int) mime.size, mime.data);
1996+
append_content_s(b, LIT(
1997+
" </ul>\n"
1998+
" </body>\n"
1999+
"</html>\n"));
2000+
closedir(d);
2001+
} else {
19472002

1948-
string dst = append_content_start(b, (size_t) buf.st_size);
1949-
if (dst.size == 0) {
1950-
status_line(b, 500);
1951-
close(fd);
1952-
return true;
1953-
}
1954-
assert(dst.size >= (size_t) buf.st_size);
2003+
// Append /index.html to the path
2004+
if (path.size + SIZEOF("/index.html")-1 >= sizeof(pathmem)) {
2005+
status_line(b, 500);
2006+
return true;
2007+
}
2008+
memcpy(path.data + path.size, "/index.html", SIZEOF("/index.html")-1);
2009+
path.size += SIZEOF("/index.html")-1;
2010+
path.data[path.size] = '\0';
19552011

1956-
size_t copied = 0;
1957-
while (copied < (size_t) buf.st_size) {
1958-
int num = read(fd, dst.data + copied, (size_t) buf.st_size - copied);
1959-
if (num <= 0) {
1960-
if (num < 0)
1961-
log_format("Failed reading from '%.*s'\n", (int) path.size, path.data);
1962-
break;
2012+
if (stat(path.data, &buf)) {
2013+
if (errno == ENOENT)
2014+
return false;
2015+
status_line(b, 500);
2016+
return true;
2017+
}
2018+
if (!S_ISREG(buf.st_mode)) {
2019+
status_line(b, 500);
2020+
return true;
19632021
}
1964-
copied += num;
1965-
}
19662022

1967-
append_content_end(b, copied);
1968-
close(fd);
2023+
serve_file(path, (size_t) buf.st_size, mime, b);
2024+
}
19692025
return true;
19702026
}
19712027

1972-
if (enable_dir_listing && S_ISDIR(buf.st_mode)) {
1973-
1974-
DIR *d = opendir(path.data);
1975-
if (d == NULL) {
1976-
status_line(b, 500);
1977-
return true;
1978-
}
1979-
1980-
status_line(b, 200);
1981-
append_content_s(b, LIT(
1982-
"<html>\n"
1983-
" <head>\n"
1984-
" </head>\n"
1985-
" <body>\n"
1986-
" <ul>\n"
1987-
" <li><a href=\"\">(parent)</a></li>")); // TODO: Add links
1988-
1989-
struct dirent *dir;
1990-
while ((dir = readdir(d))) {
1991-
if (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."))
1992-
continue;
1993-
append_content_f(b, "<li><a href=\"\">%s</a></li>\n", dir->d_name); // TODO: Add links
1994-
}
1995-
1996-
append_content_s(b, LIT(
1997-
" </ul>\n"
1998-
" </body>\n"
1999-
"</html>\n"));
2000-
closedir(d);
2028+
if (S_ISREG(buf.st_mode)) {
2029+
serve_file(path, (size_t) buf.st_size, mime, b);
20012030
return true;
20022031
}
20032032

0 commit comments

Comments
 (0)