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_response.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 response_init(mrb_state *mrb, mrb_value self) { return self; } 472c593315Sopenharmony_ci} // namespace 482c593315Sopenharmony_ci 492c593315Sopenharmony_cinamespace { 502c593315Sopenharmony_cimrb_value response_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 &resp = downstream->response(); 542c593315Sopenharmony_ci return mrb_fixnum_value(resp.http_major); 552c593315Sopenharmony_ci} 562c593315Sopenharmony_ci} // namespace 572c593315Sopenharmony_ci 582c593315Sopenharmony_cinamespace { 592c593315Sopenharmony_cimrb_value response_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 &resp = downstream->response(); 632c593315Sopenharmony_ci return mrb_fixnum_value(resp.http_minor); 642c593315Sopenharmony_ci} 652c593315Sopenharmony_ci} // namespace 662c593315Sopenharmony_ci 672c593315Sopenharmony_cinamespace { 682c593315Sopenharmony_cimrb_value response_get_status(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 &resp = downstream->response(); 722c593315Sopenharmony_ci return mrb_fixnum_value(resp.http_status); 732c593315Sopenharmony_ci} 742c593315Sopenharmony_ci} // namespace 752c593315Sopenharmony_ci 762c593315Sopenharmony_cinamespace { 772c593315Sopenharmony_cimrb_value response_set_status(mrb_state *mrb, mrb_value self) { 782c593315Sopenharmony_ci auto data = static_cast<MRubyAssocData *>(mrb->ud); 792c593315Sopenharmony_ci auto downstream = data->downstream; 802c593315Sopenharmony_ci auto &resp = downstream->response(); 812c593315Sopenharmony_ci 822c593315Sopenharmony_ci mrb_int status; 832c593315Sopenharmony_ci mrb_get_args(mrb, "i", &status); 842c593315Sopenharmony_ci // We don't support 1xx status code for mruby scripting yet. 852c593315Sopenharmony_ci if (status < 200 || status > 999) { 862c593315Sopenharmony_ci mrb_raise(mrb, E_RUNTIME_ERROR, 872c593315Sopenharmony_ci "invalid status; it should be [200, 999], inclusive"); 882c593315Sopenharmony_ci } 892c593315Sopenharmony_ci 902c593315Sopenharmony_ci resp.http_status = status; 912c593315Sopenharmony_ci 922c593315Sopenharmony_ci return self; 932c593315Sopenharmony_ci} 942c593315Sopenharmony_ci} // namespace 952c593315Sopenharmony_ci 962c593315Sopenharmony_cinamespace { 972c593315Sopenharmony_cimrb_value response_get_headers(mrb_state *mrb, mrb_value self) { 982c593315Sopenharmony_ci auto data = static_cast<MRubyAssocData *>(mrb->ud); 992c593315Sopenharmony_ci auto downstream = data->downstream; 1002c593315Sopenharmony_ci const auto &resp = downstream->response(); 1012c593315Sopenharmony_ci 1022c593315Sopenharmony_ci return create_headers_hash(mrb, resp.fs.headers()); 1032c593315Sopenharmony_ci} 1042c593315Sopenharmony_ci} // namespace 1052c593315Sopenharmony_ci 1062c593315Sopenharmony_cinamespace { 1072c593315Sopenharmony_cimrb_value response_mod_header(mrb_state *mrb, mrb_value self, bool repl) { 1082c593315Sopenharmony_ci auto data = static_cast<MRubyAssocData *>(mrb->ud); 1092c593315Sopenharmony_ci auto downstream = data->downstream; 1102c593315Sopenharmony_ci auto &resp = downstream->response(); 1112c593315Sopenharmony_ci auto &balloc = downstream->get_block_allocator(); 1122c593315Sopenharmony_ci 1132c593315Sopenharmony_ci mrb_value key, values; 1142c593315Sopenharmony_ci mrb_get_args(mrb, "So", &key, &values); 1152c593315Sopenharmony_ci 1162c593315Sopenharmony_ci if (RSTRING_LEN(key) == 0) { 1172c593315Sopenharmony_ci mrb_raise(mrb, E_RUNTIME_ERROR, "empty key is not allowed"); 1182c593315Sopenharmony_ci } 1192c593315Sopenharmony_ci 1202c593315Sopenharmony_ci auto ai = mrb_gc_arena_save(mrb); 1212c593315Sopenharmony_ci 1222c593315Sopenharmony_ci key = mrb_funcall(mrb, key, "downcase", 0); 1232c593315Sopenharmony_ci 1242c593315Sopenharmony_ci auto keyref = 1252c593315Sopenharmony_ci make_string_ref(balloc, StringRef{RSTRING_PTR(key), 1262c593315Sopenharmony_ci static_cast<size_t>(RSTRING_LEN(key))}); 1272c593315Sopenharmony_ci 1282c593315Sopenharmony_ci mrb_gc_arena_restore(mrb, ai); 1292c593315Sopenharmony_ci 1302c593315Sopenharmony_ci auto token = http2::lookup_token(keyref.byte(), keyref.size()); 1312c593315Sopenharmony_ci 1322c593315Sopenharmony_ci if (repl) { 1332c593315Sopenharmony_ci size_t p = 0; 1342c593315Sopenharmony_ci auto &headers = resp.fs.headers(); 1352c593315Sopenharmony_ci for (size_t i = 0; i < headers.size(); ++i) { 1362c593315Sopenharmony_ci auto &kv = headers[i]; 1372c593315Sopenharmony_ci if (kv.name == keyref) { 1382c593315Sopenharmony_ci continue; 1392c593315Sopenharmony_ci } 1402c593315Sopenharmony_ci if (i != p) { 1412c593315Sopenharmony_ci headers[p] = std::move(kv); 1422c593315Sopenharmony_ci } 1432c593315Sopenharmony_ci ++p; 1442c593315Sopenharmony_ci } 1452c593315Sopenharmony_ci headers.resize(p); 1462c593315Sopenharmony_ci } 1472c593315Sopenharmony_ci 1482c593315Sopenharmony_ci if (mrb_array_p(values)) { 1492c593315Sopenharmony_ci auto n = RARRAY_LEN(values); 1502c593315Sopenharmony_ci for (int i = 0; i < n; ++i) { 1512c593315Sopenharmony_ci auto value = mrb_ary_ref(mrb, values, i); 1522c593315Sopenharmony_ci if (!mrb_string_p(value)) { 1532c593315Sopenharmony_ci mrb_raise(mrb, E_RUNTIME_ERROR, "value must be string"); 1542c593315Sopenharmony_ci } 1552c593315Sopenharmony_ci 1562c593315Sopenharmony_ci resp.fs.add_header_token( 1572c593315Sopenharmony_ci keyref, 1582c593315Sopenharmony_ci make_string_ref(balloc, 1592c593315Sopenharmony_ci StringRef{RSTRING_PTR(value), 1602c593315Sopenharmony_ci static_cast<size_t>(RSTRING_LEN(value))}), 1612c593315Sopenharmony_ci false, token); 1622c593315Sopenharmony_ci } 1632c593315Sopenharmony_ci } else if (mrb_string_p(values)) { 1642c593315Sopenharmony_ci resp.fs.add_header_token( 1652c593315Sopenharmony_ci keyref, 1662c593315Sopenharmony_ci make_string_ref(balloc, 1672c593315Sopenharmony_ci StringRef{RSTRING_PTR(values), 1682c593315Sopenharmony_ci static_cast<size_t>(RSTRING_LEN(values))}), 1692c593315Sopenharmony_ci false, token); 1702c593315Sopenharmony_ci } else { 1712c593315Sopenharmony_ci mrb_raise(mrb, E_RUNTIME_ERROR, "value must be string"); 1722c593315Sopenharmony_ci } 1732c593315Sopenharmony_ci 1742c593315Sopenharmony_ci return mrb_nil_value(); 1752c593315Sopenharmony_ci} 1762c593315Sopenharmony_ci} // namespace 1772c593315Sopenharmony_ci 1782c593315Sopenharmony_cinamespace { 1792c593315Sopenharmony_cimrb_value response_set_header(mrb_state *mrb, mrb_value self) { 1802c593315Sopenharmony_ci return response_mod_header(mrb, self, true); 1812c593315Sopenharmony_ci} 1822c593315Sopenharmony_ci} // namespace 1832c593315Sopenharmony_ci 1842c593315Sopenharmony_cinamespace { 1852c593315Sopenharmony_cimrb_value response_add_header(mrb_state *mrb, mrb_value self) { 1862c593315Sopenharmony_ci return response_mod_header(mrb, self, false); 1872c593315Sopenharmony_ci} 1882c593315Sopenharmony_ci} // namespace 1892c593315Sopenharmony_ci 1902c593315Sopenharmony_cinamespace { 1912c593315Sopenharmony_cimrb_value response_clear_headers(mrb_state *mrb, mrb_value self) { 1922c593315Sopenharmony_ci auto data = static_cast<MRubyAssocData *>(mrb->ud); 1932c593315Sopenharmony_ci auto downstream = data->downstream; 1942c593315Sopenharmony_ci auto &resp = downstream->response(); 1952c593315Sopenharmony_ci 1962c593315Sopenharmony_ci resp.fs.clear_headers(); 1972c593315Sopenharmony_ci 1982c593315Sopenharmony_ci return mrb_nil_value(); 1992c593315Sopenharmony_ci} 2002c593315Sopenharmony_ci} // namespace 2012c593315Sopenharmony_ci 2022c593315Sopenharmony_cinamespace { 2032c593315Sopenharmony_cimrb_value response_return(mrb_state *mrb, mrb_value self) { 2042c593315Sopenharmony_ci auto data = static_cast<MRubyAssocData *>(mrb->ud); 2052c593315Sopenharmony_ci auto downstream = data->downstream; 2062c593315Sopenharmony_ci auto &req = downstream->request(); 2072c593315Sopenharmony_ci auto &resp = downstream->response(); 2082c593315Sopenharmony_ci int rv; 2092c593315Sopenharmony_ci 2102c593315Sopenharmony_ci auto &balloc = downstream->get_block_allocator(); 2112c593315Sopenharmony_ci 2122c593315Sopenharmony_ci if (downstream->get_response_state() == DownstreamState::MSG_COMPLETE) { 2132c593315Sopenharmony_ci mrb_raise(mrb, E_RUNTIME_ERROR, "response has already been committed"); 2142c593315Sopenharmony_ci } 2152c593315Sopenharmony_ci 2162c593315Sopenharmony_ci const char *val; 2172c593315Sopenharmony_ci mrb_int vallen; 2182c593315Sopenharmony_ci mrb_get_args(mrb, "|s", &val, &vallen); 2192c593315Sopenharmony_ci 2202c593315Sopenharmony_ci const uint8_t *body = nullptr; 2212c593315Sopenharmony_ci size_t bodylen = 0; 2222c593315Sopenharmony_ci 2232c593315Sopenharmony_ci if (resp.http_status == 0) { 2242c593315Sopenharmony_ci resp.http_status = 200; 2252c593315Sopenharmony_ci } 2262c593315Sopenharmony_ci 2272c593315Sopenharmony_ci if (downstream->expect_response_body() && vallen > 0) { 2282c593315Sopenharmony_ci body = reinterpret_cast<const uint8_t *>(val); 2292c593315Sopenharmony_ci bodylen = vallen; 2302c593315Sopenharmony_ci } 2312c593315Sopenharmony_ci 2322c593315Sopenharmony_ci auto cl = resp.fs.header(http2::HD_CONTENT_LENGTH); 2332c593315Sopenharmony_ci 2342c593315Sopenharmony_ci if (resp.http_status == 204 || 2352c593315Sopenharmony_ci (resp.http_status == 200 && req.method == HTTP_CONNECT)) { 2362c593315Sopenharmony_ci if (cl) { 2372c593315Sopenharmony_ci // Delete content-length here 2382c593315Sopenharmony_ci http2::erase_header(cl); 2392c593315Sopenharmony_ci } 2402c593315Sopenharmony_ci 2412c593315Sopenharmony_ci resp.fs.content_length = -1; 2422c593315Sopenharmony_ci } else { 2432c593315Sopenharmony_ci auto content_length = util::make_string_ref_uint(balloc, vallen); 2442c593315Sopenharmony_ci 2452c593315Sopenharmony_ci if (cl) { 2462c593315Sopenharmony_ci cl->value = content_length; 2472c593315Sopenharmony_ci } else { 2482c593315Sopenharmony_ci resp.fs.add_header_token(StringRef::from_lit("content-length"), 2492c593315Sopenharmony_ci content_length, false, http2::HD_CONTENT_LENGTH); 2502c593315Sopenharmony_ci } 2512c593315Sopenharmony_ci 2522c593315Sopenharmony_ci resp.fs.content_length = vallen; 2532c593315Sopenharmony_ci } 2542c593315Sopenharmony_ci 2552c593315Sopenharmony_ci auto date = resp.fs.header(http2::HD_DATE); 2562c593315Sopenharmony_ci if (!date) { 2572c593315Sopenharmony_ci auto lgconf = log_config(); 2582c593315Sopenharmony_ci lgconf->update_tstamp(std::chrono::system_clock::now()); 2592c593315Sopenharmony_ci resp.fs.add_header_token(StringRef::from_lit("date"), 2602c593315Sopenharmony_ci make_string_ref(balloc, lgconf->tstamp->time_http), 2612c593315Sopenharmony_ci false, http2::HD_DATE); 2622c593315Sopenharmony_ci } 2632c593315Sopenharmony_ci 2642c593315Sopenharmony_ci auto upstream = downstream->get_upstream(); 2652c593315Sopenharmony_ci 2662c593315Sopenharmony_ci rv = upstream->send_reply(downstream, body, bodylen); 2672c593315Sopenharmony_ci if (rv != 0) { 2682c593315Sopenharmony_ci mrb_raise(mrb, E_RUNTIME_ERROR, "could not send response"); 2692c593315Sopenharmony_ci } 2702c593315Sopenharmony_ci 2712c593315Sopenharmony_ci auto handler = upstream->get_client_handler(); 2722c593315Sopenharmony_ci 2732c593315Sopenharmony_ci handler->signal_write(); 2742c593315Sopenharmony_ci 2752c593315Sopenharmony_ci return self; 2762c593315Sopenharmony_ci} 2772c593315Sopenharmony_ci} // namespace 2782c593315Sopenharmony_ci 2792c593315Sopenharmony_cinamespace { 2802c593315Sopenharmony_cimrb_value response_send_info(mrb_state *mrb, mrb_value self) { 2812c593315Sopenharmony_ci auto data = static_cast<MRubyAssocData *>(mrb->ud); 2822c593315Sopenharmony_ci auto downstream = data->downstream; 2832c593315Sopenharmony_ci auto &resp = downstream->response(); 2842c593315Sopenharmony_ci int rv; 2852c593315Sopenharmony_ci 2862c593315Sopenharmony_ci if (downstream->get_response_state() == DownstreamState::MSG_COMPLETE) { 2872c593315Sopenharmony_ci mrb_raise(mrb, E_RUNTIME_ERROR, "response has already been committed"); 2882c593315Sopenharmony_ci } 2892c593315Sopenharmony_ci 2902c593315Sopenharmony_ci mrb_int http_status; 2912c593315Sopenharmony_ci mrb_value hash; 2922c593315Sopenharmony_ci mrb_get_args(mrb, "iH", &http_status, &hash); 2932c593315Sopenharmony_ci 2942c593315Sopenharmony_ci if (http_status / 100 != 1) { 2952c593315Sopenharmony_ci mrb_raise(mrb, E_RUNTIME_ERROR, 2962c593315Sopenharmony_ci "status_code must be in range [100, 199], inclusive"); 2972c593315Sopenharmony_ci } 2982c593315Sopenharmony_ci 2992c593315Sopenharmony_ci auto &balloc = downstream->get_block_allocator(); 3002c593315Sopenharmony_ci 3012c593315Sopenharmony_ci auto keys = mrb_hash_keys(mrb, hash); 3022c593315Sopenharmony_ci auto keyslen = RARRAY_LEN(keys); 3032c593315Sopenharmony_ci 3042c593315Sopenharmony_ci for (int i = 0; i < keyslen; ++i) { 3052c593315Sopenharmony_ci auto key = mrb_ary_ref(mrb, keys, i); 3062c593315Sopenharmony_ci if (!mrb_string_p(key)) { 3072c593315Sopenharmony_ci mrb_raise(mrb, E_RUNTIME_ERROR, "key must be string"); 3082c593315Sopenharmony_ci } 3092c593315Sopenharmony_ci 3102c593315Sopenharmony_ci auto values = mrb_hash_get(mrb, hash, key); 3112c593315Sopenharmony_ci 3122c593315Sopenharmony_ci auto ai = mrb_gc_arena_save(mrb); 3132c593315Sopenharmony_ci 3142c593315Sopenharmony_ci key = mrb_funcall(mrb, key, "downcase", 0); 3152c593315Sopenharmony_ci 3162c593315Sopenharmony_ci auto keyref = make_string_ref( 3172c593315Sopenharmony_ci balloc, 3182c593315Sopenharmony_ci StringRef{RSTRING_PTR(key), static_cast<size_t>(RSTRING_LEN(key))}); 3192c593315Sopenharmony_ci 3202c593315Sopenharmony_ci mrb_gc_arena_restore(mrb, ai); 3212c593315Sopenharmony_ci 3222c593315Sopenharmony_ci auto token = http2::lookup_token(keyref.byte(), keyref.size()); 3232c593315Sopenharmony_ci 3242c593315Sopenharmony_ci if (mrb_array_p(values)) { 3252c593315Sopenharmony_ci auto n = RARRAY_LEN(values); 3262c593315Sopenharmony_ci for (int i = 0; i < n; ++i) { 3272c593315Sopenharmony_ci auto value = mrb_ary_ref(mrb, values, i); 3282c593315Sopenharmony_ci if (!mrb_string_p(value)) { 3292c593315Sopenharmony_ci mrb_raise(mrb, E_RUNTIME_ERROR, "value must be string"); 3302c593315Sopenharmony_ci } 3312c593315Sopenharmony_ci 3322c593315Sopenharmony_ci resp.fs.add_header_token( 3332c593315Sopenharmony_ci keyref, 3342c593315Sopenharmony_ci make_string_ref(balloc, 3352c593315Sopenharmony_ci StringRef{RSTRING_PTR(value), 3362c593315Sopenharmony_ci static_cast<size_t>(RSTRING_LEN(value))}), 3372c593315Sopenharmony_ci false, token); 3382c593315Sopenharmony_ci } 3392c593315Sopenharmony_ci } else if (mrb_string_p(values)) { 3402c593315Sopenharmony_ci resp.fs.add_header_token( 3412c593315Sopenharmony_ci keyref, 3422c593315Sopenharmony_ci make_string_ref(balloc, 3432c593315Sopenharmony_ci StringRef{RSTRING_PTR(values), 3442c593315Sopenharmony_ci static_cast<size_t>(RSTRING_LEN(values))}), 3452c593315Sopenharmony_ci false, token); 3462c593315Sopenharmony_ci } else { 3472c593315Sopenharmony_ci mrb_raise(mrb, E_RUNTIME_ERROR, "value must be string"); 3482c593315Sopenharmony_ci } 3492c593315Sopenharmony_ci } 3502c593315Sopenharmony_ci 3512c593315Sopenharmony_ci resp.http_status = http_status; 3522c593315Sopenharmony_ci 3532c593315Sopenharmony_ci auto upstream = downstream->get_upstream(); 3542c593315Sopenharmony_ci 3552c593315Sopenharmony_ci rv = upstream->on_downstream_header_complete(downstream); 3562c593315Sopenharmony_ci if (rv != 0) { 3572c593315Sopenharmony_ci mrb_raise(mrb, E_RUNTIME_ERROR, "could not send non-final response"); 3582c593315Sopenharmony_ci } 3592c593315Sopenharmony_ci 3602c593315Sopenharmony_ci auto handler = upstream->get_client_handler(); 3612c593315Sopenharmony_ci 3622c593315Sopenharmony_ci handler->signal_write(); 3632c593315Sopenharmony_ci 3642c593315Sopenharmony_ci return self; 3652c593315Sopenharmony_ci} 3662c593315Sopenharmony_ci} // namespace 3672c593315Sopenharmony_ci 3682c593315Sopenharmony_civoid init_response_class(mrb_state *mrb, RClass *module) { 3692c593315Sopenharmony_ci auto response_class = 3702c593315Sopenharmony_ci mrb_define_class_under(mrb, module, "Response", mrb->object_class); 3712c593315Sopenharmony_ci 3722c593315Sopenharmony_ci mrb_define_method(mrb, response_class, "initialize", response_init, 3732c593315Sopenharmony_ci MRB_ARGS_NONE()); 3742c593315Sopenharmony_ci mrb_define_method(mrb, response_class, "http_version_major", 3752c593315Sopenharmony_ci response_get_http_version_major, MRB_ARGS_NONE()); 3762c593315Sopenharmony_ci mrb_define_method(mrb, response_class, "http_version_minor", 3772c593315Sopenharmony_ci response_get_http_version_minor, MRB_ARGS_NONE()); 3782c593315Sopenharmony_ci mrb_define_method(mrb, response_class, "status", response_get_status, 3792c593315Sopenharmony_ci MRB_ARGS_NONE()); 3802c593315Sopenharmony_ci mrb_define_method(mrb, response_class, "status=", response_set_status, 3812c593315Sopenharmony_ci MRB_ARGS_REQ(1)); 3822c593315Sopenharmony_ci mrb_define_method(mrb, response_class, "headers", response_get_headers, 3832c593315Sopenharmony_ci MRB_ARGS_NONE()); 3842c593315Sopenharmony_ci mrb_define_method(mrb, response_class, "add_header", response_add_header, 3852c593315Sopenharmony_ci MRB_ARGS_REQ(2)); 3862c593315Sopenharmony_ci mrb_define_method(mrb, response_class, "set_header", response_set_header, 3872c593315Sopenharmony_ci MRB_ARGS_REQ(2)); 3882c593315Sopenharmony_ci mrb_define_method(mrb, response_class, "clear_headers", 3892c593315Sopenharmony_ci response_clear_headers, MRB_ARGS_NONE()); 3902c593315Sopenharmony_ci mrb_define_method(mrb, response_class, "return", response_return, 3912c593315Sopenharmony_ci MRB_ARGS_OPT(1)); 3922c593315Sopenharmony_ci mrb_define_method(mrb, response_class, "send_info", response_send_info, 3932c593315Sopenharmony_ci MRB_ARGS_REQ(2)); 3942c593315Sopenharmony_ci} 3952c593315Sopenharmony_ci 3962c593315Sopenharmony_ci} // namespace mruby 3972c593315Sopenharmony_ci 3982c593315Sopenharmony_ci} // namespace shrpx 399