nghttpx: Rewrite API; introduce Env object
This commit is contained in:
parent
a9338f1c0e
commit
bddc4a0a04
|
@ -134,6 +134,7 @@ if HAVE_MRUBY
|
|||
NGHTTPX_SRCS += \
|
||||
shrpx_mruby.cc shrpx_mruby.h \
|
||||
shrpx_mruby_module.cc shrpx_mruby_module.h \
|
||||
shrpx_mruby_module_env.cc shrpx_mruby_module_env.h \
|
||||
shrpx_mruby_module_request.cc shrpx_mruby_module_request.h \
|
||||
shrpx_mruby_module_response.cc shrpx_mruby_module_response.h
|
||||
endif # HAVE_MRUBY
|
||||
|
|
|
@ -34,6 +34,11 @@
|
|||
#include "shrpx_error.h"
|
||||
#include "shrpx_downstream_connection.h"
|
||||
#include "shrpx_downstream_queue.h"
|
||||
#include "shrpx_worker.h"
|
||||
#include "shrpx_http2_session.h"
|
||||
#ifdef HAVE_MRUBY
|
||||
#include "shrpx_mruby.h"
|
||||
#endif // HAVE_MRUBY
|
||||
#include "util.h"
|
||||
#include "http2.h"
|
||||
|
||||
|
@ -160,6 +165,12 @@ Downstream::~Downstream() {
|
|||
ev_timer_stop(loop, &upstream_wtimer_);
|
||||
ev_timer_stop(loop, &downstream_rtimer_);
|
||||
ev_timer_stop(loop, &downstream_wtimer_);
|
||||
|
||||
auto handler = upstream_->get_client_handler();
|
||||
auto worker = handler->get_worker();
|
||||
auto mruby_ctx = worker->get_mruby_context();
|
||||
|
||||
mruby_ctx->delete_downstream(this);
|
||||
}
|
||||
|
||||
// DownstreamConnection may refer to this object. Delete it now
|
||||
|
|
|
@ -99,6 +99,10 @@ int MRubyContext::run_on_response_proc(Downstream *downstream) {
|
|||
return run_request_proc(downstream, on_response_proc_);
|
||||
}
|
||||
|
||||
void MRubyContext::delete_downstream(Downstream *downstream) {
|
||||
delete_downstream_from_module(mrb_, downstream);
|
||||
}
|
||||
|
||||
// Based on
|
||||
// https://github.com/h2o/h2o/blob/master/lib/handler/mruby.c. It is
|
||||
// very hard to write these kind of code because mruby has almost no
|
||||
|
@ -144,6 +148,13 @@ RProc *compile(mrb_state *mrb, const char *filename) {
|
|||
}
|
||||
|
||||
std::unique_ptr<MRubyContext> create_mruby_context() {
|
||||
auto req_file = get_config()->request_phase_file.get();
|
||||
auto res_file = get_config()->response_phase_file.get();
|
||||
|
||||
if (!req_file && !res_file) {
|
||||
return make_unique<MRubyContext>(nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
auto mrb = mrb_open();
|
||||
if (mrb == nullptr) {
|
||||
LOG(ERROR) << "mrb_open failed";
|
||||
|
@ -152,9 +163,6 @@ std::unique_ptr<MRubyContext> create_mruby_context() {
|
|||
|
||||
init_module(mrb);
|
||||
|
||||
auto req_file = get_config()->request_phase_file.get();
|
||||
auto res_file = get_config()->response_phase_file.get();
|
||||
|
||||
auto req_proc = compile(mrb, req_file);
|
||||
|
||||
if (req_file && !req_proc) {
|
||||
|
@ -174,6 +182,12 @@ std::unique_ptr<MRubyContext> create_mruby_context() {
|
|||
return make_unique<MRubyContext>(mrb, req_proc, res_proc);
|
||||
}
|
||||
|
||||
mrb_sym intern_ptr(mrb_state *mrb, void *ptr) {
|
||||
auto p = reinterpret_cast<uintptr_t>(ptr);
|
||||
|
||||
return mrb_intern(mrb, reinterpret_cast<const char *>(&p), sizeof(p));
|
||||
}
|
||||
|
||||
} // namespace mruby
|
||||
|
||||
} // namespace shrpx
|
||||
|
|
|
@ -48,6 +48,8 @@ public:
|
|||
|
||||
int run_request_proc(Downstream *downstream, RProc *proc);
|
||||
|
||||
void delete_downstream(Downstream *downstream);
|
||||
|
||||
private:
|
||||
mrb_state *mrb_;
|
||||
RProc *on_request_proc_;
|
||||
|
@ -65,6 +67,9 @@ RProc *compile(mrb_state *mrb, const char *filename);
|
|||
|
||||
std::unique_ptr<MRubyContext> create_mruby_context();
|
||||
|
||||
// Return interned |ptr|.
|
||||
mrb_sym intern_ptr(mrb_state *mrb, void *ptr);
|
||||
|
||||
} // namespace mruby
|
||||
|
||||
} // namespace shrpx
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <mruby/array.h>
|
||||
|
||||
#include "shrpx_mruby.h"
|
||||
#include "shrpx_mruby_module_env.h"
|
||||
#include "shrpx_mruby_module_request.h"
|
||||
#include "shrpx_mruby_module_response.h"
|
||||
|
||||
|
@ -49,21 +50,48 @@ mrb_value run(mrb_state *mrb, mrb_value self) {
|
|||
}
|
||||
|
||||
auto module = mrb_module_get(mrb, "Nghttpx");
|
||||
auto request_class = mrb_class_get_under(mrb, module, "Request");
|
||||
auto response_class = mrb_class_get_under(mrb, module, "Response");
|
||||
|
||||
std::array<mrb_value, 2> args{{mrb_obj_new(mrb, response_class, 0, nullptr),
|
||||
mrb_obj_new(mrb, request_class, 0, nullptr)}};
|
||||
auto env_sym = mrb_intern_lit(mrb, "env");
|
||||
auto env = mrb_obj_iv_get(mrb, reinterpret_cast<RObject *>(module), env_sym);
|
||||
|
||||
if (mrb_nil_p(env)) {
|
||||
auto env_class = mrb_class_get_under(mrb, module, "Env");
|
||||
auto request_class = mrb_class_get_under(mrb, module, "Request");
|
||||
auto response_class = mrb_class_get_under(mrb, module, "Response");
|
||||
|
||||
env = mrb_obj_new(mrb, env_class, 0, nullptr);
|
||||
auto req = mrb_obj_new(mrb, request_class, 0, nullptr);
|
||||
auto resp = mrb_obj_new(mrb, response_class, 0, nullptr);
|
||||
|
||||
mrb_iv_set(mrb, env, mrb_intern_lit(mrb, "req"), req);
|
||||
mrb_iv_set(mrb, env, mrb_intern_lit(mrb, "resp"), resp);
|
||||
|
||||
mrb_obj_iv_set(mrb, reinterpret_cast<RObject *>(module), env_sym, env);
|
||||
}
|
||||
|
||||
std::array<mrb_value, 1> args{{env}};
|
||||
return mrb_yield_argv(mrb, b, args.size(), args.data());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void delete_downstream_from_module(mrb_state *mrb, Downstream *downstream) {
|
||||
auto module = mrb_module_get(mrb, "Nghttpx");
|
||||
auto env = mrb_obj_iv_get(mrb, reinterpret_cast<RObject *>(module),
|
||||
mrb_intern_lit(mrb, "env"));
|
||||
if (mrb_nil_p(env)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mrb_iv_remove(mrb, env, intern_ptr(mrb, downstream));
|
||||
}
|
||||
|
||||
void init_module(mrb_state *mrb) {
|
||||
auto module = mrb_define_module(mrb, "Nghttpx");
|
||||
|
||||
mrb_define_class_method(mrb, module, "run", run,
|
||||
MRB_ARGS_REQ(1) | MRB_ARGS_BLOCK());
|
||||
|
||||
init_env_class(mrb, module);
|
||||
init_request_class(mrb, module);
|
||||
init_response_class(mrb, module);
|
||||
}
|
||||
|
|
|
@ -35,10 +35,14 @@ using namespace nghttp2;
|
|||
|
||||
namespace shrpx {
|
||||
|
||||
class Downstream;
|
||||
|
||||
namespace mruby {
|
||||
|
||||
void init_module(mrb_state *mrb);
|
||||
|
||||
void delete_downstream_from_module(mrb_state *mrb, Downstream *downstream);
|
||||
|
||||
mrb_value create_headers_hash(mrb_state *mrb, const Headers &headers);
|
||||
|
||||
} // namespace mruby
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* nghttp2 - HTTP/2 C Library
|
||||
*
|
||||
* Copyright (c) 2015 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "shrpx_mruby_module_env.h"
|
||||
|
||||
#include <mruby/variable.h>
|
||||
#include <mruby/string.h>
|
||||
#include <mruby/hash.h>
|
||||
#include <mruby/array.h>
|
||||
|
||||
#include "shrpx_downstream.h"
|
||||
#include "shrpx_upstream.h"
|
||||
#include "shrpx_client_handler.h"
|
||||
#include "shrpx_mruby.h"
|
||||
#include "shrpx_mruby_module.h"
|
||||
#include "util.h"
|
||||
#include "http2.h"
|
||||
|
||||
namespace shrpx {
|
||||
|
||||
namespace mruby {
|
||||
|
||||
namespace {
|
||||
mrb_value env_init(mrb_state *mrb, mrb_value self) { return self; }
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
mrb_value env_get_req(mrb_state *mrb, mrb_value self) {
|
||||
return mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "req"));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
mrb_value env_get_resp(mrb_state *mrb, mrb_value self) {
|
||||
return mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "resp"));
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
mrb_value env_get_ctx(mrb_state *mrb, mrb_value self) {
|
||||
auto data = reinterpret_cast<MRubyAssocData *>(mrb->ud);
|
||||
auto downstream = data->downstream;
|
||||
|
||||
auto dsym = intern_ptr(mrb, downstream);
|
||||
|
||||
auto ctx = mrb_iv_get(mrb, self, dsym);
|
||||
if (mrb_nil_p(ctx)) {
|
||||
ctx = mrb_hash_new(mrb);
|
||||
mrb_iv_set(mrb, self, dsym, ctx);
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
mrb_value env_get_remote_addr(mrb_state *mrb, mrb_value self) {
|
||||
auto data = static_cast<MRubyAssocData *>(mrb->ud);
|
||||
auto downstream = data->downstream;
|
||||
auto upstream = downstream->get_upstream();
|
||||
auto handler = upstream->get_client_handler();
|
||||
|
||||
auto &ipaddr = handler->get_ipaddr();
|
||||
|
||||
return mrb_str_new(mrb, ipaddr.c_str(), ipaddr.size());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void init_env_class(mrb_state *mrb, RClass *module) {
|
||||
auto env_class =
|
||||
mrb_define_class_under(mrb, module, "Env", mrb->object_class);
|
||||
|
||||
mrb_define_method(mrb, env_class, "initialize", env_init, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, env_class, "req", env_get_req, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, env_class, "resp", env_get_resp, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, env_class, "ctx", env_get_ctx, MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, env_class, "remote_addr", env_get_remote_addr,
|
||||
MRB_ARGS_NONE());
|
||||
}
|
||||
|
||||
} // namespace mruby
|
||||
|
||||
} // namespace shrpx
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* nghttp2 - HTTP/2 C Library
|
||||
*
|
||||
* Copyright (c) 2015 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef SHRPX_MRUBY_MODULE_ENV_H
|
||||
#define SHRPX_MRUBY_MODULE_ENV_H
|
||||
|
||||
#include "shrpx.h"
|
||||
|
||||
#include <mruby.h>
|
||||
|
||||
using namespace nghttp2;
|
||||
|
||||
namespace shrpx {
|
||||
|
||||
namespace mruby {
|
||||
|
||||
void init_env_class(mrb_state *mrb, RClass *module);
|
||||
|
||||
} // namespace mruby
|
||||
|
||||
} // namespace shrpx
|
||||
|
||||
#endif // SHRPX_MRUBY_MODULE_ENV_H
|
|
@ -250,19 +250,6 @@ mrb_value request_clear_headers(mrb_state *mrb, mrb_value self) {
|
|||
}
|
||||
} // namespace
|
||||
|
||||
namespace {
|
||||
mrb_value request_get_remote_addr(mrb_state *mrb, mrb_value self) {
|
||||
auto data = static_cast<MRubyAssocData *>(mrb->ud);
|
||||
auto downstream = data->downstream;
|
||||
auto upstream = downstream->get_upstream();
|
||||
auto handler = upstream->get_client_handler();
|
||||
|
||||
auto &ipaddr = handler->get_ipaddr();
|
||||
|
||||
return mrb_str_new(mrb, ipaddr.c_str(), ipaddr.size());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
void init_request_class(mrb_state *mrb, RClass *module) {
|
||||
auto request_class =
|
||||
mrb_define_class_under(mrb, module, "Request", mrb->object_class);
|
||||
|
@ -297,8 +284,6 @@ void init_request_class(mrb_state *mrb, RClass *module) {
|
|||
MRB_ARGS_REQ(2));
|
||||
mrb_define_method(mrb, request_class, "clear_headers", request_clear_headers,
|
||||
MRB_ARGS_NONE());
|
||||
mrb_define_method(mrb, request_class, "remote_addr", request_get_remote_addr,
|
||||
MRB_ARGS_NONE());
|
||||
}
|
||||
|
||||
} // namespace mruby
|
||||
|
|
Loading…
Reference in New Issue