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
39 changes: 34 additions & 5 deletions include/glaze/net/http_router.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ namespace glz
*/
void add(http_method method, std::string_view path, H handle, const route_spec& spec = {})
{
#if __cpp_exceptions
try {
// Install in the radix tree first. add_route can throw on conflict
// (duplicate :param or *wildcard names at the same position); if it
Expand All @@ -316,6 +317,16 @@ namespace glz
std::fprintf(stderr, "Error adding route '%.*s': %s\n", static_cast<int>(path.length()), path.data(),
e.what());
}
#else
// Under -fno-exceptions add_route's misuse-detection throws are
// compiled to fprintf+abort (see the matching #else branches below),
// so we cannot observe the conflict here and simply propagate the
// install. Misconfigured routes still get reported on stderr.
add_route(method, path, handle, spec.constraints);
auto& entry = routes[std::string(path)][method];
entry.handle = std::move(handle);
entry.spec = spec;
#endif
}

/**
Expand Down Expand Up @@ -392,8 +403,14 @@ namespace glz
current->parameter_child->full_path = current->full_path + "/" + segment;
}
else if (current->parameter_child->parameter_name != param_name) {
throw std::runtime_error("Route conflict: different parameter names at same position: :" +
current->parameter_child->parameter_name + " vs :" + param_name);
const auto msg = "Route conflict: different parameter names at same position: :" +
current->parameter_child->parameter_name + " vs :" + param_name;
#if __cpp_exceptions
throw std::runtime_error(msg);
#else
std::fprintf(stderr, "%s\n", msg.c_str());
std::abort();
#endif
}

current = current->parameter_child.get();
Expand All @@ -402,7 +419,13 @@ namespace glz
std::string wildcard_name = segment.substr(1);

if (i != segments.size() - 1) {
throw std::runtime_error("Wildcard must be the last segment in route: " + path_str);
const auto msg = "Wildcard must be the last segment in route: " + path_str;
#if __cpp_exceptions
throw std::runtime_error(msg);
#else
std::fprintf(stderr, "%s\n", msg.c_str());
std::abort();
#endif
}

if (!current->wildcard_child) {
Expand All @@ -413,8 +436,14 @@ namespace glz
current->wildcard_child->full_path = current->full_path + "/" + segment;
}
else if (current->wildcard_child->parameter_name != wildcard_name) {
throw std::runtime_error("Route conflict: different wildcard names at same position: *" +
current->wildcard_child->parameter_name + " vs *" + wildcard_name);
const auto msg = "Route conflict: different wildcard names at same position: *" +
current->wildcard_child->parameter_name + " vs *" + wildcard_name;
#if __cpp_exceptions
throw std::runtime_error(msg);
#else
std::fprintf(stderr, "%s\n", msg.c_str());
std::abort();
#endif
}

current = current->wildcard_child.get();
Expand Down
18 changes: 18 additions & 0 deletions include/glaze/rpc/registry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,13 +328,21 @@ namespace glz
resp.reset(req_view);
repe::state_view state{req_view, resp};

#if __cpp_exceptions
try {
it->second(state);
}
catch (const std::exception& e) {
resp.reset(req_view);
resp.set_error(error_code::parse_error, detail::build_registry_error(in.query, e.what()));
}
#else
// Builds with -fno-exceptions cannot catch handler-thrown
// exceptions; user code in `it->second` is expected to be
// exception-free, matching the rest of glaze's no-exceptions
// contract (see #2265).
it->second(state);
#endif
}
}
else {
Expand Down Expand Up @@ -412,6 +420,7 @@ namespace glz
// Zero-copy call: state_view references the parsed request and response builder directly
repe::state_view state{req, resp};

#if __cpp_exceptions
try {
it->second(state);
}
Expand All @@ -425,6 +434,10 @@ namespace glz
resp.set_error(error_code::parse_error, "Unknown error");
return;
}
#else
// -fno-exceptions: user handlers are expected to be exception-free (see #2265).
it->second(state);
#endif

// For notifications, response buffer stays empty (no response sent)
}
Expand Down Expand Up @@ -529,6 +542,7 @@ namespace glz
bool has_params = !req.params.str.empty() && req.params.str != "null";
jsonrpc::state state{req.id, response, is_notification, has_params, req.params.str};

#if __cpp_exceptions
try {
it->second(std::move(state));
}
Expand All @@ -540,6 +554,10 @@ namespace glz
return R"({"jsonrpc":"2.0","error":{"code":-32603,"message":"Internal error","data":)" +
write_json(std::string_view{e.what()}).value_or("null") + R"(},"id":)" + id_json + "}";
}
#else
// -fno-exceptions: user handlers are expected to be exception-free (see #2265).
it->second(std::move(state));
#endif

if (is_notification) {
return std::nullopt;
Expand Down
Loading