Skip to content
Merged
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
13 changes: 11 additions & 2 deletions config/vitepress.conf
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,18 @@ server {
root www/vitepress_docs;

index index.html index.htm;
error_page 404 /404.html;
error_page 403 /404.html;

location / {
error_page 404 /404.html;
error_page 403 /404.html;
error_page 404 /404_route_specific1.html;
}

location /override/ {
error_page 404 /404_route_specific2.html;
}

location /nooverride/ {

}
}
104 changes: 59 additions & 45 deletions src/config/config_builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,61 @@
#include <cstdlib>
#include <stdexcept>

static bool file_readable(const std::string& path)
{
struct stat sb;
return (stat(path.c_str(), &sb) == 0 && S_ISREG(sb.st_mode));
}

static bool read_error_page(const std::string& path, std::string& error_page_content)
{
if (!file_readable(path)) {
LOG(DEBUG) << "error page not readable : " << path;
return false;
}

int fd = 0;
char buf[4096];
ssize_t bytes = 1;
fd = open(path.c_str(), O_RDONLY);
if (fd == -1) {
return false;
}

while (bytes) {
bytes = read(fd, buf, sizeof(buf));
if (bytes == 0) {
break;
}
if (bytes < 0) {
close(fd);
return false;
}
error_page_content.append(buf, bytes);
}
close(fd);
return true;
}

static void update_error_pages(SharedConfig& shared)
{
for (std::map<HttpResponse::Status, std::string>::iterator it = shared.error_pages.begin();
it != shared.error_pages.end();
++it) {
HttpResponse::Status status = it->first;
const std::string& url = it->second;
std::string path = shared.document_root + url;
std::string error_page = "";
if (read_error_page(path, error_page)) {
LOG(DEBUG) << "ERROR page loaded : " << static_cast<int>(status) << " " << url;
it->second = error_page;
}
else {
it->second = "";
}
}
}

static void config_error(const std::string& msg, int line = -1)
{
if (line == -1)
Expand Down Expand Up @@ -254,42 +309,6 @@ static void parse_client_max_body_size(const AstNode& node, SharedConfig& config
config.max_body_size = size;
}

static bool file_readable(const std::string& path)
{
struct stat sb;
return (stat(path.c_str(), &sb) == 0 && S_ISREG(sb.st_mode));
}

static bool read_error_page(const std::string& path, std::string& error_page_content)
{
if (!file_readable(path)) {
LOG(DEBUG) << "error page not readable : " << path;
return false;
}

int fd = 0;
char buf[4096];
ssize_t bytes = 1;
fd = open(path.c_str(), O_RDONLY);
if (fd == -1) {
return false;
}

while (bytes) {
bytes = read(fd, buf, sizeof(buf));
if (bytes == 0) {
break;
}
if (bytes < 0) {
close(fd);
return false;
}
error_page_content.append(buf, bytes);
}
close(fd);
return true;
}

static void parse_error_pages(const AstNode& node, SharedConfig& config)
{
expect_min_argc(node, 2);
Expand All @@ -301,15 +320,7 @@ static void parse_error_pages(const AstNode& node, SharedConfig& config)

if (status == HttpResponse::kStatusNone)
config_error("'error_page' unsupported status code '" + node.args[i] + "'", node.line);

std::string error_page;
std::string path =
config.document_root +
url; // potentially unsave ? if file cannot be loaded, default error pages are used
if (read_error_page(path, error_page) == true) {
LOG(DEBUG) << "ERROR page loaded : " << status << " " << url;
config.error_pages[status] = error_page;
}
config.error_pages[status] = url;
}
}

Expand Down Expand Up @@ -431,6 +442,9 @@ RouteConfig ConfigBuilder::build_route_config(const AstNode& node, const SharedC
}

SharedConfig shared = build_shared_config(shared_nodes, &parent);

update_error_pages(shared); // loading the error pages

route.shared = shared;

return route;
Expand Down
2 changes: 1 addition & 1 deletion src/router/router.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ Handler* Router::handle_request(const HttpRequest& request) const
assert(!request.path.empty() && "Request URI can never be empty in the router");

const RouteConfig& best_route = find_best_route(request.path);

LOG(DEBUG) << "best_route.path = " << best_route.path;
if (!best_route.shared.redirect.url.empty()) {
return new RedirectHandler(best_route, request);
}
Expand Down
1 change: 1 addition & 0 deletions www/vitepress_docs/404_route_specific1.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<h1>ROUTE1 404</h1>
1 change: 1 addition & 0 deletions www/vitepress_docs/404_route_specific2.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<h1>ROUTE2 404</h1>