Unverified Commit e329479a authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa Committed by GitHub

Merge pull request #1215 from nghttp2/mruby-per-backend

nghttpx: Support per-backend mruby script
parents f80a7873 b574ae6a
...@@ -299,9 +299,19 @@ server. These hooks allows users to modify header fields, or common ...@@ -299,9 +299,19 @@ server. These hooks allows users to modify header fields, or common
HTTP variables, like authority or request path, and even return custom HTTP variables, like authority or request path, and even return custom
response without forwarding request to backend servers. response without forwarding request to backend servers.
To specify mruby script file, use :option:`--mruby-file` option. The There are 2 levels of mruby script invocations: global and
script will be evaluated once per thread on startup, and it must per-backend. The global mruby script is set by :option:`--mruby-file`
instantiate object and evaluate it as the return value (e.g., option and is called for all requests. The per-backend mruby script
is set by "mruby" parameter in :option:`-b` option. It is invoked for
a request which is forwarded to the particular backend. The order of
hook invocation is: global request phase hook, per-backend request
phase hook, per-backend response phase hook, and finally global
response phase hook. If a hook returns a response, any later hooks
are not invoked. The global request hook is invoked before selecting
backend, and changing request path may affect the backend selection.
The all mruby script will be evaluated once per thread on startup, and
it must instantiate object and evaluate it as the return value (e.g.,
``App.new``). This object is called app object. If app object ``App.new``). This object is called app object. If app object
defines ``on_req`` method, it is called with :rb:class:`Nghttpx::Env` defines ``on_req`` method, it is called with :rb:class:`Nghttpx::Env`
object on request hook. Similarly, if app object defines ``on_resp`` object on request hook. Similarly, if app object defines ``on_resp``
......
...@@ -169,6 +169,7 @@ OPTIONS = [ ...@@ -169,6 +169,7 @@ OPTIONS = [
"ocsp-startup", "ocsp-startup",
"no-verify-ocsp", "no-verify-ocsp",
"verify-client-tolerate-expired", "verify-client-tolerate-expired",
"ignore-per-backend-mruby-error",
] ]
LOGVARS = [ LOGVARS = [
......
...@@ -1729,12 +1729,13 @@ Connections: ...@@ -1729,12 +1729,13 @@ Connections:
The parameters are delimited by ";". The available The parameters are delimited by ";". The available
parameters are: "proto=<PROTO>", "tls", parameters are: "proto=<PROTO>", "tls",
"sni=<SNI_HOST>", "fall=<N>", "rise=<N>", "sni=<SNI_HOST>", "fall=<N>", "rise=<N>",
"affinity=<METHOD>", "dns", and "redirect-if-not-tls". "affinity=<METHOD>", "dns", "redirect-if-not-tls",
The parameter consists of keyword, and optionally "upgrade-scheme", and "mruby=<PATH>". The parameter
followed by "=" and value. For example, the parameter consists of keyword, and optionally followed by "=" and
"proto=h2" consists of the keyword "proto" and value value. For example, the parameter "proto=h2" consists
"h2". The parameter "tls" consists of the keyword "tls" of the keyword "proto" and value "h2". The parameter
without value. Each parameter is described as follows. "tls" consists of the keyword "tls" without value. Each
parameter is described as follows.
The backend application protocol can be specified using The backend application protocol can be specified using
optional "proto" parameter, and in the form of optional "proto" parameter, and in the form of
...@@ -1827,6 +1828,10 @@ Connections: ...@@ -1827,6 +1828,10 @@ Connections:
server which requires "https" :scheme pseudo header server which requires "https" :scheme pseudo header
field on TLS encrypted connection. field on TLS encrypted connection.
"mruby=<PATH>" parameter specifies a path to mruby
script file which is invoked when this backend is
selected.
Since ";" and ":" are used as delimiter, <PATTERN> must Since ";" and ":" are used as delimiter, <PATTERN> must
not contain these characters. Since ";" has special not contain these characters. Since ";" has special
meaning in shell, the option value must be quoted. meaning in shell, the option value must be quoted.
...@@ -2749,6 +2754,10 @@ Process: ...@@ -2749,6 +2754,10 @@ Process:
Scripting: Scripting:
--mruby-file=<PATH> --mruby-file=<PATH>
Set mruby script file Set mruby script file
--ignore-per-backend-mruby-error
Ignore mruby compile error for per-backend mruby script
file. If error occurred, it is treated as if no mruby
file were specified for the backend.
Misc: Misc:
--conf=<PATH> --conf=<PATH>
...@@ -3424,6 +3433,8 @@ int main(int argc, char **argv) { ...@@ -3424,6 +3433,8 @@ int main(int argc, char **argv) {
{SHRPX_OPT_SINGLE_PROCESS.c_str(), no_argument, &flag, 159}, {SHRPX_OPT_SINGLE_PROCESS.c_str(), no_argument, &flag, 159},
{SHRPX_OPT_VERIFY_CLIENT_TOLERATE_EXPIRED.c_str(), no_argument, &flag, {SHRPX_OPT_VERIFY_CLIENT_TOLERATE_EXPIRED.c_str(), no_argument, &flag,
160}, 160},
{SHRPX_OPT_IGNORE_PER_BACKEND_MRUBY_ERROR.c_str(), no_argument, &flag,
161},
{nullptr, 0, nullptr, 0}}; {nullptr, 0, nullptr, 0}};
int option_index = 0; int option_index = 0;
...@@ -4190,6 +4201,11 @@ int main(int argc, char **argv) { ...@@ -4190,6 +4201,11 @@ int main(int argc, char **argv) {
cmdcfgs.emplace_back(SHRPX_OPT_VERIFY_CLIENT_TOLERATE_EXPIRED, cmdcfgs.emplace_back(SHRPX_OPT_VERIFY_CLIENT_TOLERATE_EXPIRED,
StringRef::from_lit("yes")); StringRef::from_lit("yes"));
break; break;
case 161:
// --ignore-per-backend-mruby-error
cmdcfgs.emplace_back(SHRPX_OPT_IGNORE_PER_BACKEND_MRUBY_ERROR,
StringRef::from_lit("yes"));
break;
default: default:
break; break;
} }
......
...@@ -55,6 +55,9 @@ ...@@ -55,6 +55,9 @@
#include "shrpx_log.h" #include "shrpx_log.h"
#include "shrpx_tls.h" #include "shrpx_tls.h"
#include "shrpx_http.h" #include "shrpx_http.h"
#ifdef HAVE_MRUBY
# include "shrpx_mruby.h"
#endif // HAVE_MRUBY
#include "util.h" #include "util.h"
#include "base64.h" #include "base64.h"
#include "ssl_compat.h" #include "ssl_compat.h"
...@@ -807,6 +810,7 @@ int parse_upstream_params(UpstreamParams &out, const StringRef &src_params) { ...@@ -807,6 +810,7 @@ int parse_upstream_params(UpstreamParams &out, const StringRef &src_params) {
struct DownstreamParams { struct DownstreamParams {
StringRef sni; StringRef sni;
StringRef mruby;
AffinityConfig affinity; AffinityConfig affinity;
size_t fall; size_t fall;
size_t rise; size_t rise;
...@@ -921,6 +925,9 @@ int parse_downstream_params(DownstreamParams &out, ...@@ -921,6 +925,9 @@ int parse_downstream_params(DownstreamParams &out,
out.redirect_if_not_tls = true; out.redirect_if_not_tls = true;
} else if (util::strieq_l("upgrade-scheme", param)) { } else if (util::strieq_l("upgrade-scheme", param)) {
out.upgrade_scheme = true; out.upgrade_scheme = true;
} else if (util::istarts_with_l(param, "mruby=")) {
auto valstr = StringRef{first + str_size("mruby="), end};
out.mruby = valstr;
} else if (!param.empty()) { } else if (!param.empty()) {
LOG(ERROR) << "backend: " << param << ": unknown keyword"; LOG(ERROR) << "backend: " << param << ": unknown keyword";
return -1; return -1;
...@@ -1045,6 +1052,18 @@ int parse_mapping(Config *config, DownstreamAddrConfig &addr, ...@@ -1045,6 +1052,18 @@ int parse_mapping(Config *config, DownstreamAddrConfig &addr,
if (params.redirect_if_not_tls) { if (params.redirect_if_not_tls) {
g.redirect_if_not_tls = true; g.redirect_if_not_tls = true;
} }
// All backends in the same group must have the same mruby path.
// If some backend does not specify mruby file, and there is at
// least one backend with mruby file, it is used for all backend
// in the group.
if (g.mruby_file.empty()) {
g.mruby_file = params.mruby;
} else if (g.mruby_file != params.mruby) {
LOG(ERROR) << "backend: mruby: multiple different mruby file found in "
"a single group";
return -1;
}
g.addrs.push_back(addr); g.addrs.push_back(addr);
continue; continue;
} }
...@@ -1065,6 +1084,7 @@ int parse_mapping(Config *config, DownstreamAddrConfig &addr, ...@@ -1065,6 +1084,7 @@ int parse_mapping(Config *config, DownstreamAddrConfig &addr,
g.affinity.cookie.secure = params.affinity.cookie.secure; g.affinity.cookie.secure = params.affinity.cookie.secure;
} }
g.redirect_if_not_tls = params.redirect_if_not_tls; g.redirect_if_not_tls = params.redirect_if_not_tls;
g.mruby_file = params.mruby;
if (pattern[0] == '*') { if (pattern[0] == '*') {
// wildcard pattern // wildcard pattern
...@@ -2179,6 +2199,9 @@ int option_lookup_token(const char *name, size_t namelen) { ...@@ -2179,6 +2199,9 @@ int option_lookup_token(const char *name, size_t namelen) {
} }
break; break;
case 'r': case 'r':
if (util::strieq_l("ignore-per-backend-mruby-erro", name, 29)) {
return SHRPX_OPTID_IGNORE_PER_BACKEND_MRUBY_ERROR;
}
if (util::strieq_l("strip-incoming-x-forwarded-fo", name, 29)) { if (util::strieq_l("strip-incoming-x-forwarded-fo", name, 29)) {
return SHRPX_OPTID_STRIP_INCOMING_X_FORWARDED_FOR; return SHRPX_OPTID_STRIP_INCOMING_X_FORWARDED_FOR;
} }
...@@ -3563,6 +3586,10 @@ int parse_config(Config *config, int optid, const StringRef &opt, ...@@ -3563,6 +3586,10 @@ int parse_config(Config *config, int optid, const StringRef &opt,
case SHRPX_OPTID_VERIFY_CLIENT_TOLERATE_EXPIRED: case SHRPX_OPTID_VERIFY_CLIENT_TOLERATE_EXPIRED:
config->tls.client_verify.tolerate_expired = util::strieq_l("yes", optarg); config->tls.client_verify.tolerate_expired = util::strieq_l("yes", optarg);
return 0;
case SHRPX_OPTID_IGNORE_PER_BACKEND_MRUBY_ERROR:
config->ignore_per_backend_mruby_error = util::strieq_l("yes", optarg);
return 0; return 0;
case SHRPX_OPTID_CONF: case SHRPX_OPTID_CONF:
LOG(WARN) << "conf: ignored"; LOG(WARN) << "conf: ignored";
...@@ -3854,7 +3881,32 @@ int configure_downstream_group(Config *config, bool http2_proxy, ...@@ -3854,7 +3881,32 @@ int configure_downstream_group(Config *config, bool http2_proxy,
<< (addr.tls ? ", tls" : ""); << (addr.tls ? ", tls" : "");
} }
} }
#ifdef HAVE_MRUBY
// Try compile mruby script and catch compile error early.
if (!g.mruby_file.empty()) {
if (mruby::create_mruby_context(g.mruby_file) == nullptr) {
LOG(config->ignore_per_backend_mruby_error ? ERROR : FATAL)
<< "backend: Could not compile mruby flie for pattern "
<< g.pattern;
if (!config->ignore_per_backend_mruby_error) {
return -1;
}
g.mruby_file = StringRef{};
}
}
#endif // HAVE_MRUBY
}
#ifdef HAVE_MRUBY
// Try compile mruby script (--mruby-file) here to catch compile
// error early.
if (!config->mruby_file.empty()) {
if (mruby::create_mruby_context(config->mruby_file) == nullptr) {
LOG(FATAL) << "mruby-file: Could not compile mruby file";
return -1;
}
} }
#endif // HAVE_MRUBY
if (catch_all_group == -1) { if (catch_all_group == -1) {
LOG(FATAL) << "backend: No catch-all backend address is configured"; LOG(FATAL) << "backend: No catch-all backend address is configured";
......
...@@ -345,6 +345,8 @@ constexpr auto SHRPX_OPT_OCSP_STARTUP = StringRef::from_lit("ocsp-startup"); ...@@ -345,6 +345,8 @@ constexpr auto SHRPX_OPT_OCSP_STARTUP = StringRef::from_lit("ocsp-startup");
constexpr auto SHRPX_OPT_NO_VERIFY_OCSP = StringRef::from_lit("no-verify-ocsp"); constexpr auto SHRPX_OPT_NO_VERIFY_OCSP = StringRef::from_lit("no-verify-ocsp");
constexpr auto SHRPX_OPT_VERIFY_CLIENT_TOLERATE_EXPIRED = constexpr auto SHRPX_OPT_VERIFY_CLIENT_TOLERATE_EXPIRED =
StringRef::from_lit("verify-client-tolerate-expired"); StringRef::from_lit("verify-client-tolerate-expired");
constexpr auto SHRPX_OPT_IGNORE_PER_BACKEND_MRUBY_ERROR =
StringRef::from_lit("ignore-per-backend-mruby-error");
constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8; constexpr size_t SHRPX_OBFUSCATED_NODE_LENGTH = 8;
...@@ -483,6 +485,7 @@ struct DownstreamAddrGroupConfig { ...@@ -483,6 +485,7 @@ struct DownstreamAddrGroupConfig {
: pattern(pattern), affinity{AFFINITY_NONE}, redirect_if_not_tls(false) {} : pattern(pattern), affinity{AFFINITY_NONE}, redirect_if_not_tls(false) {}
StringRef pattern; StringRef pattern;
StringRef mruby_file;
std::vector<DownstreamAddrConfig> addrs; std::vector<DownstreamAddrConfig> addrs;
// Bunch of session affinity hash. Only used if affinity == // Bunch of session affinity hash. Only used if affinity ==
// AFFINITY_IP. // AFFINITY_IP.
...@@ -915,6 +918,7 @@ struct Config { ...@@ -915,6 +918,7 @@ struct Config {
http2_proxy{false}, http2_proxy{false},
single_process{false}, single_process{false},
single_thread{false}, single_thread{false},
ignore_per_backend_mruby_error{false},
ev_loop_flags{0} {} ev_loop_flags{0} {}
~Config(); ~Config();
...@@ -959,6 +963,8 @@ struct Config { ...@@ -959,6 +963,8 @@ struct Config {
// handling is omitted. // handling is omitted.
bool single_process; bool single_process;
bool single_thread; bool single_thread;
// Ignore mruby compile error for per-backend mruby script.
bool ignore_per_backend_mruby_error;
// flags passed to ev_default_loop() and ev_loop_new() // flags passed to ev_default_loop() and ev_loop_new()
int ev_loop_flags; int ev_loop_flags;
}; };
...@@ -1063,6 +1069,7 @@ enum { ...@@ -1063,6 +1069,7 @@ enum {
SHRPX_OPTID_HTTP2_MAX_CONCURRENT_STREAMS, SHRPX_OPTID_HTTP2_MAX_CONCURRENT_STREAMS,
SHRPX_OPTID_HTTP2_NO_COOKIE_CRUMBLING, SHRPX_OPTID_HTTP2_NO_COOKIE_CRUMBLING,
SHRPX_OPTID_HTTP2_PROXY, SHRPX_OPTID_HTTP2_PROXY,
SHRPX_OPTID_IGNORE_PER_BACKEND_MRUBY_ERROR,
SHRPX_OPTID_INCLUDE, SHRPX_OPTID_INCLUDE,
SHRPX_OPTID_INSECURE, SHRPX_OPTID_INSECURE,
SHRPX_OPTID_LISTENER_DISABLE_TIMEOUT, SHRPX_OPTID_LISTENER_DISABLE_TIMEOUT,
......
...@@ -188,6 +188,14 @@ Downstream::~Downstream() { ...@@ -188,6 +188,14 @@ Downstream::~Downstream() {
#endif // HAVE_MRUBY #endif // HAVE_MRUBY
} }
#ifdef HAVE_MRUBY
if (dconn_) {
const auto &group = dconn_->get_downstream_addr_group();
const auto &mruby_ctx = group->mruby_ctx;
mruby_ctx->delete_downstream(this);
}
#endif // HAVE_MRUBY
// DownstreamConnection may refer to this object. Delete it now // DownstreamConnection may refer to this object. Delete it now
// explicitly. // explicitly.
dconn_.reset(); dconn_.reset();
...@@ -217,6 +225,12 @@ void Downstream::detach_downstream_connection() { ...@@ -217,6 +225,12 @@ void Downstream::detach_downstream_connection() {
return; return;
} }
#ifdef HAVE_MRUBY
const auto &group = dconn_->get_downstream_addr_group();
const auto &mruby_ctx = group->mruby_ctx;
mruby_ctx->delete_downstream(this);
#endif // HAVE_MRUBY
dconn_->detach_downstream(this); dconn_->detach_downstream(this);
auto handler = dconn_->get_client_handler(); auto handler = dconn_->get_client_handler();
...@@ -230,6 +244,16 @@ DownstreamConnection *Downstream::get_downstream_connection() { ...@@ -230,6 +244,16 @@ DownstreamConnection *Downstream::get_downstream_connection() {
} }
std::unique_ptr<DownstreamConnection> Downstream::pop_downstream_connection() { std::unique_ptr<DownstreamConnection> Downstream::pop_downstream_connection() {
#ifdef HAVE_MRUBY
if (!dconn_) {
return nullptr;
}
const auto &group = dconn_->get_downstream_addr_group();
const auto &mruby_ctx = group->mruby_ctx;
mruby_ctx->delete_downstream(this);
#endif // HAVE_MRUBY
return std::unique_ptr<DownstreamConnection>(dconn_.release()); return std::unique_ptr<DownstreamConnection>(dconn_.release());
} }
......
...@@ -461,6 +461,9 @@ void Http2Upstream::initiate_downstream(Downstream *downstream) { ...@@ -461,6 +461,9 @@ void Http2Upstream::initiate_downstream(Downstream *downstream) {
return; return;
} }
#ifdef HAVE_MRUBY
auto dconn_ptr = dconn.get();
#endif // HAVE_MRUBY
rv = downstream->attach_downstream_connection(std::move(dconn)); rv = downstream->attach_downstream_connection(std::move(dconn));
if (rv != 0) { if (rv != 0) {
// downstream connection fails, send error page // downstream connection fails, send error page
...@@ -474,6 +477,25 @@ void Http2Upstream::initiate_downstream(Downstream *downstream) { ...@@ -474,6 +477,25 @@ void Http2Upstream::initiate_downstream(Downstream *downstream) {
return; return;
} }
#ifdef HAVE_MRUBY
const auto &group = dconn_ptr->get_downstream_addr_group();
const auto &mruby_ctx = group->mruby_ctx;
if (mruby_ctx->run_on_request_proc(downstream) != 0) {
if (error_reply(downstream, 500) != 0) {
rst_stream(downstream, NGHTTP2_INTERNAL_ERROR);
}
downstream_queue_.mark_failure(downstream);
return;
}
if (downstream->get_response_state() == Downstream::MSG_COMPLETE) {
return;
}
#endif // HAVE_MRUBY
rv = downstream->push_request_headers(); rv = downstream->push_request_headers();
if (rv != 0) { if (rv != 0) {
...@@ -1611,6 +1633,22 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) { ...@@ -1611,6 +1633,22 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
#ifdef HAVE_MRUBY #ifdef HAVE_MRUBY
if (!downstream->get_non_final_response()) { if (!downstream->get_non_final_response()) {
auto dconn = downstream->get_downstream_connection();
const auto &group = dconn->get_downstream_addr_group();
const auto &dmruby_ctx = group->mruby_ctx;
if (dmruby_ctx->run_on_response_proc(downstream) != 0) {
if (error_reply(downstream, 500) != 0) {
return -1;
}
// Returning -1 will signal deletion of dconn.
return -1;
}
if (downstream->get_response_state() == Downstream::MSG_COMPLETE) {
return -1;
}
auto worker = handler_->get_worker(); auto worker = handler_->get_worker();
auto mruby_ctx = worker->get_mruby_context(); auto mruby_ctx = worker->get_mruby_context();
......
...@@ -431,12 +431,29 @@ int htp_hdrs_completecb(http_parser *htp) { ...@@ -431,12 +431,29 @@ int htp_hdrs_completecb(http_parser *htp) {
return -1; return -1;
} }
#ifdef HAVE_MRUBY
auto dconn_ptr = dconn.get();
#endif // HAVE_MRUBY
if (downstream->attach_downstream_connection(std::move(dconn)) != 0) { if (downstream->attach_downstream_connection(std::move(dconn)) != 0) {
downstream->set_request_state(Downstream::CONNECT_FAIL); downstream->set_request_state(Downstream::CONNECT_FAIL);
return -1; return -1;
} }
#ifdef HAVE_MRUBY
const auto &group = dconn_ptr->get_downstream_addr_group();
const auto &dmruby_ctx = group->mruby_ctx;
if (dmruby_ctx->run_on_request_proc(downstream) != 0) {
resp.http_status = 500;
return -1;
}
if (downstream->get_response_state() == Downstream::MSG_COMPLETE) {
return 0;
}
#endif // HAVE_MRUBY
rv = downstream->push_request_headers(); rv = downstream->push_request_headers();
if (rv != 0) { if (rv != 0) {
...@@ -1021,6 +1038,8 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) { ...@@ -1021,6 +1038,8 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
const auto &req = downstream->request(); const auto &req = downstream->request();
auto &resp = downstream->response(); auto &resp = downstream->response();
auto &balloc = downstream->get_block_allocator(); auto &balloc = downstream->get_block_allocator();
auto dconn = downstream->get_downstream_connection();
assert(dconn);
if (downstream->get_non_final_response() && if (downstream->get_non_final_response() &&
!downstream->supports_non_final_response()) { !downstream->supports_non_final_response()) {
...@@ -1030,6 +1049,18 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) { ...@@ -1030,6 +1049,18 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
#ifdef HAVE_MRUBY #ifdef HAVE_MRUBY
if (!downstream->get_non_final_response()) { if (!downstream->get_non_final_response()) {
const auto &group = dconn->get_downstream_addr_group();
const auto &dmruby_ctx = group->mruby_ctx;
if (dmruby_ctx->run_on_response_proc(downstream) != 0) {
error_reply(500);
return -1;
}
if (downstream->get_response_state() == Downstream::MSG_COMPLETE) {
return -1;
}
auto worker = handler_->get_worker(); auto worker = handler_->get_worker();
auto mruby_ctx = worker->get_mruby_context(); auto mruby_ctx = worker->get_mruby_context();
...@@ -1150,8 +1181,6 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) { ...@@ -1150,8 +1181,6 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
if (req.method != HTTP_CONNECT || !downstream->get_upgraded()) { if (req.method != HTTP_CONNECT || !downstream->get_upgraded()) {
auto affinity_cookie = downstream->get_affinity_cookie_to_send(); auto affinity_cookie = downstream->get_affinity_cookie_to_send();
if (affinity_cookie) { if (affinity_cookie) {
auto dconn = downstream->get_downstream_connection();
assert(dconn);
auto &group = dconn->get_downstream_addr_group(); auto &group = dconn->get_downstream_addr_group();
auto &shared_addr = group->shared_addr; auto &shared_addr = group->shared_addr;
auto &cookieconf = shared_addr->affinity.cookie; auto &cookieconf = shared_addr->affinity.cookie;
......
...@@ -68,6 +68,10 @@ void proc_wev_cb(struct ev_loop *loop, ev_timer *w, int revents) { ...@@ -68,6 +68,10 @@ void proc_wev_cb(struct ev_loop *loop, ev_timer *w, int revents) {
} }
} // namespace } // namespace
DownstreamAddrGroup::DownstreamAddrGroup() : retired{false} {}
DownstreamAddrGroup::~DownstreamAddrGroup() {}
// DownstreamKey is used to index SharedDownstreamAddr in order to // DownstreamKey is used to index SharedDownstreamAddr in order to
// find the same configuration. // find the same configuration.
using DownstreamKey = std::tuple< using DownstreamKey = std::tuple<
...@@ -185,6 +189,10 @@ void Worker::replace_downstream_config( ...@@ -185,6 +189,10 @@ void Worker::replace_downstream_config(
dst = std::make_shared<DownstreamAddrGroup>(); dst = std::make_shared<DownstreamAddrGroup>();
dst->pattern = dst->pattern =
ImmutableString{std::begin(src.pattern), std::end(src.pattern)}; ImmutableString{std::begin(src.pattern), std::end(src.pattern)};
#ifdef HAVE_MRUBY
dst->mruby_ctx = mruby::create_mruby_context(src.mruby_file);
assert(dst->mruby_ctx);
#endif // HAVE_MRUBY
auto shared_addr = std::make_shared<SharedDownstreamAddr>(); auto shared_addr = std::make_shared<SharedDownstreamAddr>();
......
...@@ -183,7 +183,8 @@ struct SharedDownstreamAddr { ...@@ -183,7 +183,8 @@ struct SharedDownstreamAddr {
}; };
struct DownstreamAddrGroup { struct DownstreamAddrGroup {
DownstreamAddrGroup() : retired{false} {}; DownstreamAddrGroup();
~DownstreamAddrGroup();
DownstreamAddrGroup(const DownstreamAddrGroup &) = delete; DownstreamAddrGroup(const DownstreamAddrGroup &) = delete;
DownstreamAddrGroup(DownstreamAddrGroup &&) = delete; DownstreamAddrGroup(DownstreamAddrGroup &&) = delete;
...@@ -192,6 +193,9 @@ struct DownstreamAddrGroup { ...@@ -192,6 +193,9 @@ struct DownstreamAddrGroup {
ImmutableString pattern; ImmutableString pattern;
std::shared_ptr<SharedDownstreamAddr> shared_addr; std::shared_ptr<SharedDownstreamAddr> shared_addr;
#ifdef HAVE_MRUBY
std::unique_ptr<mruby::MRubyContext> mruby_ctx;
#endif // HAVE_MRUBY
// true if this group is no longer used for new request. If this is // true if this group is no longer used for new request. If this is
// true, the connection made using one of address in shared_addr // true, the connection made using one of address in shared_addr
// must not be pooled. // must not be pooled.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment