nghttpx: Rewrite API; introduce Env object
This commit is contained in:
parent
a9338f1c0e
commit
bddc4a0a04
|
@ -134,6 +134,7 @@ if HAVE_MRUBY
|
||||||
NGHTTPX_SRCS += \
|
NGHTTPX_SRCS += \
|
||||||
shrpx_mruby.cc shrpx_mruby.h \
|
shrpx_mruby.cc shrpx_mruby.h \
|
||||||
shrpx_mruby_module.cc shrpx_mruby_module.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_request.cc shrpx_mruby_module_request.h \
|
||||||
shrpx_mruby_module_response.cc shrpx_mruby_module_response.h
|
shrpx_mruby_module_response.cc shrpx_mruby_module_response.h
|
||||||
endif # HAVE_MRUBY
|
endif # HAVE_MRUBY
|
||||||
|
|
|
@ -34,6 +34,11 @@
|
||||||
#include "shrpx_error.h"
|
#include "shrpx_error.h"
|
||||||
#include "shrpx_downstream_connection.h"
|
#include "shrpx_downstream_connection.h"
|
||||||
#include "shrpx_downstream_queue.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 "util.h"
|
||||||
#include "http2.h"
|
#include "http2.h"
|
||||||
|
|
||||||
|
@ -160,6 +165,12 @@ Downstream::~Downstream() {
|
||||||
ev_timer_stop(loop, &upstream_wtimer_);
|
ev_timer_stop(loop, &upstream_wtimer_);
|
||||||
ev_timer_stop(loop, &downstream_rtimer_);
|
ev_timer_stop(loop, &downstream_rtimer_);
|
||||||
ev_timer_stop(loop, &downstream_wtimer_);
|
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
|
// 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_);
|
return run_request_proc(downstream, on_response_proc_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MRubyContext::delete_downstream(Downstream *downstream) {
|
||||||
|
delete_downstream_from_module(mrb_, downstream);
|
||||||
|
}
|
||||||
|
|
||||||
// Based on
|
// Based on
|
||||||
// https://github.com/h2o/h2o/blob/master/lib/handler/mruby.c. It is
|
// 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
|
// 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() {
|
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();
|
auto mrb = mrb_open();
|
||||||
if (mrb == nullptr) {
|
if (mrb == nullptr) {
|
||||||
LOG(ERROR) << "mrb_open failed";
|
LOG(ERROR) << "mrb_open failed";
|
||||||
|
@ -152,9 +163,6 @@ std::unique_ptr<MRubyContext> create_mruby_context() {
|
||||||
|
|
||||||
init_module(mrb);
|
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);
|
auto req_proc = compile(mrb, req_file);
|
||||||
|
|
||||||
if (req_file && !req_proc) {
|
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);
|
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 mruby
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -48,6 +48,8 @@ public:
|
||||||
|
|
||||||
int run_request_proc(Downstream *downstream, RProc *proc);
|
int run_request_proc(Downstream *downstream, RProc *proc);
|
||||||
|
|
||||||
|
void delete_downstream(Downstream *downstream);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mrb_state *mrb_;
|
mrb_state *mrb_;
|
||||||
RProc *on_request_proc_;
|
RProc *on_request_proc_;
|
||||||
|
@ -65,6 +67,9 @@ RProc *compile(mrb_state *mrb, const char *filename);
|
||||||
|
|
||||||
std::unique_ptr<MRubyContext> create_mruby_context();
|
std::unique_ptr<MRubyContext> create_mruby_context();
|
||||||
|
|
||||||
|
// Return interned |ptr|.
|
||||||
|
mrb_sym intern_ptr(mrb_state *mrb, void *ptr);
|
||||||
|
|
||||||
} // namespace mruby
|
} // namespace mruby
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <mruby/array.h>
|
#include <mruby/array.h>
|
||||||
|
|
||||||
#include "shrpx_mruby.h"
|
#include "shrpx_mruby.h"
|
||||||
|
#include "shrpx_mruby_module_env.h"
|
||||||
#include "shrpx_mruby_module_request.h"
|
#include "shrpx_mruby_module_request.h"
|
||||||
#include "shrpx_mruby_module_response.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 module = mrb_module_get(mrb, "Nghttpx");
|
||||||
|
|
||||||
|
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 request_class = mrb_class_get_under(mrb, module, "Request");
|
||||||
auto response_class = mrb_class_get_under(mrb, module, "Response");
|
auto response_class = mrb_class_get_under(mrb, module, "Response");
|
||||||
|
|
||||||
std::array<mrb_value, 2> args{{mrb_obj_new(mrb, response_class, 0, nullptr),
|
env = mrb_obj_new(mrb, env_class, 0, nullptr);
|
||||||
mrb_obj_new(mrb, request_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());
|
return mrb_yield_argv(mrb, b, args.size(), args.data());
|
||||||
}
|
}
|
||||||
} // namespace
|
} // 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) {
|
void init_module(mrb_state *mrb) {
|
||||||
auto module = mrb_define_module(mrb, "Nghttpx");
|
auto module = mrb_define_module(mrb, "Nghttpx");
|
||||||
|
|
||||||
mrb_define_class_method(mrb, module, "run", run,
|
mrb_define_class_method(mrb, module, "run", run,
|
||||||
MRB_ARGS_REQ(1) | MRB_ARGS_BLOCK());
|
MRB_ARGS_REQ(1) | MRB_ARGS_BLOCK());
|
||||||
|
|
||||||
|
init_env_class(mrb, module);
|
||||||
init_request_class(mrb, module);
|
init_request_class(mrb, module);
|
||||||
init_response_class(mrb, module);
|
init_response_class(mrb, module);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,10 +35,14 @@ using namespace nghttp2;
|
||||||
|
|
||||||
namespace shrpx {
|
namespace shrpx {
|
||||||
|
|
||||||
|
class Downstream;
|
||||||
|
|
||||||
namespace mruby {
|
namespace mruby {
|
||||||
|
|
||||||
void init_module(mrb_state *mrb);
|
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);
|
mrb_value create_headers_hash(mrb_state *mrb, const Headers &headers);
|
||||||
|
|
||||||
} // namespace mruby
|
} // 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
|
||||||
|
|
||||||
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) {
|
void init_request_class(mrb_state *mrb, RClass *module) {
|
||||||
auto request_class =
|
auto request_class =
|
||||||
mrb_define_class_under(mrb, module, "Request", mrb->object_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_ARGS_REQ(2));
|
||||||
mrb_define_method(mrb, request_class, "clear_headers", request_clear_headers,
|
mrb_define_method(mrb, request_class, "clear_headers", request_clear_headers,
|
||||||
MRB_ARGS_NONE());
|
MRB_ARGS_NONE());
|
||||||
mrb_define_method(mrb, request_class, "remote_addr", request_get_remote_addr,
|
|
||||||
MRB_ARGS_NONE());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mruby
|
} // namespace mruby
|
||||||
|
|
Loading…
Reference in New Issue