12c593315Sopenharmony_ci/* 22c593315Sopenharmony_ci * nghttp2 - HTTP/2 C Library 32c593315Sopenharmony_ci * 42c593315Sopenharmony_ci * Copyright (c) 2015 Tatsuhiro Tsujikawa 52c593315Sopenharmony_ci * 62c593315Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining 72c593315Sopenharmony_ci * a copy of this software and associated documentation files (the 82c593315Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 92c593315Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 102c593315Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to 112c593315Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 122c593315Sopenharmony_ci * the following conditions: 132c593315Sopenharmony_ci * 142c593315Sopenharmony_ci * The above copyright notice and this permission notice shall be 152c593315Sopenharmony_ci * included in all copies or substantial portions of the Software. 162c593315Sopenharmony_ci * 172c593315Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 182c593315Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 192c593315Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 202c593315Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 212c593315Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 222c593315Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 232c593315Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 242c593315Sopenharmony_ci */ 252c593315Sopenharmony_ci#include "shrpx_mruby_module_request.h" 262c593315Sopenharmony_ci 272c593315Sopenharmony_ci#include <mruby/variable.h> 282c593315Sopenharmony_ci#include <mruby/string.h> 292c593315Sopenharmony_ci#include <mruby/hash.h> 302c593315Sopenharmony_ci#include <mruby/array.h> 312c593315Sopenharmony_ci 322c593315Sopenharmony_ci#include "shrpx_downstream.h" 332c593315Sopenharmony_ci#include "shrpx_upstream.h" 342c593315Sopenharmony_ci#include "shrpx_client_handler.h" 352c593315Sopenharmony_ci#include "shrpx_mruby.h" 362c593315Sopenharmony_ci#include "shrpx_mruby_module.h" 372c593315Sopenharmony_ci#include "shrpx_log.h" 382c593315Sopenharmony_ci#include "util.h" 392c593315Sopenharmony_ci#include "http2.h" 402c593315Sopenharmony_ci 412c593315Sopenharmony_cinamespace shrpx { 422c593315Sopenharmony_ci 432c593315Sopenharmony_cinamespace mruby { 442c593315Sopenharmony_ci 452c593315Sopenharmony_cinamespace { 462c593315Sopenharmony_cimrb_value request_init(mrb_state *mrb, mrb_value self) { return self; } 472c593315Sopenharmony_ci} // namespace 482c593315Sopenharmony_ci 492c593315Sopenharmony_cinamespace { 502c593315Sopenharmony_cimrb_value request_get_http_version_major(mrb_state *mrb, mrb_value self) { 512c593315Sopenharmony_ci auto data = static_cast<MRubyAssocData *>(mrb->ud); 522c593315Sopenharmony_ci auto downstream = data->downstream; 532c593315Sopenharmony_ci const auto &req = downstream->request(); 542c593315Sopenharmony_ci return mrb_fixnum_value(req.http_major); 552c593315Sopenharmony_ci} 562c593315Sopenharmony_ci} // namespace 572c593315Sopenharmony_ci 582c593315Sopenharmony_cinamespace { 592c593315Sopenharmony_cimrb_value request_get_http_version_minor(mrb_state *mrb, mrb_value self) { 602c593315Sopenharmony_ci auto data = static_cast<MRubyAssocData *>(mrb->ud); 612c593315Sopenharmony_ci auto downstream = data->downstream; 622c593315Sopenharmony_ci const auto &req = downstream->request(); 632c593315Sopenharmony_ci return mrb_fixnum_value(req.http_minor); 642c593315Sopenharmony_ci} 652c593315Sopenharmony_ci} // namespace 662c593315Sopenharmony_ci 672c593315Sopenharmony_cinamespace { 682c593315Sopenharmony_cimrb_value request_get_method(mrb_state *mrb, mrb_value self) { 692c593315Sopenharmony_ci auto data = static_cast<MRubyAssocData *>(mrb->ud); 702c593315Sopenharmony_ci auto downstream = data->downstream; 712c593315Sopenharmony_ci const auto &req = downstream->request(); 722c593315Sopenharmony_ci auto method = http2::to_method_string(req.method); 732c593315Sopenharmony_ci 742c593315Sopenharmony_ci return mrb_str_new(mrb, method.c_str(), method.size()); 752c593315Sopenharmony_ci} 762c593315Sopenharmony_ci} // namespace 772c593315Sopenharmony_ci 782c593315Sopenharmony_cinamespace { 792c593315Sopenharmony_cimrb_value request_set_method(mrb_state *mrb, mrb_value self) { 802c593315Sopenharmony_ci auto data = static_cast<MRubyAssocData *>(mrb->ud); 812c593315Sopenharmony_ci auto downstream = data->downstream; 822c593315Sopenharmony_ci auto &req = downstream->request(); 832c593315Sopenharmony_ci 842c593315Sopenharmony_ci check_phase(mrb, data->phase, PHASE_REQUEST); 852c593315Sopenharmony_ci 862c593315Sopenharmony_ci const char *method; 872c593315Sopenharmony_ci mrb_int n; 882c593315Sopenharmony_ci mrb_get_args(mrb, "s", &method, &n); 892c593315Sopenharmony_ci if (n == 0) { 902c593315Sopenharmony_ci mrb_raise(mrb, E_RUNTIME_ERROR, "method must not be empty string"); 912c593315Sopenharmony_ci } 922c593315Sopenharmony_ci auto token = 932c593315Sopenharmony_ci http2::lookup_method_token(reinterpret_cast<const uint8_t *>(method), n); 942c593315Sopenharmony_ci if (token == -1) { 952c593315Sopenharmony_ci mrb_raise(mrb, E_RUNTIME_ERROR, "method not supported"); 962c593315Sopenharmony_ci } 972c593315Sopenharmony_ci 982c593315Sopenharmony_ci req.method = token; 992c593315Sopenharmony_ci 1002c593315Sopenharmony_ci return self; 1012c593315Sopenharmony_ci} 1022c593315Sopenharmony_ci} // namespace 1032c593315Sopenharmony_ci 1042c593315Sopenharmony_cinamespace { 1052c593315Sopenharmony_cimrb_value request_get_authority(mrb_state *mrb, mrb_value self) { 1062c593315Sopenharmony_ci auto data = static_cast<MRubyAssocData *>(mrb->ud); 1072c593315Sopenharmony_ci auto downstream = data->downstream; 1082c593315Sopenharmony_ci const auto &req = downstream->request(); 1092c593315Sopenharmony_ci 1102c593315Sopenharmony_ci return mrb_str_new(mrb, req.authority.c_str(), req.authority.size()); 1112c593315Sopenharmony_ci} 1122c593315Sopenharmony_ci} // namespace 1132c593315Sopenharmony_ci 1142c593315Sopenharmony_cinamespace { 1152c593315Sopenharmony_cimrb_value request_set_authority(mrb_state *mrb, mrb_value self) { 1162c593315Sopenharmony_ci auto data = static_cast<MRubyAssocData *>(mrb->ud); 1172c593315Sopenharmony_ci auto downstream = data->downstream; 1182c593315Sopenharmony_ci auto &req = downstream->request(); 1192c593315Sopenharmony_ci 1202c593315Sopenharmony_ci auto &balloc = downstream->get_block_allocator(); 1212c593315Sopenharmony_ci 1222c593315Sopenharmony_ci check_phase(mrb, data->phase, PHASE_REQUEST); 1232c593315Sopenharmony_ci 1242c593315Sopenharmony_ci const char *authority; 1252c593315Sopenharmony_ci mrb_int n; 1262c593315Sopenharmony_ci mrb_get_args(mrb, "s", &authority, &n); 1272c593315Sopenharmony_ci if (n == 0) { 1282c593315Sopenharmony_ci mrb_raise(mrb, E_RUNTIME_ERROR, "authority must not be empty string"); 1292c593315Sopenharmony_ci } 1302c593315Sopenharmony_ci 1312c593315Sopenharmony_ci req.authority = 1322c593315Sopenharmony_ci make_string_ref(balloc, StringRef{authority, static_cast<size_t>(n)}); 1332c593315Sopenharmony_ci 1342c593315Sopenharmony_ci return self; 1352c593315Sopenharmony_ci} 1362c593315Sopenharmony_ci} // namespace 1372c593315Sopenharmony_ci 1382c593315Sopenharmony_cinamespace { 1392c593315Sopenharmony_cimrb_value request_get_scheme(mrb_state *mrb, mrb_value self) { 1402c593315Sopenharmony_ci auto data = static_cast<MRubyAssocData *>(mrb->ud); 1412c593315Sopenharmony_ci auto downstream = data->downstream; 1422c593315Sopenharmony_ci const auto &req = downstream->request(); 1432c593315Sopenharmony_ci 1442c593315Sopenharmony_ci return mrb_str_new(mrb, req.scheme.c_str(), req.scheme.size()); 1452c593315Sopenharmony_ci} 1462c593315Sopenharmony_ci} // namespace 1472c593315Sopenharmony_ci 1482c593315Sopenharmony_cinamespace { 1492c593315Sopenharmony_cimrb_value request_set_scheme(mrb_state *mrb, mrb_value self) { 1502c593315Sopenharmony_ci auto data = static_cast<MRubyAssocData *>(mrb->ud); 1512c593315Sopenharmony_ci auto downstream = data->downstream; 1522c593315Sopenharmony_ci auto &req = downstream->request(); 1532c593315Sopenharmony_ci 1542c593315Sopenharmony_ci auto &balloc = downstream->get_block_allocator(); 1552c593315Sopenharmony_ci 1562c593315Sopenharmony_ci check_phase(mrb, data->phase, PHASE_REQUEST); 1572c593315Sopenharmony_ci 1582c593315Sopenharmony_ci const char *scheme; 1592c593315Sopenharmony_ci mrb_int n; 1602c593315Sopenharmony_ci mrb_get_args(mrb, "s", &scheme, &n); 1612c593315Sopenharmony_ci if (n == 0) { 1622c593315Sopenharmony_ci mrb_raise(mrb, E_RUNTIME_ERROR, "scheme must not be empty string"); 1632c593315Sopenharmony_ci } 1642c593315Sopenharmony_ci 1652c593315Sopenharmony_ci req.scheme = 1662c593315Sopenharmony_ci make_string_ref(balloc, StringRef{scheme, static_cast<size_t>(n)}); 1672c593315Sopenharmony_ci 1682c593315Sopenharmony_ci return self; 1692c593315Sopenharmony_ci} 1702c593315Sopenharmony_ci} // namespace 1712c593315Sopenharmony_ci 1722c593315Sopenharmony_cinamespace { 1732c593315Sopenharmony_cimrb_value request_get_path(mrb_state *mrb, mrb_value self) { 1742c593315Sopenharmony_ci auto data = static_cast<MRubyAssocData *>(mrb->ud); 1752c593315Sopenharmony_ci auto downstream = data->downstream; 1762c593315Sopenharmony_ci const auto &req = downstream->request(); 1772c593315Sopenharmony_ci 1782c593315Sopenharmony_ci return mrb_str_new(mrb, req.path.c_str(), req.path.size()); 1792c593315Sopenharmony_ci} 1802c593315Sopenharmony_ci} // namespace 1812c593315Sopenharmony_ci 1822c593315Sopenharmony_cinamespace { 1832c593315Sopenharmony_cimrb_value request_set_path(mrb_state *mrb, mrb_value self) { 1842c593315Sopenharmony_ci auto data = static_cast<MRubyAssocData *>(mrb->ud); 1852c593315Sopenharmony_ci auto downstream = data->downstream; 1862c593315Sopenharmony_ci auto &req = downstream->request(); 1872c593315Sopenharmony_ci 1882c593315Sopenharmony_ci auto &balloc = downstream->get_block_allocator(); 1892c593315Sopenharmony_ci 1902c593315Sopenharmony_ci check_phase(mrb, data->phase, PHASE_REQUEST); 1912c593315Sopenharmony_ci 1922c593315Sopenharmony_ci const char *path; 1932c593315Sopenharmony_ci mrb_int pathlen; 1942c593315Sopenharmony_ci mrb_get_args(mrb, "s", &path, &pathlen); 1952c593315Sopenharmony_ci 1962c593315Sopenharmony_ci req.path = 1972c593315Sopenharmony_ci make_string_ref(balloc, StringRef{path, static_cast<size_t>(pathlen)}); 1982c593315Sopenharmony_ci 1992c593315Sopenharmony_ci return self; 2002c593315Sopenharmony_ci} 2012c593315Sopenharmony_ci} // namespace 2022c593315Sopenharmony_ci 2032c593315Sopenharmony_cinamespace { 2042c593315Sopenharmony_cimrb_value request_get_headers(mrb_state *mrb, mrb_value self) { 2052c593315Sopenharmony_ci auto data = static_cast<MRubyAssocData *>(mrb->ud); 2062c593315Sopenharmony_ci auto downstream = data->downstream; 2072c593315Sopenharmony_ci const auto &req = downstream->request(); 2082c593315Sopenharmony_ci return create_headers_hash(mrb, req.fs.headers()); 2092c593315Sopenharmony_ci} 2102c593315Sopenharmony_ci} // namespace 2112c593315Sopenharmony_ci 2122c593315Sopenharmony_cinamespace { 2132c593315Sopenharmony_cimrb_value request_mod_header(mrb_state *mrb, mrb_value self, bool repl) { 2142c593315Sopenharmony_ci auto data = static_cast<MRubyAssocData *>(mrb->ud); 2152c593315Sopenharmony_ci auto downstream = data->downstream; 2162c593315Sopenharmony_ci auto &req = downstream->request(); 2172c593315Sopenharmony_ci auto &balloc = downstream->get_block_allocator(); 2182c593315Sopenharmony_ci 2192c593315Sopenharmony_ci check_phase(mrb, data->phase, PHASE_REQUEST); 2202c593315Sopenharmony_ci 2212c593315Sopenharmony_ci mrb_value key, values; 2222c593315Sopenharmony_ci mrb_get_args(mrb, "So", &key, &values); 2232c593315Sopenharmony_ci 2242c593315Sopenharmony_ci if (RSTRING_LEN(key) == 0) { 2252c593315Sopenharmony_ci mrb_raise(mrb, E_RUNTIME_ERROR, "empty key is not allowed"); 2262c593315Sopenharmony_ci } 2272c593315Sopenharmony_ci 2282c593315Sopenharmony_ci auto ai = mrb_gc_arena_save(mrb); 2292c593315Sopenharmony_ci 2302c593315Sopenharmony_ci key = mrb_funcall(mrb, key, "downcase", 0); 2312c593315Sopenharmony_ci 2322c593315Sopenharmony_ci auto keyref = 2332c593315Sopenharmony_ci make_string_ref(balloc, StringRef{RSTRING_PTR(key), 2342c593315Sopenharmony_ci static_cast<size_t>(RSTRING_LEN(key))}); 2352c593315Sopenharmony_ci 2362c593315Sopenharmony_ci mrb_gc_arena_restore(mrb, ai); 2372c593315Sopenharmony_ci 2382c593315Sopenharmony_ci auto token = http2::lookup_token(keyref.byte(), keyref.size()); 2392c593315Sopenharmony_ci 2402c593315Sopenharmony_ci if (repl) { 2412c593315Sopenharmony_ci size_t p = 0; 2422c593315Sopenharmony_ci auto &headers = req.fs.headers(); 2432c593315Sopenharmony_ci for (size_t i = 0; i < headers.size(); ++i) { 2442c593315Sopenharmony_ci auto &kv = headers[i]; 2452c593315Sopenharmony_ci if (kv.name == keyref) { 2462c593315Sopenharmony_ci continue; 2472c593315Sopenharmony_ci } 2482c593315Sopenharmony_ci if (i != p) { 2492c593315Sopenharmony_ci headers[p] = std::move(kv); 2502c593315Sopenharmony_ci } 2512c593315Sopenharmony_ci ++p; 2522c593315Sopenharmony_ci } 2532c593315Sopenharmony_ci headers.resize(p); 2542c593315Sopenharmony_ci } 2552c593315Sopenharmony_ci 2562c593315Sopenharmony_ci if (mrb_array_p(values)) { 2572c593315Sopenharmony_ci auto n = RARRAY_LEN(values); 2582c593315Sopenharmony_ci for (int i = 0; i < n; ++i) { 2592c593315Sopenharmony_ci auto value = mrb_ary_ref(mrb, values, i); 2602c593315Sopenharmony_ci if (!mrb_string_p(value)) { 2612c593315Sopenharmony_ci mrb_raise(mrb, E_RUNTIME_ERROR, "value must be string"); 2622c593315Sopenharmony_ci } 2632c593315Sopenharmony_ci 2642c593315Sopenharmony_ci req.fs.add_header_token( 2652c593315Sopenharmony_ci keyref, 2662c593315Sopenharmony_ci make_string_ref(balloc, 2672c593315Sopenharmony_ci StringRef{RSTRING_PTR(value), 2682c593315Sopenharmony_ci static_cast<size_t>(RSTRING_LEN(value))}), 2692c593315Sopenharmony_ci false, token); 2702c593315Sopenharmony_ci } 2712c593315Sopenharmony_ci } else if (mrb_string_p(values)) { 2722c593315Sopenharmony_ci req.fs.add_header_token( 2732c593315Sopenharmony_ci keyref, 2742c593315Sopenharmony_ci make_string_ref(balloc, 2752c593315Sopenharmony_ci StringRef{RSTRING_PTR(values), 2762c593315Sopenharmony_ci static_cast<size_t>(RSTRING_LEN(values))}), 2772c593315Sopenharmony_ci false, token); 2782c593315Sopenharmony_ci } else { 2792c593315Sopenharmony_ci mrb_raise(mrb, E_RUNTIME_ERROR, "value must be string"); 2802c593315Sopenharmony_ci } 2812c593315Sopenharmony_ci 2822c593315Sopenharmony_ci return mrb_nil_value(); 2832c593315Sopenharmony_ci} 2842c593315Sopenharmony_ci} // namespace 2852c593315Sopenharmony_ci 2862c593315Sopenharmony_cinamespace { 2872c593315Sopenharmony_cimrb_value request_set_header(mrb_state *mrb, mrb_value self) { 2882c593315Sopenharmony_ci return request_mod_header(mrb, self, true); 2892c593315Sopenharmony_ci} 2902c593315Sopenharmony_ci} // namespace 2912c593315Sopenharmony_ci 2922c593315Sopenharmony_cinamespace { 2932c593315Sopenharmony_cimrb_value request_add_header(mrb_state *mrb, mrb_value self) { 2942c593315Sopenharmony_ci return request_mod_header(mrb, self, false); 2952c593315Sopenharmony_ci} 2962c593315Sopenharmony_ci} // namespace 2972c593315Sopenharmony_ci 2982c593315Sopenharmony_cinamespace { 2992c593315Sopenharmony_cimrb_value request_clear_headers(mrb_state *mrb, mrb_value self) { 3002c593315Sopenharmony_ci auto data = static_cast<MRubyAssocData *>(mrb->ud); 3012c593315Sopenharmony_ci auto downstream = data->downstream; 3022c593315Sopenharmony_ci auto &req = downstream->request(); 3032c593315Sopenharmony_ci 3042c593315Sopenharmony_ci check_phase(mrb, data->phase, PHASE_REQUEST); 3052c593315Sopenharmony_ci 3062c593315Sopenharmony_ci req.fs.clear_headers(); 3072c593315Sopenharmony_ci 3082c593315Sopenharmony_ci return mrb_nil_value(); 3092c593315Sopenharmony_ci} 3102c593315Sopenharmony_ci} // namespace 3112c593315Sopenharmony_ci 3122c593315Sopenharmony_cinamespace { 3132c593315Sopenharmony_cimrb_value request_push(mrb_state *mrb, mrb_value self) { 3142c593315Sopenharmony_ci auto data = static_cast<MRubyAssocData *>(mrb->ud); 3152c593315Sopenharmony_ci auto downstream = data->downstream; 3162c593315Sopenharmony_ci auto upstream = downstream->get_upstream(); 3172c593315Sopenharmony_ci 3182c593315Sopenharmony_ci const char *uri; 3192c593315Sopenharmony_ci mrb_int len; 3202c593315Sopenharmony_ci mrb_get_args(mrb, "s", &uri, &len); 3212c593315Sopenharmony_ci 3222c593315Sopenharmony_ci upstream->initiate_push(downstream, StringRef{uri, static_cast<size_t>(len)}); 3232c593315Sopenharmony_ci 3242c593315Sopenharmony_ci return mrb_nil_value(); 3252c593315Sopenharmony_ci} 3262c593315Sopenharmony_ci} // namespace 3272c593315Sopenharmony_ci 3282c593315Sopenharmony_civoid init_request_class(mrb_state *mrb, RClass *module) { 3292c593315Sopenharmony_ci auto request_class = 3302c593315Sopenharmony_ci mrb_define_class_under(mrb, module, "Request", mrb->object_class); 3312c593315Sopenharmony_ci 3322c593315Sopenharmony_ci mrb_define_method(mrb, request_class, "initialize", request_init, 3332c593315Sopenharmony_ci MRB_ARGS_NONE()); 3342c593315Sopenharmony_ci mrb_define_method(mrb, request_class, "http_version_major", 3352c593315Sopenharmony_ci request_get_http_version_major, MRB_ARGS_NONE()); 3362c593315Sopenharmony_ci mrb_define_method(mrb, request_class, "http_version_minor", 3372c593315Sopenharmony_ci request_get_http_version_minor, MRB_ARGS_NONE()); 3382c593315Sopenharmony_ci mrb_define_method(mrb, request_class, "method", request_get_method, 3392c593315Sopenharmony_ci MRB_ARGS_NONE()); 3402c593315Sopenharmony_ci mrb_define_method(mrb, request_class, "method=", request_set_method, 3412c593315Sopenharmony_ci MRB_ARGS_REQ(1)); 3422c593315Sopenharmony_ci mrb_define_method(mrb, request_class, "authority", request_get_authority, 3432c593315Sopenharmony_ci MRB_ARGS_NONE()); 3442c593315Sopenharmony_ci mrb_define_method(mrb, request_class, "authority=", request_set_authority, 3452c593315Sopenharmony_ci MRB_ARGS_REQ(1)); 3462c593315Sopenharmony_ci mrb_define_method(mrb, request_class, "scheme", request_get_scheme, 3472c593315Sopenharmony_ci MRB_ARGS_NONE()); 3482c593315Sopenharmony_ci mrb_define_method(mrb, request_class, "scheme=", request_set_scheme, 3492c593315Sopenharmony_ci MRB_ARGS_REQ(1)); 3502c593315Sopenharmony_ci mrb_define_method(mrb, request_class, "path", request_get_path, 3512c593315Sopenharmony_ci MRB_ARGS_NONE()); 3522c593315Sopenharmony_ci mrb_define_method(mrb, request_class, "path=", request_set_path, 3532c593315Sopenharmony_ci MRB_ARGS_REQ(1)); 3542c593315Sopenharmony_ci mrb_define_method(mrb, request_class, "headers", request_get_headers, 3552c593315Sopenharmony_ci MRB_ARGS_NONE()); 3562c593315Sopenharmony_ci mrb_define_method(mrb, request_class, "add_header", request_add_header, 3572c593315Sopenharmony_ci MRB_ARGS_REQ(2)); 3582c593315Sopenharmony_ci mrb_define_method(mrb, request_class, "set_header", request_set_header, 3592c593315Sopenharmony_ci MRB_ARGS_REQ(2)); 3602c593315Sopenharmony_ci mrb_define_method(mrb, request_class, "clear_headers", request_clear_headers, 3612c593315Sopenharmony_ci MRB_ARGS_NONE()); 3622c593315Sopenharmony_ci mrb_define_method(mrb, request_class, "push", request_push, MRB_ARGS_REQ(1)); 3632c593315Sopenharmony_ci} 3642c593315Sopenharmony_ci 3652c593315Sopenharmony_ci} // namespace mruby 3662c593315Sopenharmony_ci 3672c593315Sopenharmony_ci} // namespace shrpx 368