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_); } 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_) { if (!proc || running_) {
return 0; return 0;
} }
running_ = true; running_ = true;
MRubyAssocData data{downstream}; MRubyAssocData data{downstream, phase};
mrb_->ud = &data; mrb_->ud = &data;
@ -92,11 +93,11 @@ int MRubyContext::run_request_proc(Downstream *downstream, RProc *proc) {
} }
int MRubyContext::run_on_request_proc(Downstream *downstream) { 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) { 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) { 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)); 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 mruby
} // namespace shrpx } // namespace shrpx

View File

@ -46,7 +46,7 @@ public:
int run_on_request_proc(Downstream *downstream); int run_on_request_proc(Downstream *downstream);
int run_on_response_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); void delete_downstream(Downstream *downstream);
@ -57,8 +57,15 @@ private:
bool running_; bool running_;
}; };
enum {
PHASE_NONE = 0,
PHASE_REQUEST = 1,
PHASE_RESPONSE = 1 << 1,
};
struct MRubyAssocData { struct MRubyAssocData {
Downstream *downstream; Downstream *downstream;
int phase;
bool request_headers_dirty; bool request_headers_dirty;
bool response_headers_dirty; bool response_headers_dirty;
}; };
@ -70,6 +77,10 @@ std::unique_ptr<MRubyContext> create_mruby_context();
// Return interned |ptr|. // Return interned |ptr|.
mrb_sym intern_ptr(mrb_state *mrb, void *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 mruby
} // namespace shrpx } // namespace shrpx

View File

@ -90,6 +90,10 @@ void init_module(mrb_state *mrb) {
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());
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_env_class(mrb, module);
init_request_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 data = static_cast<MRubyAssocData *>(mrb->ud);
auto downstream = data->downstream; auto downstream = data->downstream;
check_phase(mrb, data->phase, PHASE_REQUEST);
const char *method; const char *method;
mrb_int n; mrb_int n;
mrb_get_args(mrb, "s", &method, &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 data = static_cast<MRubyAssocData *>(mrb->ud);
auto downstream = data->downstream; auto downstream = data->downstream;
check_phase(mrb, data->phase, PHASE_REQUEST);
const char *authority; const char *authority;
mrb_int n; mrb_int n;
mrb_get_args(mrb, "s", &authority, &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 data = static_cast<MRubyAssocData *>(mrb->ud);
auto downstream = data->downstream; auto downstream = data->downstream;
check_phase(mrb, data->phase, PHASE_REQUEST);
const char *scheme; const char *scheme;
mrb_int n; mrb_int n;
mrb_get_args(mrb, "s", &scheme, &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 data = static_cast<MRubyAssocData *>(mrb->ud);
auto downstream = data->downstream; auto downstream = data->downstream;
check_phase(mrb, data->phase, PHASE_REQUEST);
const char *path; const char *path;
mrb_int pathlen; mrb_int pathlen;
mrb_get_args(mrb, "s", &path, &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 data = static_cast<MRubyAssocData *>(mrb->ud);
auto downstream = data->downstream; auto downstream = data->downstream;
check_phase(mrb, data->phase, PHASE_REQUEST);
mrb_value key, values; mrb_value key, values;
mrb_get_args(mrb, "oo", &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 data = static_cast<MRubyAssocData *>(mrb->ud);
auto downstream = data->downstream; auto downstream = data->downstream;
check_phase(mrb, data->phase, PHASE_REQUEST);
downstream->clear_request_headers(); downstream->clear_request_headers();
return mrb_nil_value(); return mrb_nil_value();