nghttpx: Check allowed operations per phase

This commit is contained in:
Tatsuhiro Tsujikawa 2015-09-05 01:07:29 +09:00
parent bddc4a0a04
commit 45e0d42c51
4 changed files with 39 additions and 5 deletions

View File

@ -44,14 +44,15 @@ MRubyContext::MRubyContext(mrb_state *mrb, RProc *on_request_proc,
MRubyContext::~MRubyContext() { mrb_close(mrb_); }
int MRubyContext::run_request_proc(Downstream *downstream, RProc *proc) {
int MRubyContext::run_request_proc(Downstream *downstream, RProc *proc,
int phase) {
if (!proc || running_) {
return 0;
}
running_ = true;
MRubyAssocData data{downstream};
MRubyAssocData data{downstream, phase};
mrb_->ud = &data;
@ -92,11 +93,11 @@ int MRubyContext::run_request_proc(Downstream *downstream, RProc *proc) {
}
int MRubyContext::run_on_request_proc(Downstream *downstream) {
return run_request_proc(downstream, on_request_proc_);
return run_request_proc(downstream, on_request_proc_, PHASE_REQUEST);
}
int MRubyContext::run_on_response_proc(Downstream *downstream) {
return run_request_proc(downstream, on_response_proc_);
return run_request_proc(downstream, on_response_proc_, PHASE_RESPONSE);
}
void MRubyContext::delete_downstream(Downstream *downstream) {
@ -188,6 +189,12 @@ mrb_sym intern_ptr(mrb_state *mrb, void *ptr) {
return mrb_intern(mrb, reinterpret_cast<const char *>(&p), sizeof(p));
}
void check_phase(mrb_state *mrb, int phase, int phase_mask) {
if ((phase & phase_mask) == 0) {
mrb_raise(mrb, E_RUNTIME_ERROR, "operation was not allowed in this phase");
}
}
} // namespace mruby
} // namespace shrpx

View File

@ -46,7 +46,7 @@ public:
int run_on_request_proc(Downstream *downstream);
int run_on_response_proc(Downstream *downstream);
int run_request_proc(Downstream *downstream, RProc *proc);
int run_request_proc(Downstream *downstream, RProc *proc, int phase);
void delete_downstream(Downstream *downstream);
@ -57,8 +57,15 @@ private:
bool running_;
};
enum {
PHASE_NONE = 0,
PHASE_REQUEST = 1,
PHASE_RESPONSE = 1 << 1,
};
struct MRubyAssocData {
Downstream *downstream;
int phase;
bool request_headers_dirty;
bool response_headers_dirty;
};
@ -70,6 +77,10 @@ std::unique_ptr<MRubyContext> create_mruby_context();
// Return interned |ptr|.
mrb_sym intern_ptr(mrb_state *mrb, void *ptr);
// Checks that |phase| is set in |phase_mask|. If not set, raise
// exception.
void check_phase(mrb_state *mrb, int phase, int phase_mask);
} // namespace mruby
} // namespace shrpx

View File

@ -90,6 +90,10 @@ void init_module(mrb_state *mrb) {
mrb_define_class_method(mrb, module, "run", run,
MRB_ARGS_REQ(1) | MRB_ARGS_BLOCK());
mrb_define_const(mrb, module, "REQUEST_PHASE",
mrb_fixnum_value(PHASE_REQUEST));
mrb_define_const(mrb, module, "RESPONSE_PHASE",
mrb_fixnum_value(PHASE_RESPONSE));
init_env_class(mrb, module);
init_request_class(mrb, module);

View File

@ -76,6 +76,8 @@ mrb_value request_set_method(mrb_state *mrb, mrb_value self) {
auto data = static_cast<MRubyAssocData *>(mrb->ud);
auto downstream = data->downstream;
check_phase(mrb, data->phase, PHASE_REQUEST);
const char *method;
mrb_int n;
mrb_get_args(mrb, "s", &method, &n);
@ -109,6 +111,8 @@ mrb_value request_set_authority(mrb_state *mrb, mrb_value self) {
auto data = static_cast<MRubyAssocData *>(mrb->ud);
auto downstream = data->downstream;
check_phase(mrb, data->phase, PHASE_REQUEST);
const char *authority;
mrb_int n;
mrb_get_args(mrb, "s", &authority, &n);
@ -137,6 +141,8 @@ mrb_value request_set_scheme(mrb_state *mrb, mrb_value self) {
auto data = static_cast<MRubyAssocData *>(mrb->ud);
auto downstream = data->downstream;
check_phase(mrb, data->phase, PHASE_REQUEST);
const char *scheme;
mrb_int n;
mrb_get_args(mrb, "s", &scheme, &n);
@ -165,6 +171,8 @@ mrb_value request_set_path(mrb_state *mrb, mrb_value self) {
auto data = static_cast<MRubyAssocData *>(mrb->ud);
auto downstream = data->downstream;
check_phase(mrb, data->phase, PHASE_REQUEST);
const char *path;
mrb_int pathlen;
mrb_get_args(mrb, "s", &path, &pathlen);
@ -188,6 +196,8 @@ mrb_value request_mod_header(mrb_state *mrb, mrb_value self, bool repl) {
auto data = static_cast<MRubyAssocData *>(mrb->ud);
auto downstream = data->downstream;
check_phase(mrb, data->phase, PHASE_REQUEST);
mrb_value key, values;
mrb_get_args(mrb, "oo", &key, &values);
@ -244,6 +254,8 @@ mrb_value request_clear_headers(mrb_state *mrb, mrb_value self) {
auto data = static_cast<MRubyAssocData *>(mrb->ud);
auto downstream = data->downstream;
check_phase(mrb, data->phase, PHASE_REQUEST);
downstream->clear_request_headers();
return mrb_nil_value();