luaCtx.registerFunction<void(std::shared_ptr<DOHFrontend>::*)(const std::map<int, std::shared_ptr<DOHResponseMapEntry>>&)>("setResponsesMap", [](std::shared_ptr<DOHFrontend> frontend, const std::map<int, std::shared_ptr<DOHResponseMapEntry>>& map) {
if (frontend != nullptr) {
- std::vector<std::shared_ptr<DOHResponseMapEntry>> newMap;
- newMap.reserve(map.size());
+ auto newMap = std::make_shared<std::vector<std::shared_ptr<DOHResponseMapEntry>>>();
+ newMap->reserve(map.size());
for (const auto& entry : map) {
- newMap.push_back(entry.second);
+ newMap->push_back(entry.second);
}
frontend->d_responsesMap = std::move(newMap);
// would be nice to be able to use a pdns_string_view there,
// but regex (called by matches() internally) requires a null-terminated string
string path(req->path.base, req->path.len);
- for (const auto& entry : dsc->df->d_responsesMap) {
- if (entry->matches(path)) {
- const auto& customHeaders = entry->getHeaders();
- handleResponse(*dsc->df, req, entry->getStatusCode(), entry->getContent(), customHeaders ? *customHeaders : dsc->df->d_customResponseHeaders, std::string(), false);
- return 0;
+ /* the responses map can be updated at runtime, so we need to take a copy of
+ the shared pointer, increasing the reference counter */
+ auto responsesMap = dsc->df->d_responsesMap;
+ if (responsesMap) {
+ for (const auto& entry : *responsesMap) {
+ if (entry->matches(path)) {
+ const auto& customHeaders = entry->getHeaders();
+ handleResponse(*dsc->df, req, entry->getStatusCode(), entry->getContent(), customHeaders ? *customHeaders : dsc->df->d_customResponseHeaders, std::string(), false);
+ return 0;
+ }
}
}
}
std::shared_ptr<DOHServerConfig> d_dsc{nullptr};
- std::vector<std::shared_ptr<DOHResponseMapEntry>> d_responsesMap;
+ std::shared_ptr<std::vector<std::shared_ptr<DOHResponseMapEntry>>> d_responsesMap;
TLSConfig d_tlsConfig;
TLSErrorCounters d_tlsCounters;
std::string d_serverTokens{"h2o/dnsdist"};